[rhq] modules/core modules/enterprise modules/plugins
by snegrea
modules/core/native-system/src/main/java/org/rhq/core/system/SigarAccess.java | 2
modules/core/native-system/src/main/java/org/rhq/core/system/SystemInfoFactory.java | 53 ++++------
modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java | 7 -
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/promptcmd/NativePromptCommand.java | 16 +--
modules/plugins/lsof/src/main/java/org/rhq/plugins/lsof/LsofDiscoveryComponent.java | 8 -
5 files changed, 43 insertions(+), 43 deletions(-)
New commits:
commit cb654429a9c0d0d30092a21740da5e1d4e614be2
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Oct 31 10:47:24 2012 -0500
[BZ 869730] Move static block of code that was checking for Sigar availability to a static method to be able to use correctly at startup both system properties and stored agent preferences. This change will avoid attempts to load the Sigar library even if --nonative flag or rhq.agent.disable-native-system property are set to true.
Before this change the static initializer would probe the sigar library as soon as the SystemInfoFactory class was loaded even if not used later by the agent (native system disabled). This was causing the entire JVM to crash on some systems and could not be prevented even with --nonative.
diff --git a/modules/core/native-system/src/main/java/org/rhq/core/system/SigarAccess.java b/modules/core/native-system/src/main/java/org/rhq/core/system/SigarAccess.java
index f28d92d..ee98a09 100644
--- a/modules/core/native-system/src/main/java/org/rhq/core/system/SigarAccess.java
+++ b/modules/core/native-system/src/main/java/org/rhq/core/system/SigarAccess.java
@@ -69,7 +69,7 @@ public class SigarAccess {
}
public static boolean isSigarAvailable() {
- if (SystemInfoFactory.isNativeSystemInfoAvailable() && !SystemInfoFactory.isNativeSystemInfoDisabled()) {
+ if (!SystemInfoFactory.isNativeSystemInfoDisabled() && SystemInfoFactory.isNativeSystemInfoAvailable()) {
// its available, but it may not yet have been initialized. If it has not been initialized,
// make a call that forces it to be initialized and loaded. 99% of the time, the native layer
// will already be initialized and this check will be very fast.
diff --git a/modules/core/native-system/src/main/java/org/rhq/core/system/SystemInfoFactory.java b/modules/core/native-system/src/main/java/org/rhq/core/system/SystemInfoFactory.java
index 8d9e05d..df35169 100644
--- a/modules/core/native-system/src/main/java/org/rhq/core/system/SystemInfoFactory.java
+++ b/modules/core/native-system/src/main/java/org/rhq/core/system/SystemInfoFactory.java
@@ -70,30 +70,6 @@ public class SystemInfoFactory {
load, VERSION_STRING, BUILD_DATE, NATIVE_VERSION_STRING, NATIVE_BUILD_DATE
}
- static {
- try {
- Class<?> clazz = Class.forName(NATIVE_LIBRARY_CLASS_NAME);
-
- nativeApis.put(NativeApi.load, clazz.getMethod(NativeApi.load.name(), new Class[0]));
- nativeApis.put(NativeApi.VERSION_STRING, clazz.getField(NativeApi.VERSION_STRING.name()));
- nativeApis.put(NativeApi.BUILD_DATE, clazz.getField(NativeApi.BUILD_DATE.name()));
- nativeApis.put(NativeApi.NATIVE_VERSION_STRING, clazz.getField(NativeApi.NATIVE_VERSION_STRING.name()));
- nativeApis.put(NativeApi.NATIVE_BUILD_DATE, clazz.getField(NativeApi.NATIVE_BUILD_DATE.name()));
-
- invokeApi(NativeApi.load);
-
- nativeLibraryLoadable = true;
- } catch (Throwable t) {
- // We don't have the JNI classes (sigar.jar) and/or the native shared library (e.g. libsigar-amd64-linux.so).
- // This might be expected (e.g. the admin console WAR (Embedded Jopr) does not include SIGAR), so don't log
- // anything, but store the Throwable, so callers can log the cause when appropriate.
- nativeLibraryLoadable = false;
- nativeLibraryLoadThrowable = t;
- }
-
- disabled = !nativeLibraryLoadable; // automatically disable native system info iff the native library is not loadable
- }
-
/**
* If the native system is both {@link #isNativeSystemInfoAvailable() available} and
* {@link #isNativeSystemInfoDisabled() enabled}, this will return the native system's version string. Otherwise, a
@@ -107,7 +83,7 @@ public class SystemInfoFactory {
initialize(); // make sure we've loaded the native libraries, if appropriate
- if (isNativeSystemInfoAvailable() && !isNativeSystemInfoDisabled()) {
+ if (!isNativeSystemInfoDisabled() && isNativeSystemInfoAvailable()) {
try {
version = "Version=" + invokeApi(NativeApi.VERSION_STRING) + " (" + invokeApi(NativeApi.BUILD_DATE)
+ "); Native version=" + invokeApi(NativeApi.NATIVE_VERSION_STRING) + " ("
@@ -173,6 +149,8 @@ public class SystemInfoFactory {
* @see JavaSystemInfo
*/
public static boolean isNativeSystemInfoAvailable() {
+ initialize();
+
return nativeLibraryLoadable;
}
@@ -213,7 +191,7 @@ public class SystemInfoFactory {
SystemInfo nativePlatform = null;
- if (isNativeSystemInfoAvailable() && !isNativeSystemInfoDisabled()) {
+ if (!isNativeSystemInfoDisabled() && isNativeSystemInfoAvailable()) {
// we could use SIGAR here, but this should be enough
if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1) {
nativePlatform = new WindowsNativeSystemInfo();
@@ -276,15 +254,32 @@ public class SystemInfoFactory {
*/
private static synchronized void initialize() {
if (!initialized) {
- if (isNativeSystemInfoAvailable() && !isNativeSystemInfoDisabled()) {
+ if (!isNativeSystemInfoDisabled()) {
try {
+ Class<?> clazz = Class.forName(NATIVE_LIBRARY_CLASS_NAME);
+
+ nativeApis.put(NativeApi.load, clazz.getMethod(NativeApi.load.name(), new Class[0]));
+ nativeApis.put(NativeApi.VERSION_STRING, clazz.getField(NativeApi.VERSION_STRING.name()));
+ nativeApis.put(NativeApi.BUILD_DATE, clazz.getField(NativeApi.BUILD_DATE.name()));
+ nativeApis.put(NativeApi.NATIVE_VERSION_STRING, clazz.getField(NativeApi.NATIVE_VERSION_STRING.name()));
+ nativeApis.put(NativeApi.NATIVE_BUILD_DATE, clazz.getField(NativeApi.NATIVE_BUILD_DATE.name()));
+
invokeApi(NativeApi.load);
+
+ nativeLibraryLoadable = true;
+
initialized = true; // we only set this to true when we actually initialized the native layer
} catch (Throwable t) {
+ // We don't have the JNI classes (sigar.jar) and/or the native shared library (e.g. libsigar-amd64-linux.so).
+ // This might be expected (e.g. the admin console WAR (Embedded Jopr) does not include SIGAR), so don't log
+ // anything, but store the Throwable, so callers can log the cause when appropriate.
+ nativeLibraryLoadable = false;
+ nativeLibraryLoadThrowable = t;
+
LOG.warn("Native library not available on this platform: " + ThrowableUtil.getAllMessages(t));
LOG.debug("Native library failure stack trace follows: ", t);
- nativeLibraryLoadable = false;
- disabled = true;
+
+ disabled = true; // automatically disable native system info if the native library is not loadable
}
}
}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java
index 730effc..46e72bd 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java
@@ -431,9 +431,12 @@ public class StandaloneContainer {
SystemInfoFactory.disableNativeSystemInfo();
System.out.println("Native layer disabled.");
} else if (what.startsWith("s")) {
- System.out.println(SystemInfoFactory.isNativeSystemInfoAvailable() ? "Available" : "Not Available");
+ System.out.println("Native layer is:");
System.out.println(SystemInfoFactory.isNativeSystemInfoDisabled() ? "Disabled" : "Enabled");
- System.out.println(SystemInfoFactory.isNativeSystemInfoInitialized() ? "Initialized" : "Not initialized");
+ if (!SystemInfoFactory.isNativeSystemInfoDisabled()) {
+ System.out.println(SystemInfoFactory.isNativeSystemInfoAvailable() ? "Available" : "Not Available");
+ System.out.println(SystemInfoFactory.isNativeSystemInfoInitialized() ? "Initialized" : "Not initialized");
+ }
} else {
System.err.println("Unknown option. Only 'e', 'd' and 's' are applicable (enable/disable/status)");
return;
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/promptcmd/NativePromptCommand.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/promptcmd/NativePromptCommand.java
index 5ef242f..9ebf4b5 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/promptcmd/NativePromptCommand.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/promptcmd/NativePromptCommand.java
@@ -54,16 +54,18 @@ public class NativePromptCommand implements AgentPromptCommand {
if (args.length <= 1) {
out.println(MSG
- .getMsg(SystemInfoFactory.isNativeSystemInfoAvailable() ? AgentI18NResourceKeys.NATIVE_IS_AVAILABLE
- : AgentI18NResourceKeys.NATIVE_IS_NOT_AVAILABLE));
-
- out.println(MSG
.getMsg(SystemInfoFactory.isNativeSystemInfoDisabled() ? AgentI18NResourceKeys.NATIVE_IS_DISABLED
: AgentI18NResourceKeys.NATIVE_IS_NOT_DISABLED));
- out.println(MSG
- .getMsg(SystemInfoFactory.isNativeSystemInfoInitialized() ? AgentI18NResourceKeys.NATIVE_IS_INITIALIZED
- : AgentI18NResourceKeys.NATIVE_IS_NOT_INITIALIZED));
+ if (!SystemInfoFactory.isNativeSystemInfoDisabled()) {
+ out.println(MSG
+ .getMsg(SystemInfoFactory.isNativeSystemInfoAvailable() ? AgentI18NResourceKeys.NATIVE_IS_AVAILABLE
+ : AgentI18NResourceKeys.NATIVE_IS_NOT_AVAILABLE));
+
+ out.println(MSG
+ .getMsg(SystemInfoFactory.isNativeSystemInfoInitialized() ? AgentI18NResourceKeys.NATIVE_IS_INITIALIZED
+ : AgentI18NResourceKeys.NATIVE_IS_NOT_INITIALIZED));
+ }
return true;
}
diff --git a/modules/plugins/lsof/src/main/java/org/rhq/plugins/lsof/LsofDiscoveryComponent.java b/modules/plugins/lsof/src/main/java/org/rhq/plugins/lsof/LsofDiscoveryComponent.java
index a5bfe31..22820a9 100644
--- a/modules/plugins/lsof/src/main/java/org/rhq/plugins/lsof/LsofDiscoveryComponent.java
+++ b/modules/plugins/lsof/src/main/java/org/rhq/plugins/lsof/LsofDiscoveryComponent.java
@@ -53,14 +53,14 @@ public class LsofDiscoveryComponent extends ScriptDiscoveryComponent {
switch (detectionMechanism) {
case INTERNAL:
- if (!SystemInfoFactory.isNativeSystemInfoAvailable()) {
- throw new InvalidPluginConfigurationException(
- "The native system is not available - cannot use the internal detection mechanism");
- }
if (SystemInfoFactory.isNativeSystemInfoDisabled()) {
throw new InvalidPluginConfigurationException(
"The native system is disabled - cannot use the internal detection mechanism");
}
+ if (!SystemInfoFactory.isNativeSystemInfoAvailable()) {
+ throw new InvalidPluginConfigurationException(
+ "The native system is not available - cannot use the internal detection mechanism");
+ }
String version = LsofComponent.VERSION;
details = new DiscoveredResourceDetails(discoveryContext.getResourceType(), "*lsof-internal*",
DEFAULT_NAME, version, DEFAULT_DESCRIPTION, pluginConfig, null);
11 years, 6 months
[rhq] modules/enterprise
by Jiri Kremser
modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
New commits:
commit 1402590305df51642f83c7efe63340c62b354d83
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Wed Oct 31 14:21:17 2012 +0100
[BZ 871407 - NPE on auto completion for javascript object] the contextComplete() method now returns -1 instead of throwing NPE
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
index d4d68bc..78d3c9a 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
@@ -182,7 +182,12 @@ public class JavascriptCompletor implements CodeCompletion {
Map<String, List<Object>> matches = getContextMatches(output, baseObject, next);
if (!matches.isEmpty()) {
- Object rootObject = matches.get(next).get(0);
+ // BZ 871407 NPE on auto completion for javascript object
+ List<Object> nextList = matches.get(next);
+ if (nextList == null || nextList.isEmpty()) {
+ return -1;
+ }
+ Object rootObject = nextList.get(0);
if (rootObject instanceof PropertyDescriptor && !(baseObject instanceof Class)) {
try {
rootObject = invoke(baseObject, ((PropertyDescriptor) rootObject).getReadMethod());
11 years, 6 months
[rhq] Branch 'lkrejci/code-coverage' - modules/integration-tests modules/pom.xml
by lkrejci
modules/integration-tests/pom.xml | 27 +++++++++++++++++++++------
modules/pom.xml | 17 +++++++++++++++++
2 files changed, 38 insertions(+), 6 deletions(-)
New commits:
commit 7afe389bce54ace3d460ea9e13245bc7689747a9
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Oct 31 13:05:04 2012 +0100
Build everything including all the integration tests in the code-coverage
profile.
Clean up the integration-tests pom. The jbos-as-7-plugin-test no longer exists.
diff --git a/modules/integration-tests/pom.xml b/modules/integration-tests/pom.xml
index 982dfca..9678b15 100644
--- a/modules/integration-tests/pom.xml
+++ b/modules/integration-tests/pom.xml
@@ -60,19 +60,34 @@
<profiles>
<profile>
<id>integration-tests</id>
+ <activation>
+ <property>
+ <name>integration.tests</name>
+ </property>
+ </activation>
+
<modules>
<module>apache-plugin-test</module>
<module>jndi-access</module>
<!--<module>mod_cluster-plugin-test</module>-->
+ <!--<module>rest-api</module>-->
</modules>
</profile>
+
<profile>
- <id>as7-integration-test</id>
- <!-- this one is separate from others, requires special setup -->
- <modules>
- <module>jboss-as-7-plugin-test</module>
- </modules>
- </profile>
+ <id>code-coverage</id>
+ <activation>
+ <property>
+ <name>code-coverage</name>
+ </property>
+ </activation>
+ <modules>
+ <module>apache-plugin-test</module>
+ <module>jndi-access</module>
+ <!--<module>mod_cluster-plugin-test</module>-->
+ <!--<module>rest-api</module>-->
+ </modules>
+ </profile>
</profiles>
diff --git a/modules/pom.xml b/modules/pom.xml
index c2c5087..e40d89a 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -176,6 +176,23 @@
<module>integration-tests</module>
</modules>
</profile>
+
+ <profile>
+ <id>code-coverage</id>
+ <activation>
+ <property>
+ <name>code-coverage</name>
+ </property>
+ </activation>
+ <modules>
+ <module>core</module>
+ <module>common</module>
+ <module>plugins</module>
+ <module>helpers</module>
+ <module>enterprise</module>
+ <module>integration-tests</module>
+ </modules>
+ </profile>
</profiles>
</project>
11 years, 6 months
[rhq] Branch 'jsanda/cassandra-plugin' - 2 commits - modules/enterprise modules/plugins
by snegrea
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java | 17
modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/FailureDetectorComponent.java | 43 +
modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml | 355 +++++++---
3 files changed, 318 insertions(+), 97 deletions(-)
New commits:
commit 8c214b8754b319b0549f28703d38335625528cd7
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Oct 30 17:18:14 2012 -0500
Add the last set of exposed management interfaces to the resource descriptor.
Also, moved all the resources to groups based on management function.
diff --git a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/FailureDetectorComponent.java b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/FailureDetectorComponent.java
new file mode 100644
index 0000000..38d0149
--- /dev/null
+++ b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/FailureDetectorComponent.java
@@ -0,0 +1,43 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2011, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.cassandra;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
+import org.rhq.plugins.jmx.JMXComponent;
+import org.rhq.plugins.jmx.MBeanResourceComponent;
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public class FailureDetectorComponent extends MBeanResourceComponent<JMXComponent<?>> {
+
+ @Override
+ public Configuration loadResourceConfiguration() {
+ return super.loadResourceConfiguration();
+ }
+
+ @Override
+ public void updateResourceConfiguration(ConfigurationUpdateReport report) {
+ super.updateResourceConfiguration(report);
+ }
+}
diff --git a/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
index bc115d3..73ed5a6 100644
--- a/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
@@ -29,7 +29,9 @@
<subcategories>
<subcategory name="Client Request Metrics" description="Client Request Metrics"/>
<subcategory name="Server Request Metrics" description="Server Request Metrics"/>
- <subcategory name="Internal Server Metrics" description="Server Request Metrics"/>
+ <subcategory name="Internal Server Metrics" description="Internal Server Metrics"/>
+ <subcategory name="Database Management Services" description="Database Management Services"/>
+ <subcategory name="Network Services" description="Network Services"/>
</subcategories>
<plugin-configuration>
@@ -82,7 +84,8 @@
<service name="StorageProxy"
discovery="org.rhq.plugins.jmx.MBeanResourceDiscoveryComponent"
class="org.rhq.plugins.jmx.MBeanResourceComponent"
- singleton="true">
+ singleton="true"
+ subCategory="Database Management Services">
<plugin-configuration>
<c:simple-property name="objectName" readOnly="true" default="org.apache.cassandra.db:type=StorageProxy"/>
@@ -112,7 +115,8 @@
<service name="StorageService"
discovery="org.rhq.plugins.jmx.MBeanResourceDiscoveryComponent"
class="org.rhq.plugins.cassandra.StorageServiceComponent"
- singleton="true">
+ singleton="true"
+ subCategory="Database Management Services">
<plugin-configuration>
<c:simple-property name="objectName" readOnly="true" default="org.apache.cassandra.db:type=StorageService"/>
@@ -175,7 +179,8 @@
<service name="CommitLog"
discovery="org.rhq.plugins.jmx.MBeanResourceDiscoveryComponent"
class="org.rhq.plugins.jmx.MBeanResourceComponent"
- singleton="true">
+ singleton="true"
+ subCategory="Database Management Services">
<plugin-configuration>
<c:simple-property name="objectName" readOnly="true" type="string" default="org.apache.cassandra.db:type=Commitlog"/>
@@ -240,7 +245,8 @@
<service name="CompactionManager"
discovery="org.rhq.plugins.jmx.MBeanResourceDiscoveryComponent"
class="org.rhq.plugins.jmx.MBeanResourceComponent"
- singleton="true">
+ singleton="true"
+ subCategory="Database Management Services">
<plugin-configuration>
<c:simple-property name="objectName" readOnly="true" type="string" default="org.apache.cassandra.db:type=CompactionManager"/>
@@ -271,7 +277,8 @@
<service name="CacheService"
discovery="org.rhq.plugins.jmx.MBeanResourceDiscoveryComponent"
class="org.rhq.plugins.jmx.MBeanResourceComponent"
- singleton="true">
+ singleton="true"
+ subCategory="Database Management Services">
<plugin-configuration>
<c:simple-property name="objectName" readOnly="true" type="string" default="org.apache.cassandra.db:type=Caches"/>
@@ -307,6 +314,255 @@
</service>
+ <service name="ConfigurableStages"
+ discovery="org.rhq.plugins.cassandra.MetricsDiscoveryComponent"
+ class="org.rhq.plugins.jmx.MBeanResourceComponent"
+ singleton="true"
+ subCategory="Server Request Metrics">
+
+ <plugin-configuration>
+ <c:simple-property name="objectName" readOnly="true" type="string"
+ default="org.apache.cassandra.request:type=MutationStage|org.apache.cassandra.request:type=ReadStage|org.apache.cassandra.request:type=ReplicateOnWriteStage"/>
+ <c:simple-property name="nameMarker" readOnly="true" type="string" default="type=" />
+ </plugin-configuration>
+
+ <metric property="ActiveCount" measurementType="dynamic" displayType="summary" description="Active Count"/>
+ <metric property="CurrentlyBlockedTasks" measurementType="dynamic" displayType="summary" description="Currently Blocked Tasks"/>
+ <metric property="CompletedTasks" measurementType="dynamic" displayType="summary" description="Completed Tasks"/>
+ <metric property="PendingTasks" measurementType="dynamic" displayType="summary" description="Pending Tasks"/>
+ <metric property="TotalBlockedTasks" measurementType="dynamic" displayType="summary" description="Total Blocked Tasks"/>
+
+ <resource-configuration>
+ <c:simple-property name="CorePoolSize" type="integer" required="true" description="Core Pool Size."/>
+ </resource-configuration>
+ </service>
+
+ <service name="EnabledStages"
+ discovery="org.rhq.plugins.cassandra.MetricsDiscoveryComponent"
+ class="org.rhq.plugins.jmx.MBeanResourceComponent"
+ singleton="true"
+ subCategory="Server Request Metrics">
+
+ <plugin-configuration>
+ <c:simple-property name="objectName" readOnly="true" type="string"
+ default="org.apache.cassandra.request:type=ReadRepairStage|org.apache.cassandra.request:type=RequestResponseStage"/>
+ <c:simple-property name="nameMarker" readOnly="true" type="string" default="type=" />
+ </plugin-configuration>
+
+ <metric property="ActiveCount" measurementType="dynamic" displayType="summary" description="Active Count"/>
+ <metric property="CurrentlyBlockedTasks" measurementType="dynamic" displayType="summary" description="Currently Blocked Tasks"/>
+ <metric property="CompletedTasks" measurementType="dynamic" displayType="summary" description="Completed Tasks"/>
+ <metric property="PendingTasks" measurementType="dynamic" displayType="summary" description="Pending Tasks"/>
+ <metric property="TotalBlockedTasks" measurementType="dynamic" displayType="summary" description="Total Blocked Tasks"/>
+ </service>
+
+ <service name="ConfigurableInternalServerMetrics"
+ discovery="org.rhq.plugins.cassandra.MetricsDiscoveryComponent"
+ class="org.rhq.plugins.jmx.MBeanResourceComponent"
+ singleton="true"
+ subCategory="Internal Server Metrics">
+
+ <plugin-configuration>
+ <c:simple-property name="objectName" readOnly="true" type="string"
+ default="org.apache.cassandra.internal:type=AntiEntropySessions"/>
+ <c:simple-property name="nameMarker" readOnly="true" type="string" default="type=" />
+ </plugin-configuration>
+
+ <metric property="ActiveCount" measurementType="dynamic" displayType="summary" description="Active Count"/>
+ <metric property="CurrentlyBlockedTasks" measurementType="dynamic" displayType="summary" description="Currently Blocked Tasks"/>
+ <metric property="CompletedTasks" measurementType="dynamic" displayType="summary" description="Completed Tasks"/>
+ <metric property="PendingTasks" measurementType="dynamic" displayType="summary" description="Pending Tasks"/>
+ <metric property="TotalBlockedTasks" measurementType="dynamic" displayType="summary" description="Total Blocked Tasks"/>
+
+ <resource-configuration>
+ <c:simple-property name="CorePoolSize" type="integer" required="true" description="Core Pool Size."/>
+ </resource-configuration>
+ </service>
+
+ <service name="EnabledInternalServerMetrics"
+ discovery="org.rhq.plugins.cassandra.MetricsDiscoveryComponent"
+ class="org.rhq.plugins.jmx.MBeanResourceComponent"
+ singleton="true"
+ subCategory="Internal Server Metrics">
+
+ <plugin-configuration>
+ <c:simple-property name="objectName" readOnly="true" type="string"
+ default="org.apache.cassandra.internal:type=AntiEntropyStage|org.apache.cassandra.internal:type=FlushWriter|org.apache.cassandra.internal:type=GossipStage|org.apache.cassandra.internal:type=HintedHandoff|org.apache.cassandra.internal:type=InternalResponseStage|org.apache.cassandra.internal:type=MemtablePostFlusher|org.apache.cassandra.internal:type=MigrationStage|org.apache.cassandra.internal:type=MiscStage|org.apache.cassandra.internal:type=StreamStage|org.apache.cassandra.internal:type=commitlog_archiver"/>
+ <c:simple-property name="nameMarker" readOnly="true" type="string" default="type=" />
+ </plugin-configuration>
+
+ <metric property="ActiveCount" measurementType="dynamic" displayType="summary" description="Active Count"/>
+ <metric property="CurrentlyBlockedTasks" measurementType="dynamic" displayType="summary" description="Currently Blocked Tasks"/>
+ <metric property="CompletedTasks" measurementType="dynamic" displayType="summary" description="Completed Tasks"/>
+ <metric property="PendingTasks" measurementType="dynamic" displayType="summary" description="Pending Tasks"/>
+ <metric property="TotalBlockedTasks" measurementType="dynamic" displayType="summary" description="Total Blocked Tasks"/>
+ </service>
+
+
+ <service name="FailureDetector"
+ discovery="org.rhq.plugins.jmx.MBeanResourceDiscoveryComponent"
+ class="org.rhq.plugins.cassandra.FailureDetectorComponent"
+ singleton="true"
+ subCategory="Network Services">
+
+ <plugin-configuration>
+ <c:simple-property name="objectName" readOnly="true" type="string" default="org.apache.cassandra.net:type=FailureDetector"/>
+ <c:simple-property name="nameTemplate" readOnly="true" type="string" default="Failure Detector" />
+ </plugin-configuration>
+
+ <resource-configuration>
+ <c:simple-property name="PhiConvictThreshold" type="integer" required="true" description="Phi-convict threshold sets the sensitivity of the failure detector. Lower values increase the likelihood that an unresponsive node will be marked as down, while higher values decrease the likelihood."/>
+ <c:simple-property name="AllEndpointStates" type="integer" required="false" readOnly="true" description="States of all the end-points."/>
+ <c:list-property name="SimpleStates" readOnly="true">
+ <c:map-property name="SimpleState" readOnly="true">
+ <c:simple-property name="name" type="string" readOnly="true"/>
+ <c:simple-property name="value" type="string" readOnly="true"/>
+ </c:map-property>
+ </c:list-property>
+ </resource-configuration>
+ </service>
+
+
+ <service name="Gossiper"
+ discovery="org.rhq.plugins.jmx.MBeanResourceDiscoveryComponent"
+ class="org.rhq.plugins.jmx.MBeanResourceComponent"
+ singleton="true"
+ subCategory="Network Services">
+
+ <plugin-configuration>
+ <c:simple-property name="objectName" readOnly="true" type="string" default="org.apache.cassandra.net:type=Gossiper"/>
+ <c:simple-property name="nameTemplate" readOnly="true" type="string" default="Gossiper" />
+ </plugin-configuration>
+
+ <operation name="getVersion" description="Get version">
+ <parameters>
+ <c:simple-property name="p1" displayName="Address" required="true" type="string" description="Address"/>
+ </parameters>
+ <results>
+ <c:simple-property name="operationResult" description="Version"/>
+ </results>
+ </operation>
+ <operation name="getCurrentGenerationNumber" description="Get current generation number">
+ <parameters>
+ <c:simple-property name="p1" displayName="Address" required="true" type="string" description="Address"/>
+ </parameters>
+ <results>
+ <c:simple-property name="operationResult" description="Current Generation Number"/>
+ </results>
+ </operation>
+ <operation name="getEndpointDowntime" description="Get endpoint downtime">
+ <parameters>
+ <c:simple-property name="p1" displayName="Address" required="true" type="string" description="Address"/>
+ </parameters>
+ <results>
+ <c:simple-property name="operationResult" description="Endpoint Downtime"/>
+ </results>
+ </operation>
+ <operation name="unsafeAssassinateEndpoint" description="Unsafe assassinate endpoint">
+ <parameters>
+ <c:simple-property name="p1" displayName="Address" required="true" type="string" description="Address"/>
+ </parameters>
+ </operation>
+ </service>
+
+ <service name="StreamingService"
+ discovery="org.rhq.plugins.jmx.MBeanResourceDiscoveryComponent"
+ class="org.rhq.plugins.jmx.MBeanResourceComponent"
+ singleton="true"
+ subCategory="Network Services">
+
+ <plugin-configuration>
+ <c:simple-property name="objectName" readOnly="true" type="string" default="org.apache.cassandra.net:type=StreamingService"/>
+ <c:simple-property name="nameTemplate" readOnly="true" type="string" default="Streaming Service" />
+ </plugin-configuration>
+
+ <resource-configuration>
+ <c:simple-property name="Status" type="string" required="false" readOnly="true" description="Status"/>
+ <c:list-property name="StreamDestinations" readOnly="true">
+ <c:map-property name="StreamDestination" readOnly="true">
+ <c:simple-property name="name" type="string" readOnly="true"/>
+ <c:simple-property name="value" type="string" readOnly="true"/>
+ </c:map-property>
+ </c:list-property>
+ <c:list-property name="StreamSources" readOnly="true">
+ <c:map-property name="StreamSource" readOnly="true">
+ <c:simple-property name="name" type="string" readOnly="true"/>
+ <c:simple-property name="value" type="string" readOnly="true"/>
+ </c:map-property>
+ </c:list-property>
+ </resource-configuration>
+ </service>
+
+ <service name="MessagingService"
+ discovery="org.rhq.plugins.jmx.MBeanResourceDiscoveryComponent"
+ class="org.rhq.plugins.jmx.MBeanResourceComponent"
+ singleton="true"
+ subCategory="Network Services">
+
+ <plugin-configuration>
+ <c:simple-property name="objectName" readOnly="true" default="org.apache.cassandra.net:type=MessagingService"/>
+ <c:simple-property name="nameTemplate" readOnly="true" type="string" default="Messaging Service"/>
+ </plugin-configuration>
+
+ <metric property="TotalTimeouts" measurementType="trendsup" displayType="detail" description="Total timeouts."/>
+ <metric property="RecentTotalTimeouts" measurementType="trendsup" displayType="detail" description="Recent total timeouts."/>
+
+ <resource-configuration>
+ <c:list-property name="CommandPendingTasks" readOnly="true">
+ <c:map-property name="CommandPendingTask" readOnly="true">
+ <c:simple-property name="name" type="string" readOnly="true"/>
+ <c:simple-property name="value" type="string" readOnly="true"/>
+ </c:map-property>
+ </c:list-property>
+ <c:list-property name="CommandCompletedTasks" readOnly="true">
+ <c:map-property name="CommandCompletedTask" readOnly="true">
+ <c:simple-property name="name" type="string" readOnly="true"/>
+ <c:simple-property name="value" type="string" readOnly="true"/>
+ </c:map-property>
+ </c:list-property>
+
+ <c:list-property name="ResponsePendingTasks" readOnly="true">
+ <c:map-property name="ResponsePendingTask" readOnly="true">
+ <c:simple-property name="name" type="string" readOnly="true"/>
+ <c:simple-property name="value" type="string" readOnly="true"/>
+ </c:map-property>
+ </c:list-property>
+ <c:list-property name="ResponseCompletedTasks" readOnly="true">
+ <c:map-property name="ResponseCompletedTask" readOnly="true">
+ <c:simple-property name="name" type="string" readOnly="true"/>
+ <c:simple-property name="value" type="string" readOnly="true"/>
+ </c:map-property>
+ </c:list-property>
+
+ <c:list-property name="DroppedMessages" readOnly="true">
+ <c:map-property name="DroppedMessage" readOnly="true">
+ <c:simple-property name="name" type="string" readOnly="true"/>
+ <c:simple-property name="value" type="string" readOnly="true"/>
+ </c:map-property>
+ </c:list-property>
+ <c:list-property name="RecentlyDroppedMessages" readOnly="true">
+ <c:map-property name="RecentlyDroppedMessage" readOnly="true">
+ <c:simple-property name="name" type="string" readOnly="true"/>
+ <c:simple-property name="value" type="string" readOnly="true"/>
+ </c:map-property>
+ </c:list-property>
+
+ <c:list-property name="TimeoutsPerHost" readOnly="true">
+ <c:map-property name="TimeoutPerHost" readOnly="true">
+ <c:simple-property name="name" type="string" readOnly="true"/>
+ <c:simple-property name="value" type="string" readOnly="true"/>
+ </c:map-property>
+ </c:list-property>
+ <c:list-property name="RecentTimeoutsPerHost" readOnly="true">
+ <c:map-property name="RecentTimeoutPerHost" readOnly="true">
+ <c:simple-property name="name" type="string" readOnly="true"/>
+ <c:simple-property name="value" type="string" readOnly="true"/>
+ </c:map-property>
+ </c:list-property>
+ </resource-configuration>
+ </service>
+
+
<service name="Keyspace"
discovery="org.rhq.plugins.cassandra.KeyspaceDiscoveryComponent"
class="org.rhq.plugins.cassandra.KeyspaceComponent">
@@ -447,90 +703,5 @@
</service>
</service>
-
- <service name="ConfigurableStages"
- discovery="org.rhq.plugins.cassandra.MetricsDiscoveryComponent"
- class="org.rhq.plugins.jmx.MBeanResourceComponent"
- singleton="true"
- subCategory="Server Request Metrics">
-
- <plugin-configuration>
- <c:simple-property name="objectName" readOnly="true" type="string"
- default="org.apache.cassandra.request:type=MutationStage|org.apache.cassandra.request:type=ReadStage|org.apache.cassandra.request:type=ReplicateOnWriteStage"/>
- <c:simple-property name="nameMarker" readOnly="true" type="string" default="type=" />
- </plugin-configuration>
-
- <metric property="ActiveCount" measurementType="dynamic" displayType="summary" description="Active Count"/>
- <metric property="CurrentlyBlockedTasks" measurementType="dynamic" displayType="summary" description="Currently Blocked Tasks"/>
- <metric property="CompletedTasks" measurementType="dynamic" displayType="summary" description="Completed Tasks"/>
- <metric property="PendingTasks" measurementType="dynamic" displayType="summary" description="Pending Tasks"/>
- <metric property="TotalBlockedTasks" measurementType="dynamic" displayType="summary" description="Total Blocked Tasks"/>
-
- <resource-configuration>
- <c:simple-property name="CorePoolSize" type="integer" required="true" description="Core Pool Size."/>
- </resource-configuration>
- </service>
-
- <service name="EnabledStages"
- discovery="org.rhq.plugins.cassandra.MetricsDiscoveryComponent"
- class="org.rhq.plugins.jmx.MBeanResourceComponent"
- singleton="true"
- subCategory="Server Request Metrics">
-
- <plugin-configuration>
- <c:simple-property name="objectName" readOnly="true" type="string"
- default="org.apache.cassandra.request:type=ReadRepairStage|org.apache.cassandra.request:type=RequestResponseStage"/>
- <c:simple-property name="nameMarker" readOnly="true" type="string" default="type=" />
- </plugin-configuration>
-
- <metric property="ActiveCount" measurementType="dynamic" displayType="summary" description="Active Count"/>
- <metric property="CurrentlyBlockedTasks" measurementType="dynamic" displayType="summary" description="Currently Blocked Tasks"/>
- <metric property="CompletedTasks" measurementType="dynamic" displayType="summary" description="Completed Tasks"/>
- <metric property="PendingTasks" measurementType="dynamic" displayType="summary" description="Pending Tasks"/>
- <metric property="TotalBlockedTasks" measurementType="dynamic" displayType="summary" description="Total Blocked Tasks"/>
- </service>
-
- <service name="ConfigurableInternalServerMetrics"
- discovery="org.rhq.plugins.cassandra.MetricsDiscoveryComponent"
- class="org.rhq.plugins.jmx.MBeanResourceComponent"
- singleton="true"
- subCategory="Internal Server Metrics">
-
- <plugin-configuration>
- <c:simple-property name="objectName" readOnly="true" type="string"
- default="org.apache.cassandra.internal:type=AntiEntropySessions"/>
- <c:simple-property name="nameMarker" readOnly="true" type="string" default="type=" />
- </plugin-configuration>
-
- <metric property="ActiveCount" measurementType="dynamic" displayType="summary" description="Active Count"/>
- <metric property="CurrentlyBlockedTasks" measurementType="dynamic" displayType="summary" description="Currently Blocked Tasks"/>
- <metric property="CompletedTasks" measurementType="dynamic" displayType="summary" description="Completed Tasks"/>
- <metric property="PendingTasks" measurementType="dynamic" displayType="summary" description="Pending Tasks"/>
- <metric property="TotalBlockedTasks" measurementType="dynamic" displayType="summary" description="Total Blocked Tasks"/>
-
- <resource-configuration>
- <c:simple-property name="CorePoolSize" type="integer" required="true" description="Core Pool Size."/>
- </resource-configuration>
- </service>
-
- <service name="EnabledInternalServerMetrics"
- discovery="org.rhq.plugins.cassandra.MetricsDiscoveryComponent"
- class="org.rhq.plugins.jmx.MBeanResourceComponent"
- singleton="true"
- subCategory="Internal Server Metrics">
-
- <plugin-configuration>
- <c:simple-property name="objectName" readOnly="true" type="string"
- default="org.apache.cassandra.internal:type=AntiEntropyStage|org.apache.cassandra.internal:type=FlushWriter|org.apache.cassandra.internal:type=GossipStage|org.apache.cassandra.internal:type=HintedHandoff|org.apache.cassandra.internal:type=InternalResponseStage|org.apache.cassandra.internal:type=MemtablePostFlusher|org.apache.cassandra.internal:type=MigrationStage|org.apache.cassandra.internal:type=MiscStage|org.apache.cassandra.internal:type=StreamStage|org.apache.cassandra.internal:type=commitlog_archiver"/>
- <c:simple-property name="nameMarker" readOnly="true" type="string" default="type=" />
- </plugin-configuration>
-
- <metric property="ActiveCount" measurementType="dynamic" displayType="summary" description="Active Count"/>
- <metric property="CurrentlyBlockedTasks" measurementType="dynamic" displayType="summary" description="Currently Blocked Tasks"/>
- <metric property="CompletedTasks" measurementType="dynamic" displayType="summary" description="Completed Tasks"/>
- <metric property="PendingTasks" measurementType="dynamic" displayType="summary" description="Pending Tasks"/>
- <metric property="TotalBlockedTasks" measurementType="dynamic" displayType="summary" description="Total Blocked Tasks"/>
- </service>
-
</server>
</plugin>
\ No newline at end of file
commit 21a228322645c1a8a2ee90f3343a917d138afb3e
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Oct 30 12:18:26 2012 -0500
Update self-referencing option sources to use explicit keyword 'self'. This reduces the confusion that an implicit self reference would pose for plugin writers.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java
index b252022..bc8fff2 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java
@@ -2529,11 +2529,18 @@ public class ConfigurationManagerBean implements ConfigurationManagerLocal, Conf
String expr = expression;
if (expr.contains(":")) {
expr = expr.substring(expr.indexOf(':') + 1);
- criteria.setSearchExpression(expr);
- resources = resourceManager.findResourcesByCriteria(subject, criteria);
- } else if (resourceId >= 0) {
- resources = new ArrayList<Resource>();
- resources.add(resourceManager.getResourceById(subject, resourceId));
+
+ if (!"self".equals(expr)) {
+ criteria.setSearchExpression(expr);
+ resources = resourceManager.findResourcesByCriteria(subject, criteria);
+ } else if (resourceId >= 0) {
+ resources = new ArrayList<Resource>();
+ resources.add(resourceManager.getResourceById(subject, resourceId));
+ } else {
+ log.warn("Self reference requested but resource id is not valid."
+ + "Option source expression:" + expression);
+ return;
+ }
} else {
log.warn("Option source expression for property " + pds.getName()
+ " and target configuration contains no ':'");
diff --git a/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
index 1966ea3..bc115d3 100644
--- a/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
@@ -401,7 +401,7 @@
<operation name="restoreSnapshot" description="Restore the column family from a previously taken snapshot.">
<parameters>
<c:simple-property name="snapshotName" required="true" type="string" description="Snapshot Name">
- <c:option-source target="configuration" expression="snapshots/snapshot=name"/>
+ <c:option-source target="configuration" expression="snapshots/snapshot=name:self"/>
</c:simple-property>
</parameters>
<results>
11 years, 6 months
[rhq] Branch 'jsanda/cassandra-plugin' - modules/plugins
by snegrea
modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/JMXServerComponent.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
New commits:
commit 5be91f0479839d19bd0b776046d1d0d13eda5a6e
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Oct 30 10:24:00 2012 -0500
Mark connection and connectionProvider as volatile since they can be accesses from multiple threads at the same time. This will avoid issues where a thread will have a stale cached value of either attribute.
This important in the context of re-establishing JMX connections since it will avoid cases where a thread relies on cached values of these attributes.
diff --git a/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/JMXServerComponent.java b/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/JMXServerComponent.java
index e510c44..412096d 100644
--- a/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/JMXServerComponent.java
+++ b/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/JMXServerComponent.java
@@ -51,8 +51,8 @@ public class JMXServerComponent<T extends ResourceComponent<?>> implements JMXCo
private static final Log log = LogFactory.getLog(JMXServerComponent.class);
- private EmsConnection connection;
- private ConnectionProvider connectionProvider;
+ private volatile EmsConnection connection;
+ private volatile ConnectionProvider connectionProvider;
/**
* The context of a component that is started. Note, other classes should use #getResourceContext(), rather than
11 years, 6 months
[rhq] modules/enterprise
by Jiri Kremser
modules/enterprise/gui/installer-war/src/main/java/org/rhq/enterprise/installer/ConfigurationBean.java | 39 +++++-----
1 file changed, 20 insertions(+), 19 deletions(-)
New commits:
commit 231093c9978a9028c151894f799a87c2c6d6b17c
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Tue Oct 30 14:02:31 2012 +0100
[BZ 870533 - Server silent/autoinstall sets http and https ports to sslsocket port value] The code responsible for overriding the "rhq.server.startup.web.http{s}.port" properties with the port # taken from "rhq.communications.connector.bind-port" has been commented out
diff --git a/modules/enterprise/gui/installer-war/src/main/java/org/rhq/enterprise/installer/ConfigurationBean.java b/modules/enterprise/gui/installer-war/src/main/java/org/rhq/enterprise/installer/ConfigurationBean.java
index e06dbe8..b9c26c4 100644
--- a/modules/enterprise/gui/installer-war/src/main/java/org/rhq/enterprise/installer/ConfigurationBean.java
+++ b/modules/enterprise/gui/installer-war/src/main/java/org/rhq/enterprise/installer/ConfigurationBean.java
@@ -1064,24 +1064,25 @@ public class ConfigurationBean {
}
preconfiguredHaServer.setEndpointAddress(publicEndpointAddress);
- // define the public endpoint ports.
- // note that if using a different transport other than (ssl)servlet, we'll
- // take the connector's bind port and use it for both ports. This is to support a special deployment
- // use-case - 99% of the time, the agents will go through the web/tomcat connector and thus we'll use
- // the http/https ports for the public endpoints.
- PropertyItemWithValue connectorTransport = getConfigurationPropertyFromAll(ServerProperties.PROP_CONNECTOR_TRANSPORT);
- if (connectorTransport != null && connectorTransport.getValue() != null
- && connectorTransport.getValue().contains("socket")) {
-
- // we aren't using the (ssl)servlet protocol, take the connector bind port and use it for the public endpoint ports
- PropertyItemWithValue connectorBindPort = getConfigurationPropertyFromAll(ServerProperties.PROP_CONNECTOR_BIND_PORT);
- if (connectorBindPort == null || connectorBindPort.getValue() == null
- || "".equals(connectorBindPort.getValue().trim()) || "0".equals(connectorBindPort.getValue().trim())) {
- throw new Exception("Using non-servlet transport [" + connectorTransport + "] but didn't define a port");
- }
- preconfiguredHaServer.setEndpointPort(Integer.parseInt(connectorBindPort.getValue()));
- preconfiguredHaServer.setEndpointSecurePort(Integer.parseInt(connectorBindPort.getValue()));
- } else {
+// commented because of BZ 870533
+// // define the public endpoint ports.
+// // note that if using a different transport other than (ssl)servlet, we'll
+// // take the connector's bind port and use it for both ports. This is to support a special deployment
+// // use-case - 99% of the time, the agents will go through the web/tomcat connector and thus we'll use
+// // the http/https ports for the public endpoints.
+// PropertyItemWithValue connectorTransport = getConfigurationPropertyFromAll(ServerProperties.PROP_CONNECTOR_TRANSPORT);
+// if (connectorTransport != null && connectorTransport.getValue() != null
+// && connectorTransport.getValue().contains("socket")) {
+//
+// // we aren't using the (ssl)servlet protocol, take the connector bind port and use it for the public endpoint ports
+// PropertyItemWithValue connectorBindPort = getConfigurationPropertyFromAll(ServerProperties.PROP_CONNECTOR_BIND_PORT);
+// if (connectorBindPort == null || connectorBindPort.getValue() == null
+// || "".equals(connectorBindPort.getValue().trim()) || "0".equals(connectorBindPort.getValue().trim())) {
+// throw new Exception("Using non-servlet transport [" + connectorTransport + "] but didn't define a port");
+// }
+// preconfiguredHaServer.setEndpointPort(Integer.parseInt(connectorBindPort.getValue()));
+// preconfiguredHaServer.setEndpointSecurePort(Integer.parseInt(connectorBindPort.getValue()));
+// } else {
// this is the typical use-case - the transport is probably (ssl)servlet so use the web http/https ports
try {
PropertyItemWithValue httpPort = getPropHaEndpointPort();
@@ -1096,7 +1097,7 @@ public class ConfigurationBean {
} catch (Exception e) {
LOG.warn("Could not determine secure port, will use default: " + e);
}
- }
+// }
// everything looks good - remember these
setHaServer(preconfiguredHaServer);
11 years, 6 months
[rhq] Branch 'lkrejci/code-coverage' - code-coverage/pom.xml
by lkrejci
code-coverage/pom.xml | 4 ----
1 file changed, 4 deletions(-)
New commits:
commit 5eec477dba382b8c67d966f53f67907c95833fad
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Oct 30 13:48:15 2012 +0100
Removed unnecessary property def.
diff --git a/code-coverage/pom.xml b/code-coverage/pom.xml
index a638858..7bce055 100644
--- a/code-coverage/pom.xml
+++ b/code-coverage/pom.xml
@@ -11,10 +11,6 @@
<name>RHQ Code Coverage</name>
<description>A module gathering the code coverage info from the test runs of all the RHQ modules</description>
- <properties>
- <rhq.internal>false</rhq.internal>
- </properties>
-
<profiles>
<profile>
<id>code-coverage</id>
11 years, 6 months
[rhq] Branch 'lkrejci/code-coverage' - code-coverage/pom.xml etc/apt etc/guiperftests modules/core modules/enterprise modules/integration-tests modules/plugins pom.xml
by lkrejci
code-coverage/pom.xml | 209 ++++++++
etc/apt/pom.xml | 4
etc/guiperftests/pom.xml | 2
modules/core/arquillian-integration/container/pom.xml | 4
modules/core/native-system/pom.xml | 4
modules/core/plugin-container/pom.xml | 4
modules/enterprise/binding/pom.xml | 4
modules/enterprise/comm/pom.xml | 2
modules/enterprise/remoting/cli/pom.xml | 2
modules/enterprise/remoting/webservices/pom.xml | 2
modules/enterprise/scripting/javascript/pom.xml | 2
modules/enterprise/scripting/python/pom.xml | 2
modules/enterprise/scripting/python/src/test/java/org/rhq/scripting/python/PythonScriptEngineInitializerTest.java | 7
modules/enterprise/server/itests/pom.xml | 2
modules/enterprise/server/plugins/alert-cli/pom.xml | 2
modules/enterprise/server/plugins/alert-email/pom.xml | 2
modules/enterprise/server/plugins/alert-irc/pom.xml | 2
modules/enterprise/server/plugins/alert-log4j/pom.xml | 2
modules/enterprise/server/plugins/alert-microblog/pom.xml | 2
modules/enterprise/server/plugins/alert-mobicents/pom.xml | 2
modules/enterprise/server/plugins/alert-operations/pom.xml | 2
modules/enterprise/server/plugins/alert-roles/pom.xml | 2
modules/enterprise/server/plugins/alert-sms/pom.xml | 2
modules/enterprise/server/plugins/alert-snmp/pom.xml | 2
modules/enterprise/server/plugins/alert-subject/pom.xml | 2
modules/enterprise/server/plugins/ant-bundle/pom.xml | 2
modules/enterprise/server/plugins/cloud/pom.xml | 2
modules/enterprise/server/plugins/cobbler/pom.xml | 2
modules/enterprise/server/plugins/disk/pom.xml | 4
modules/enterprise/server/plugins/drift-mongodb/pom.xml | 2
modules/enterprise/server/plugins/drift-rhq/pom.xml | 2
modules/enterprise/server/plugins/filetemplate-bundle/pom.xml | 2
modules/enterprise/server/plugins/groovy-script/pom.xml | 2
modules/enterprise/server/plugins/jboss-software/pom.xml | 2
modules/enterprise/server/plugins/packagetype-cli/pom.xml | 2
modules/enterprise/server/plugins/url/pom.xml | 4
modules/enterprise/server/plugins/yum/pom.xml | 4
modules/integration-tests/apache-plugin-test/pom.xml | 2
modules/integration-tests/jndi-access/jndi-access-test/pom.xml | 2
modules/integration-tests/mod_cluster-plugin-test/pom.xml | 2
modules/plugins/aliases/pom.xml | 2
modules/plugins/ant-bundle/pom.xml | 4
modules/plugins/apache/pom.xml | 2
modules/plugins/byteman/pom.xml | 4
modules/plugins/cobbler/pom.xml | 2
modules/plugins/cron/pom.xml | 2
modules/plugins/filetemplate-bundle/pom.xml | 4
modules/plugins/grub/pom.xml | 2
modules/plugins/hibernate/pom.xml | 4
modules/plugins/hosts/pom.xml | 2
modules/plugins/iis/pom.xml | 4
modules/plugins/iptables/pom.xml | 4
modules/plugins/jboss-as-5/pom.xml | 4
modules/plugins/jboss-as-7/pom.xml | 5
modules/plugins/jboss-as/pom.xml | 4
modules/plugins/jboss-cache-v3/pom.xml | 4
modules/plugins/jboss-cache/pom.xml | 4
modules/plugins/jdbctrace/pom.xml | 4
modules/plugins/jira/pom.xml | 4
modules/plugins/jmx/pom.xml | 4
modules/plugins/lsof/pom.xml | 4
modules/plugins/mod-cluster/pom.xml | 2
modules/plugins/mysql/pom.xml | 4
modules/plugins/netservices/pom.xml | 4
modules/plugins/perftest/pom.xml | 4
modules/plugins/platform/pom.xml | 4
modules/plugins/postfix/pom.xml | 2
modules/plugins/postgres/pom.xml | 4
modules/plugins/rhq-agent/pom.xml | 2
modules/plugins/rhq-server/pom.xml | 2
modules/plugins/samba/pom.xml | 2
modules/plugins/script/pom.xml | 4
modules/plugins/sshd/pom.xml | 2
modules/plugins/sudoers/pom.xml | 2
modules/plugins/tomcat/pom.xml | 4
modules/plugins/virt/pom.xml | 4
pom.xml | 237 ++++++++--
77 files changed, 531 insertions(+), 133 deletions(-)
New commits:
commit 1f005f8ed4d286f8c325ca9b54628fc0925831f6
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Oct 30 12:31:27 2012 +0100
Changed the code-coverage provider to JaCoCo.
We now generate a separate coverage report for unit tests and integration tests.
We also generate one overall report per project.
Additionally an overall report including the results of all unit and integration
tests is generated in a new top-level module called "code-coverage".
diff --git a/code-coverage/pom.xml b/code-coverage/pom.xml
new file mode 100644
index 0000000..a638858
--- /dev/null
+++ b/code-coverage/pom.xml
@@ -0,0 +1,209 @@
+<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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>rhq-parent</artifactId>
+ <groupId>org.rhq</groupId>
+ <version>4.6.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>rhq-code-coverage</artifactId>
+
+ <name>RHQ Code Coverage</name>
+ <description>A module gathering the code coverage info from the test runs of all the RHQ modules</description>
+
+ <properties>
+ <rhq.internal>false</rhq.internal>
+ </properties>
+
+ <profiles>
+ <profile>
+ <id>code-coverage</id>
+ <activation>
+ <property>
+ <name>code-coverage</name>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <!-- Do NOT run code coverage on this module... -->
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <!-- Do NOT run tests in this module... -->
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <!-- NOT even the integration tests... -->
+ <plugin>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <!-- Copy the ant tasks jar. Needed for ts.jacoco.report-ant . -->
+ <execution>
+ <id>jacoco-dependency-ant</id>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <phase>process-test-resources</phase>
+ <inherited>false</inherited>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.jacoco</groupId>
+ <artifactId>org.jacoco.ant</artifactId>
+ <version>${jacoco.version}</version>
+ </artifactItem>
+ </artifactItems>
+ <stripVersion>true</stripVersion>
+ <outputDirectory>${project.build.directory}/jacoco-jars</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>overall-chart-creation</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <!-- Execute an ant task within maven -->
+ <echo message="Generating JaCoCo Reports" />
+ <taskdef name="report" classname="org.jacoco.ant.ReportTask">
+ <classpath path="${project.build.directory}/jacoco-jars/org.jacoco.ant.jar" />
+ </taskdef>
+ <mkdir dir="${project.reporting.outputDirectory}/coverage-report/overall" />
+ <report>
+ <executiondata>
+ <fileset dir="${basedir}/../modules">
+ <include name="**/target/jacoco-unit-test.exec" />
+ <include name="**/target/jacoco-integration-test.exec" />
+ </fileset>
+ </executiondata>
+ <structure name="RHQ Overall Code Coverage Report (including unit and integration tests)">
+ <group name="Plugins">
+ <classfiles>
+ <fileset dir="${basedir}/../modules">
+ <include name="plugins/**/target/classes/org/rhq/**" />
+ <include name="plugins/**/target/generated-classes/*/org/rhq/**" />
+ <include name="integration-tests/**/target/classes/org/rhq/**" />
+ <include name="integration-tests/**/target/generated-classes/org/rhq/**" />
+ </fileset>
+ </classfiles>
+ <sourcefiles>
+ <dirset dir="${basedir}/../modules/">
+ <include name="**/src/main/java" />
+ <include name="**/target/generated-sources/*" />
+ </dirset>
+ </sourcefiles>
+ </group>
+ <group name="Core">
+ <classfiles>
+ <fileset dir="${basedir}/../modules">
+ <include name="core/**/target/classes/org/rhq/**" />
+ <include name="core/**/target/generated-classes/org/rhq/**" />
+ <include name="integration-tests/**/target/classes/org/rhq/**" />
+ <include name="integration-tests/**/target/generated-classes/org/rhq/**" />
+ </fileset>
+ </classfiles>
+ <sourcefiles>
+ <dirset dir="${basedir}/../modules/">
+ <include name="**/src/main/java" />
+ <include name="**/target/generated-sources/*" />
+ </dirset>
+ </sourcefiles>
+ </group>
+ <group name="Enterprise">
+ <classfiles>
+ <fileset dir="${basedir}/../modules">
+ <include name="enterprise/**/target/classes/org/rhq/**" />
+ <include name="enterprise/**/target/generated-classes/org/rhq/**" />
+ <include name="integration-tests/**/target/classes/org/rhq/**" />
+ <include name="integration-tests/**/target/generated-classes/org/rhq/**" />
+ <exclude name="enterprise/gui/**" />
+ </fileset>
+ </classfiles>
+ <sourcefiles>
+ <dirset dir="${basedir}/../modules/">
+ <include name="**/src/main/java" />
+ <include name="**/target/generated-sources/*" />
+ </dirset>
+ </sourcefiles>
+ </group>
+ <group name="GUI">
+ <classfiles>
+ <fileset dir="${basedir}/../modules">
+ <include name="enterprise/gui/**/target/classes/org/rhq/**" />
+ <include name="enterprise/gui/**/target/generated-classes/org/rhq/**" />
+ <include name="integration-tests/**/target/classes/org/rhq/**" />
+ <include name="integration-tests/**/target/generated-classes/org/rhq/**" />
+ </fileset>
+ </classfiles>
+ <sourcefiles>
+ <dirset dir="${basedir}/../modules/">
+ <include name="**/src/main/java" />
+ <include name="**/target/generated-sources/*" />
+ </dirset>
+ </sourcefiles>
+ </group>
+ <group name="Miscellaneous">
+ <classfiles>
+ <fileset dir="${basedir}/../modules">
+ <include name="**/target/classes/org/rhq/**" />
+ <include name="**/target/generated-classes/org/rhq/**" />
+ <exclude name="plugins/**/target/classes/org/rhq/**" />
+ <exclude name="plugins/**/target/generated-classes/*/org/rhq/**" />
+ <exclude name="core/**/target/classes/org/rhq/**" />
+ <exclude name="core/**/target/generated-classes/org/rhq/**" />
+ <exclude name="enterprise/**/target/classes/org/rhq/**" />
+ <exclude name="enterprise/**/target/generated-classes/org/rhq/**" />
+ </fileset>
+ </classfiles>
+ <sourcefiles>
+ <dirset dir="${basedir}/../modules/">
+ <include name="**/src/main/java" />
+ <include name="**/target/generated-sources/*" />
+ </dirset>
+ </sourcefiles>
+ </group>
+ </structure>
+ <html destdir="${project.reporting.outputDirectory}/coverage-report/overall" />
+ <xml destfile="${project.reporting.outputDirectory}/coverage-report/overall/coverage-report.xml" />
+ <csv destfile="${project.reporting.outputDirectory}/coverage-report/overall/coverage-report.csv" />
+ </report>
+ </target>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.jacoco</groupId>
+ <artifactId>org.jacoco.ant</artifactId>
+ <version>${jacoco.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
+
\ No newline at end of file
diff --git a/etc/apt/pom.xml b/etc/apt/pom.xml
index 882bdee..215ebd9 100644
--- a/etc/apt/pom.xml
+++ b/etc/apt/pom.xml
@@ -107,8 +107,8 @@
<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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/etc/guiperftests/pom.xml b/etc/guiperftests/pom.xml
index 4ef1107..07d6d1d 100644
--- a/etc/guiperftests/pom.xml
+++ b/etc/guiperftests/pom.xml
@@ -70,7 +70,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
- <argLine>-Xms16M -Xmx256M</argLine>
+ <argLine>${jacoco.unit-test.args} -Xms16M -Xmx256M</argLine>
</configuration>
</plugin>
</plugins>
diff --git a/modules/core/arquillian-integration/container/pom.xml b/modules/core/arquillian-integration/container/pom.xml
index 590a475..19b4d35 100644
--- a/modules/core/arquillian-integration/container/pom.xml
+++ b/modules/core/arquillian-integration/container/pom.xml
@@ -83,8 +83,10 @@
<!-- 3rd party -->
+ <!-- Yes, this is meant to be org.javassist:javassist, and NOT
+ javassist:javassist - which is an older impl -->
<dependency>
- <groupId>javassist</groupId>
+ <groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
</dependency>
diff --git a/modules/core/native-system/pom.xml b/modules/core/native-system/pom.xml
index 217830c..d7e1500 100644
--- a/modules/core/native-system/pom.xml
+++ b/modules/core/native-system/pom.xml
@@ -92,9 +92,9 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!-- need to point the library path to the location of the native libraries -->
- <argLine>-Dorg.hyperic.sigar.path=${project.build.directory}/jboss-sigar</argLine>
+ <argLine>${jacoco.unit-test.args} -Dorg.hyperic.sigar.path=${project.build.directory}/jboss-sigar</argLine>
<!--
- <argLine>-Dorg.hyperic.sigar.path=${project.build.directory}/jboss-sigar -Dsigar.nativeLogging=true -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Dorg.hyperic.sigar.path=${project.build.directory}/jboss-sigar -Dsigar.nativeLogging=true -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/core/plugin-container/pom.xml b/modules/core/plugin-container/pom.xml
index 04c6f92..b3fcf49 100644
--- a/modules/core/plugin-container/pom.xml
+++ b/modules/core/plugin-container/pom.xml
@@ -364,9 +364,9 @@
<excludedGroups>arquillian,${rhq.testng.excludedGroups}</excludedGroups>
<!-- need to point the library path to the location of the native libraries -->
- <argLine>-Dorg.hyperic.sigar.path=${project.build.directory}/jboss-sigar</argLine>
+ <argLine>${jacoco.unit-test.args} -Dorg.hyperic.sigar.path=${project.build.directory}/jboss-sigar</argLine>
<!--
- <argLine>-Dorg.hyperic.sigar.path=${project.build.directory}/jboss-sigar -Dsigar.nativeLogging=true</argLine>
+ <argLine>${jacoco.unit-test.args} -Dorg.hyperic.sigar.path=${project.build.directory}/jboss-sigar -Dsigar.nativeLogging=true</argLine>
-->
</configuration>
</execution>
diff --git a/modules/enterprise/binding/pom.xml b/modules/enterprise/binding/pom.xml
index 016f36c..0b290d3 100644
--- a/modules/enterprise/binding/pom.xml
+++ b/modules/enterprise/binding/pom.xml
@@ -240,9 +240,9 @@
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
- <!-- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE
+ <!-- <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE
-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine> -->
- <argLine>-Djava.security.manager -Djava.security.policy==${project.build.testOutputDirectory}/allow-all.policy</argLine>
+ <argLine>${jacoco.unit-test.args} -Djava.security.manager -Djava.security.policy==${project.build.testOutputDirectory}/allow-all.policy</argLine>
<!-- This is important, because some of the tests try to exit the JVM. -->
<failIfNoTests>true</failIfNoTests>
</configuration>
diff --git a/modules/enterprise/comm/pom.xml b/modules/enterprise/comm/pom.xml
index b14937b..6214f5e 100644
--- a/modules/enterprise/comm/pom.xml
+++ b/modules/enterprise/comm/pom.xml
@@ -144,7 +144,7 @@
<skip>false</skip>
-->
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
<systemPropertyVariables combine.children="append">
<rhq.comm.test.connectorBindPort>${rhq.comm.test.connectorBindPort}</rhq.comm.test.connectorBindPort>
diff --git a/modules/enterprise/remoting/cli/pom.xml b/modules/enterprise/remoting/cli/pom.xml
index 6669e43..e069d89 100644
--- a/modules/enterprise/remoting/cli/pom.xml
+++ b/modules/enterprise/remoting/cli/pom.xml
@@ -200,7 +200,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups},ws</excludedGroups>
<forkMode>pertest</forkMode>
- <argLine>-Xmx512m -Xms128m</argLine>
+ <argLine>${jacoco.unit-test.args} -Xmx512m -Xms128m</argLine>
<additionalClasspathElements>
-->
<!-- The below is required for WS Java Client support -->
diff --git a/modules/enterprise/remoting/webservices/pom.xml b/modules/enterprise/remoting/webservices/pom.xml
index e2a48c4..33c1952 100644
--- a/modules/enterprise/remoting/webservices/pom.xml
+++ b/modules/enterprise/remoting/webservices/pom.xml
@@ -207,7 +207,7 @@
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<groups>ws</groups>
<forkMode>pertest</forkMode>
- <argLine>-Xmx512m -Xms128m</argLine>
+ <argLine>${jacoco.unit-test.args} -Xmx512m -Xms128m</argLine>
<systemProperties>
<property>
<name>deploymentDirectory</name>
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index 7788fd6..ab35acb 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -57,7 +57,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
- <argLine>-Djava.security.manager
+ <argLine>${jacoco.unit-test.args} -Djava.security.manager
-Djava.security.policy==${project.build.testOutputDirectory}/allow-all.policy</argLine>
<!-- This is important, because some of the tests try to exit
the JVM. -->
diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
index 9355be6..e4b3cfb 100644
--- a/modules/enterprise/scripting/python/pom.xml
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -56,7 +56,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
- <argLine>-Djava.security.manager
+ <argLine>${jacoco.unit-test.args} -Djava.security.manager
-Djava.security.policy==${project.build.testOutputDirectory}/allow-all.policy</argLine>
<!-- This is important, because some of the tests try to exit
the JVM. -->
diff --git a/modules/enterprise/scripting/python/src/test/java/org/rhq/scripting/python/PythonScriptEngineInitializerTest.java b/modules/enterprise/scripting/python/src/test/java/org/rhq/scripting/python/PythonScriptEngineInitializerTest.java
index b1d4a65..e3b1355 100644
--- a/modules/enterprise/scripting/python/src/test/java/org/rhq/scripting/python/PythonScriptEngineInitializerTest.java
+++ b/modules/enterprise/scripting/python/src/test/java/org/rhq/scripting/python/PythonScriptEngineInitializerTest.java
@@ -25,6 +25,7 @@ import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.net.URI;
import java.security.AccessControlException;
import java.security.Permissions;
@@ -164,6 +165,12 @@ public class PythonScriptEngineInitializerTest {
Map<String, Set<Method>> ret = new HashMap<String, Set<Method>>();
for (Method m : cls.getDeclaredMethods()) {
+ int mods = m.getModifiers();
+
+ if (Modifier.isStatic(mods) || !Modifier.isPublic(mods)) {
+ continue;
+ }
+
Set<Method> methods = ret.get(m.getName());
if (methods == null) {
methods = new HashSet<Method>();
diff --git a/modules/enterprise/server/itests/pom.xml b/modules/enterprise/server/itests/pom.xml
index 337f003..0ec6a6a 100644
--- a/modules/enterprise/server/itests/pom.xml
+++ b/modules/enterprise/server/itests/pom.xml
@@ -369,7 +369,7 @@
<value>${project.version}</value>
</property>
</systemProperties>
- <argLine>-Djava.security.manager -Djava.security.policy==${basedir}/target/test-classes/security.policy</argLine>
+ <argLine>${jacoco.unit-test.args} -Djava.security.manager -Djava.security.policy==${basedir}/target/test-classes/security.policy</argLine>
<additionalClasspathElements>
<!-- The below is required for tests to run against Oracle. -->
<additionalClasspathElement>${settings.localRepository}/com/oracle/ojdbc6/${ojdbc6.version}/ojdbc6-${ojdbc6.version}.jar</additionalClasspathElement>
diff --git a/modules/enterprise/server/plugins/alert-cli/pom.xml b/modules/enterprise/server/plugins/alert-cli/pom.xml
index ba3d9e7..5beb580 100644
--- a/modules/enterprise/server/plugins/alert-cli/pom.xml
+++ b/modules/enterprise/server/plugins/alert-cli/pom.xml
@@ -28,7 +28,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
- <!-- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE
+ <!-- <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE
-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine> -->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/alert-email/pom.xml b/modules/enterprise/server/plugins/alert-email/pom.xml
index 4ef23f6..42e8f66 100644
--- a/modules/enterprise/server/plugins/alert-email/pom.xml
+++ b/modules/enterprise/server/plugins/alert-email/pom.xml
@@ -34,7 +34,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/alert-irc/pom.xml b/modules/enterprise/server/plugins/alert-irc/pom.xml
index 23835a6..03db452 100644
--- a/modules/enterprise/server/plugins/alert-irc/pom.xml
+++ b/modules/enterprise/server/plugins/alert-irc/pom.xml
@@ -31,7 +31,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/alert-log4j/pom.xml b/modules/enterprise/server/plugins/alert-log4j/pom.xml
index 2348550..01ad691 100644
--- a/modules/enterprise/server/plugins/alert-log4j/pom.xml
+++ b/modules/enterprise/server/plugins/alert-log4j/pom.xml
@@ -21,7 +21,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/alert-microblog/pom.xml b/modules/enterprise/server/plugins/alert-microblog/pom.xml
index ff263a3..e7359c1 100644
--- a/modules/enterprise/server/plugins/alert-microblog/pom.xml
+++ b/modules/enterprise/server/plugins/alert-microblog/pom.xml
@@ -29,7 +29,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/alert-mobicents/pom.xml b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
index 7e492cb..66b5993 100644
--- a/modules/enterprise/server/plugins/alert-mobicents/pom.xml
+++ b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
@@ -21,7 +21,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/alert-operations/pom.xml b/modules/enterprise/server/plugins/alert-operations/pom.xml
index 9dc3ad5..a5f809f 100644
--- a/modules/enterprise/server/plugins/alert-operations/pom.xml
+++ b/modules/enterprise/server/plugins/alert-operations/pom.xml
@@ -21,7 +21,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/alert-roles/pom.xml b/modules/enterprise/server/plugins/alert-roles/pom.xml
index 248675d..e561d51 100644
--- a/modules/enterprise/server/plugins/alert-roles/pom.xml
+++ b/modules/enterprise/server/plugins/alert-roles/pom.xml
@@ -32,7 +32,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/alert-sms/pom.xml b/modules/enterprise/server/plugins/alert-sms/pom.xml
index b0c88c9..72a6b15 100644
--- a/modules/enterprise/server/plugins/alert-sms/pom.xml
+++ b/modules/enterprise/server/plugins/alert-sms/pom.xml
@@ -64,7 +64,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/alert-snmp/pom.xml b/modules/enterprise/server/plugins/alert-snmp/pom.xml
index 5561091..3619956 100644
--- a/modules/enterprise/server/plugins/alert-snmp/pom.xml
+++ b/modules/enterprise/server/plugins/alert-snmp/pom.xml
@@ -29,7 +29,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/alert-subject/pom.xml b/modules/enterprise/server/plugins/alert-subject/pom.xml
index e3394ab..ca4c079 100644
--- a/modules/enterprise/server/plugins/alert-subject/pom.xml
+++ b/modules/enterprise/server/plugins/alert-subject/pom.xml
@@ -21,7 +21,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/ant-bundle/pom.xml b/modules/enterprise/server/plugins/ant-bundle/pom.xml
index b4f59b0..e896df6 100644
--- a/modules/enterprise/server/plugins/ant-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/ant-bundle/pom.xml
@@ -66,7 +66,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/cloud/pom.xml b/modules/enterprise/server/plugins/cloud/pom.xml
index 6ed8c41..bf2f8d5 100644
--- a/modules/enterprise/server/plugins/cloud/pom.xml
+++ b/modules/enterprise/server/plugins/cloud/pom.xml
@@ -49,7 +49,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/cobbler/pom.xml b/modules/enterprise/server/plugins/cobbler/pom.xml
index d91220a..af648f1 100644
--- a/modules/enterprise/server/plugins/cobbler/pom.xml
+++ b/modules/enterprise/server/plugins/cobbler/pom.xml
@@ -73,7 +73,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/disk/pom.xml b/modules/enterprise/server/plugins/disk/pom.xml
index af75452..f6f4172 100644
--- a/modules/enterprise/server/plugins/disk/pom.xml
+++ b/modules/enterprise/server/plugins/disk/pom.xml
@@ -48,8 +48,8 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
- -->
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ -->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/drift-mongodb/pom.xml b/modules/enterprise/server/plugins/drift-mongodb/pom.xml
index 1c65111..ccc7edd 100644
--- a/modules/enterprise/server/plugins/drift-mongodb/pom.xml
+++ b/modules/enterprise/server/plugins/drift-mongodb/pom.xml
@@ -88,7 +88,7 @@
<skipTests>${skip.mongodb.tests}</skipTests>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/drift-rhq/pom.xml b/modules/enterprise/server/plugins/drift-rhq/pom.xml
index ad0fc4f..ec4f8d3 100644
--- a/modules/enterprise/server/plugins/drift-rhq/pom.xml
+++ b/modules/enterprise/server/plugins/drift-rhq/pom.xml
@@ -62,7 +62,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
index 7f4dfac..96458e2 100644
--- a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
@@ -68,7 +68,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/groovy-script/pom.xml b/modules/enterprise/server/plugins/groovy-script/pom.xml
index b306249..d8ea7f7 100644
--- a/modules/enterprise/server/plugins/groovy-script/pom.xml
+++ b/modules/enterprise/server/plugins/groovy-script/pom.xml
@@ -125,7 +125,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/jboss-software/pom.xml b/modules/enterprise/server/plugins/jboss-software/pom.xml
index cbb2a54..c2e0b73 100644
--- a/modules/enterprise/server/plugins/jboss-software/pom.xml
+++ b/modules/enterprise/server/plugins/jboss-software/pom.xml
@@ -53,7 +53,7 @@
<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>-->
+ <!--<argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/packagetype-cli/pom.xml b/modules/enterprise/server/plugins/packagetype-cli/pom.xml
index 5a7da8e..bb5ef4d 100644
--- a/modules/enterprise/server/plugins/packagetype-cli/pom.xml
+++ b/modules/enterprise/server/plugins/packagetype-cli/pom.xml
@@ -21,7 +21,7 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/url/pom.xml b/modules/enterprise/server/plugins/url/pom.xml
index 471153b..338e489 100644
--- a/modules/enterprise/server/plugins/url/pom.xml
+++ b/modules/enterprise/server/plugins/url/pom.xml
@@ -57,8 +57,8 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
- -->
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ -->
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/yum/pom.xml b/modules/enterprise/server/plugins/yum/pom.xml
index c07a573..2d0ed5e 100644
--- a/modules/enterprise/server/plugins/yum/pom.xml
+++ b/modules/enterprise/server/plugins/yum/pom.xml
@@ -42,8 +42,8 @@
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
- -->
+ <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ -->
</configuration>
</plugin>
diff --git a/modules/integration-tests/apache-plugin-test/pom.xml b/modules/integration-tests/apache-plugin-test/pom.xml
index 4f57361..390c772 100644
--- a/modules/integration-tests/apache-plugin-test/pom.xml
+++ b/modules/integration-tests/apache-plugin-test/pom.xml
@@ -270,7 +270,7 @@
<additionalClasspathElements>
<additionalClasspathElement>${env.JAVA_HOME}/lib/tools.jar</additionalClasspathElement>
</additionalClasspathElements>
- <!--<argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib
+ <!--<argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib
-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine> -->
<environmentVariables>
<LD_LIBRARY_PATH>${basedir}/target/itest/lib:${env.LD_LIBRARY_PATH}</LD_LIBRARY_PATH>
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
index 3533cff..aed285e 100644
--- a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
+++ b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
@@ -326,7 +326,7 @@
<jnp.port>${jnp.port}</jnp.port>
<jnp.rmiPort>${jnp.rmiPort}</jnp.rmiPort>
</systemPropertyVariables>
- <argLine>-Djava.security.manager -Djava.security.policy==${basedir}/target/test-classes/security.policy</argLine>
+ <argLine>${jacoco.unit-test.args} -Djava.security.manager -Djava.security.policy==${basedir}/target/test-classes/security.policy</argLine>
<additionalClasspathElements>
<!-- The below is required for tests to run against
Oracle. -->
diff --git a/modules/integration-tests/mod_cluster-plugin-test/pom.xml b/modules/integration-tests/mod_cluster-plugin-test/pom.xml
index 63fb98d..0a30815 100644
--- a/modules/integration-tests/mod_cluster-plugin-test/pom.xml
+++ b/modules/integration-tests/mod_cluster-plugin-test/pom.xml
@@ -345,7 +345,7 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>false</useSystemClassLoader>
- <argLine>-Dorg.hyperic.sigar.path=${basedir}/target/testsetup/lib</argLine>
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/testsetup/lib</argLine>
<systemProperties>
<property>
<name>project.artifactId</name>
diff --git a/modules/plugins/aliases/pom.xml b/modules/plugins/aliases/pom.xml
index aa455b8..7a84e11 100644
--- a/modules/plugins/aliases/pom.xml
+++ b/modules/plugins/aliases/pom.xml
@@ -163,7 +163,7 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</useSystemClassLoader>
- <!--<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>-->
+ <!--<argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
<environmentVariables>
<LD_LIBRARY_PATH>${basedir}/target/itest/lib:${env.LD_LIBRARY_PATH}</LD_LIBRARY_PATH>
</environmentVariables>
diff --git a/modules/plugins/ant-bundle/pom.xml b/modules/plugins/ant-bundle/pom.xml
index 0427125..357d294 100644
--- a/modules/plugins/ant-bundle/pom.xml
+++ b/modules/plugins/ant-bundle/pom.xml
@@ -160,9 +160,9 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>false</useSystemClassLoader>
- <argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
<!--
- <argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE
+ <argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/apache/pom.xml b/modules/plugins/apache/pom.xml
index 83070a3..2055075 100644
--- a/modules/plugins/apache/pom.xml
+++ b/modules/plugins/apache/pom.xml
@@ -225,7 +225,7 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</useSystemClassLoader>
- <!--<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>-->
+ <!--<argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
<environmentVariables>
<LD_LIBRARY_PATH>${basedir}/target/itest/lib:${env.LD_LIBRARY_PATH}</LD_LIBRARY_PATH>
</environmentVariables>
diff --git a/modules/plugins/byteman/pom.xml b/modules/plugins/byteman/pom.xml
index 62e4127..b20128b 100644
--- a/modules/plugins/byteman/pom.xml
+++ b/modules/plugins/byteman/pom.xml
@@ -132,8 +132,8 @@
<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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/cobbler/pom.xml b/modules/plugins/cobbler/pom.xml
index d362d14..dd09ee4 100644
--- a/modules/plugins/cobbler/pom.xml
+++ b/modules/plugins/cobbler/pom.xml
@@ -168,7 +168,7 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</useSystemClassLoader>
- <!--<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>-->
+ <!--<argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
<environmentVariables>
<LD_LIBRARY_PATH>${basedir}/target/itest/lib:${env.LD_LIBRARY_PATH}</LD_LIBRARY_PATH>
</environmentVariables>
diff --git a/modules/plugins/cron/pom.xml b/modules/plugins/cron/pom.xml
index 7a51dda..b657717 100644
--- a/modules/plugins/cron/pom.xml
+++ b/modules/plugins/cron/pom.xml
@@ -157,7 +157,7 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</useSystemClassLoader>
- <!--<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>-->
+ <!--<argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
<environmentVariables>
<LD_LIBRARY_PATH>${basedir}/target/itest/lib:${env.LD_LIBRARY_PATH}</LD_LIBRARY_PATH>
</environmentVariables>
diff --git a/modules/plugins/filetemplate-bundle/pom.xml b/modules/plugins/filetemplate-bundle/pom.xml
index e635b21..5701fed 100644
--- a/modules/plugins/filetemplate-bundle/pom.xml
+++ b/modules/plugins/filetemplate-bundle/pom.xml
@@ -141,8 +141,8 @@
<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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/grub/pom.xml b/modules/plugins/grub/pom.xml
index 866bbb9..5ede70d 100644
--- a/modules/plugins/grub/pom.xml
+++ b/modules/plugins/grub/pom.xml
@@ -154,7 +154,7 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>false</useSystemClassLoader>
- <!--<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>-->
+ <!--<argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
<environmentVariables>
<LD_LIBRARY_PATH>${basedir}/target/itest/lib:${env.LD_LIBRARY_PATH}</LD_LIBRARY_PATH>
</environmentVariables>
diff --git a/modules/plugins/hibernate/pom.xml b/modules/plugins/hibernate/pom.xml
index 5240ed7..f959900 100644
--- a/modules/plugins/hibernate/pom.xml
+++ b/modules/plugins/hibernate/pom.xml
@@ -134,8 +134,8 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/hosts/pom.xml b/modules/plugins/hosts/pom.xml
index d893686..a3526b1 100644
--- a/modules/plugins/hosts/pom.xml
+++ b/modules/plugins/hosts/pom.xml
@@ -164,7 +164,7 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</useSystemClassLoader>
- <!--<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>-->
+ <!--<argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
<environmentVariables>
<LD_LIBRARY_PATH>${basedir}/target/itest/lib:${env.LD_LIBRARY_PATH}</LD_LIBRARY_PATH>
</environmentVariables>
diff --git a/modules/plugins/iis/pom.xml b/modules/plugins/iis/pom.xml
index 9e6f67f..76159e8 100644
--- a/modules/plugins/iis/pom.xml
+++ b/modules/plugins/iis/pom.xml
@@ -90,8 +90,8 @@
<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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/iptables/pom.xml b/modules/plugins/iptables/pom.xml
index d6eeff3..6f76c32 100644
--- a/modules/plugins/iptables/pom.xml
+++ b/modules/plugins/iptables/pom.xml
@@ -106,8 +106,8 @@
<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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/jboss-as-5/pom.xml b/modules/plugins/jboss-as-5/pom.xml
index 283b840..40783dd 100644
--- a/modules/plugins/jboss-as-5/pom.xml
+++ b/modules/plugins/jboss-as-5/pom.xml
@@ -344,8 +344,8 @@
<useSystemClassLoader>true</useSystemClassLoader>
<excludes><exclude>org/rhq/plugins/jbossas5/itest/**</exclude></excludes>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
- <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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
<additionalClasspathElements>
<additionalClasspathElement>
${project.build.testSourceDirectory}/../jars/ejb2-test.jar
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 10b0ad2..61677c1 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -88,7 +88,6 @@
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
-
</dependencies>
@@ -307,7 +306,8 @@
<delete file="${as7.zipfile}"/>
<get src="${as7.url}" dest="${as7.zipfile}" usetimestamp="true" verbose="true"/>
<unzip src="${as7.zipfile}" dest="${java.io.tmpdir}"/>
- <delete dir="${jboss7.home}" verbose="true"/>
+ <!-- What was this supposed to do? Right now, it'd delete the AS7 deployment we just unzipped. -->
+ <!-- <delete dir="${jboss7.home}" verbose="true"/> -->
<move file="${java.io.tmpdir}/jboss-eap-6.0"
tofile="${jboss7.home}" failonerror="false"/>
@@ -612,7 +612,6 @@
</build>
</profile>
-
</profiles>
</project>
diff --git a/modules/plugins/jboss-as/pom.xml b/modules/plugins/jboss-as/pom.xml
index a7bb4b2..4f44560 100644
--- a/modules/plugins/jboss-as/pom.xml
+++ b/modules/plugins/jboss-as/pom.xml
@@ -265,8 +265,8 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/jboss-cache-v3/pom.xml b/modules/plugins/jboss-cache-v3/pom.xml
index 82e9ce7..d361412 100644
--- a/modules/plugins/jboss-cache-v3/pom.xml
+++ b/modules/plugins/jboss-cache-v3/pom.xml
@@ -384,8 +384,8 @@
<additionalClasspathElement>${project.build.testSourceDirectory}/../jars/TestCacheEJB.jar</additionalClasspathElement>
</additionalClasspathElements>
<excludedGroups>jbosscache3.test</excludedGroups>
- <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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/jboss-cache/pom.xml b/modules/plugins/jboss-cache/pom.xml
index 3224e55..aa567d1 100644
--- a/modules/plugins/jboss-cache/pom.xml
+++ b/modules/plugins/jboss-cache/pom.xml
@@ -124,8 +124,8 @@
<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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/jdbctrace/pom.xml b/modules/plugins/jdbctrace/pom.xml
index 3a3ea7c..5eb4cbf 100644
--- a/modules/plugins/jdbctrace/pom.xml
+++ b/modules/plugins/jdbctrace/pom.xml
@@ -162,8 +162,8 @@
<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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/jira/pom.xml b/modules/plugins/jira/pom.xml
index d9f90ba..a0c584d 100644
--- a/modules/plugins/jira/pom.xml
+++ b/modules/plugins/jira/pom.xml
@@ -142,8 +142,8 @@
<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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/jmx/pom.xml b/modules/plugins/jmx/pom.xml
index 36db1d4..6338a09 100644
--- a/modules/plugins/jmx/pom.xml
+++ b/modules/plugins/jmx/pom.xml
@@ -122,8 +122,8 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/lsof/pom.xml b/modules/plugins/lsof/pom.xml
index eca4983..a83c1e3 100644
--- a/modules/plugins/lsof/pom.xml
+++ b/modules/plugins/lsof/pom.xml
@@ -132,8 +132,8 @@
<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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/mod-cluster/pom.xml b/modules/plugins/mod-cluster/pom.xml
index 4a3493f..159ca2b 100644
--- a/modules/plugins/mod-cluster/pom.xml
+++ b/modules/plugins/mod-cluster/pom.xml
@@ -152,7 +152,7 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>false</useSystemClassLoader>
- <argLine>-Dorg.hyperic.sigar.path=${basedir}/target/testsetup/lib</argLine>
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/testsetup/lib</argLine>
<systemProperties>
<property>
<name>project.artifactId</name>
diff --git a/modules/plugins/mysql/pom.xml b/modules/plugins/mysql/pom.xml
index 9d1d12f..2aca604 100644
--- a/modules/plugins/mysql/pom.xml
+++ b/modules/plugins/mysql/pom.xml
@@ -137,8 +137,8 @@
<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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/netservices/pom.xml b/modules/plugins/netservices/pom.xml
index 1150274..5784707 100644
--- a/modules/plugins/netservices/pom.xml
+++ b/modules/plugins/netservices/pom.xml
@@ -142,8 +142,8 @@
<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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/perftest/pom.xml b/modules/plugins/perftest/pom.xml
index 2e34f17..b5675b2 100644
--- a/modules/plugins/perftest/pom.xml
+++ b/modules/plugins/perftest/pom.xml
@@ -110,9 +110,9 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>false</useSystemClassLoader>
- <argLine>-Djava.library.path=${basedir}/target/itest/lib</argLine>
+ <argLine>${jacoco.integration-test.args} -Djava.library.path=${basedir}/target/itest/lib</argLine>
<!--
- <argLine>-Djava.library.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ <argLine>${jacoco.integration-test.args} -Djava.library.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
<systemPropertyVariables>
diff --git a/modules/plugins/platform/pom.xml b/modules/plugins/platform/pom.xml
index 3ea1b6a..e97e499 100644
--- a/modules/plugins/platform/pom.xml
+++ b/modules/plugins/platform/pom.xml
@@ -90,8 +90,8 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/postfix/pom.xml b/modules/plugins/postfix/pom.xml
index 4e01e5d..1f09192 100644
--- a/modules/plugins/postfix/pom.xml
+++ b/modules/plugins/postfix/pom.xml
@@ -162,7 +162,7 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</useSystemClassLoader>
- <!--<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>-->
+ <!--<argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
<environmentVariables>
<LD_LIBRARY_PATH>${basedir}/target/itest/lib:${env.LD_LIBRARY_PATH}</LD_LIBRARY_PATH>
</environmentVariables>
diff --git a/modules/plugins/postgres/pom.xml b/modules/plugins/postgres/pom.xml
index a169747..8edd65b 100644
--- a/modules/plugins/postgres/pom.xml
+++ b/modules/plugins/postgres/pom.xml
@@ -136,8 +136,8 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/rhq-agent/pom.xml b/modules/plugins/rhq-agent/pom.xml
index 78156ef..8e3a261 100644
--- a/modules/plugins/rhq-agent/pom.xml
+++ b/modules/plugins/rhq-agent/pom.xml
@@ -110,7 +110,7 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</useSystemClassLoader>
- <argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
<systemPropertyVariables combine.children="append">
<project.artifactId>${project.artifactId}</project.artifactId>
<project.version>${project.version}</project.version>
diff --git a/modules/plugins/rhq-server/pom.xml b/modules/plugins/rhq-server/pom.xml
index 6fcebc8..e829cdd 100644
--- a/modules/plugins/rhq-server/pom.xml
+++ b/modules/plugins/rhq-server/pom.xml
@@ -135,7 +135,7 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>false</useSystemClassLoader>
- <argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
<systemProperties>
<property>
<name>project.artifactId</name>
diff --git a/modules/plugins/samba/pom.xml b/modules/plugins/samba/pom.xml
index 4bf3518..8eb30e5 100644
--- a/modules/plugins/samba/pom.xml
+++ b/modules/plugins/samba/pom.xml
@@ -162,7 +162,7 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</useSystemClassLoader>
- <!--<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>-->
+ <!--<argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
<environmentVariables>
<LD_LIBRARY_PATH>${basedir}/target/itest/lib:${env.LD_LIBRARY_PATH}</LD_LIBRARY_PATH>
</environmentVariables>
diff --git a/modules/plugins/script/pom.xml b/modules/plugins/script/pom.xml
index 7dc360f..b0e846e 100644
--- a/modules/plugins/script/pom.xml
+++ b/modules/plugins/script/pom.xml
@@ -90,8 +90,8 @@
<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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/sshd/pom.xml b/modules/plugins/sshd/pom.xml
index 0462ac0..d03c5c4 100644
--- a/modules/plugins/sshd/pom.xml
+++ b/modules/plugins/sshd/pom.xml
@@ -154,7 +154,7 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>false</useSystemClassLoader>
- <!--<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>-->
+ <!--<argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
<environmentVariables>
<LD_LIBRARY_PATH>${basedir}/target/itest/lib:${env.LD_LIBRARY_PATH}</LD_LIBRARY_PATH>
</environmentVariables>
diff --git a/modules/plugins/sudoers/pom.xml b/modules/plugins/sudoers/pom.xml
index 095692b..c17112c 100644
--- a/modules/plugins/sudoers/pom.xml
+++ b/modules/plugins/sudoers/pom.xml
@@ -152,7 +152,7 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</useSystemClassLoader>
- <!--<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>-->
+ <!--<argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
<environmentVariables>
<LD_LIBRARY_PATH>${basedir}/target/itest/lib:${env.LD_LIBRARY_PATH}</LD_LIBRARY_PATH>
</environmentVariables>
diff --git a/modules/plugins/tomcat/pom.xml b/modules/plugins/tomcat/pom.xml
index e1b0c40..93092ea 100644
--- a/modules/plugins/tomcat/pom.xml
+++ b/modules/plugins/tomcat/pom.xml
@@ -117,8 +117,8 @@
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
<useSystemClassLoader>true</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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/modules/plugins/virt/pom.xml b/modules/plugins/virt/pom.xml
index cf01db9..ad8efb4 100644
--- a/modules/plugins/virt/pom.xml
+++ b/modules/plugins/virt/pom.xml
@@ -111,8 +111,8 @@
<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>-->
+ <argLine>${jacoco.integration-test.args} -Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>${jacoco.integration-test.args} -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>
diff --git a/pom.xml b/pom.xml
index 53fa751..ea5af1c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -72,7 +72,7 @@
<jboss-javassist.version>3.9.0.GA</jboss-javassist.version>
<jbossws-native-dist.version>3.1.1.GA</jbossws-native-dist.version>
<!-- End: JBoss AS Dependency Versions -->
-
+
<commons-logging.version>1.1.0.jboss</commons-logging.version>
<concurrent.version>1.3.4-jboss-update1</concurrent.version> <!-- oswego-concurrent compatible with 4.2.3.GA -->
<findbugs.version>2.3.2</findbugs.version>
@@ -109,10 +109,16 @@
<ant.contrib.version>1.0b3</ant.contrib.version>
<resteasy.version>2.3.4.Final</resteasy.version>
<freemarker.version>2.3.18</freemarker.version>
- <powermock.version>1.4.11</powermock.version>
+ <powermock.version>1.4.12</powermock.version>
<arquillian.version>1.0.1.Final</arquillian.version>
<xercesImpl.version>2.9.1-jbossas-2</xercesImpl.version> <!-- see BZ-820629 and CVE-2009-2625 -->
+ <!-- Note that this is DIFFERENT from the jboss-javassist defined above.
+ This version is used for org.javassist:javassist artifact that is used in
+ Arquillian integration, and works with jacoco (as opposed to javassist 3.9.0,
+ which doesn't in some cases.) -->
+ <javassist.version>3.16.1-GA</javassist.version>
+
<rhq.db.admin.username>rhqadmin</rhq.db.admin.username>
<rhq.db.admin.password>rhqadmin</rhq.db.admin.password>
@@ -195,6 +201,8 @@
<!-- The name of the file in the module's root dir that contains the intentional
api changes to be ignored by Clirr api checks -->
<intentional-api-changes-file>intentional-api-changes-since-${signature-check-base-version}.xml</intentional-api-changes-file>
+
+ <jacoco.version>0.6.0.201210061924</jacoco.version>
</properties>
@@ -496,6 +504,11 @@
<scope>import</scope>
</dependency>
+ <dependency>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <version>${javassist.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
@@ -594,18 +607,24 @@
</exclusion>
</exclusions>
</dependency>
-
- <!-- We must declare this here to workaround
- http://jira.codehaus.org/browse/MANTRUN-51.
- Once we require Maven 3.0, this will no
- no longer needed. -->
- <dependency>
- <groupId>net.sourceforge.cobertura</groupId>
- <artifactId>cobertura</artifactId>
- <version>${cobertura.version}</version>
- </dependency>
</dependencies>
- </plugin>
+
+ <executions>
+ <execution>
+ <id>pre-create target/classes</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <echo>Pre-creating target/classes so that Jacoco can see it even if there are no source files in the module.</echo>
+ <mkdir dir="${project.build.directory}/classes" />
+ </target>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
@@ -645,7 +664,7 @@
http://jira.codehaus.org/browse/SUREFIRE-836. -->
<version>2.11</version>
<configuration>
- <argLine>-Xms32M -Xmx512M</argLine>
+ <argLine>${jacoco.integration-test.args} -Xms32M -Xmx512M</argLine>
</configuration>
</plugin>
<plugin>
@@ -694,7 +713,7 @@
http://jira.codehaus.org/browse/SUREFIRE-836. -->
<version>2.11</version>
<configuration>
- <argLine>-Xms32M -Xmx512M</argLine>
+ <argLine>${jacoco.unit-test.args} -Xms32M -Xmx512M</argLine>
</configuration>
</plugin>
<plugin>
@@ -761,7 +780,13 @@
<artifactId>clirr-maven-plugin</artifactId>
<version>${clirr.version}</version>
</plugin>
- </plugins>
+
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>${jacoco.version}</version>
+ </plugin>
+ </plugins>
</pluginManagement>
@@ -1187,34 +1212,190 @@
<modules>
<module>modules</module>
+ <module>code-coverage</module>
</modules>
<profiles>
+ <!-- This profile is the "opposite" of the code coverage profile and provides
+ default values for properties that are set in the code-coverage profile
+ to kick of jacoco java agent. -->
+ <profile>
+ <id>no-code-coverage</id>
+ <activation>
+ <property>
+ <name>!code-coverage</name>
+ </property>
+ </activation>
+
+ <properties>
+ <jacoco.unit-test.args></jacoco.unit-test.args>
+ <jacoco.integration-test.args></jacoco.integration-test.args>
+ </properties>
+ </profile>
+
<profile>
<id>code-coverage</id>
-
+ <activation>
+ <property>
+ <name>code-coverage</name>
+ </property>
+ </activation>
<build>
<plugins>
+ <!-- This definition creates the 2 independent coverage reports -
+ separately for unit tests and integration tests -->
<plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>cobertura-maven-plugin</artifactId>
- <version>2.5.2</version>
- <configuration>
- <formats>
- <format>xml</format>
- </formats>
- </configuration>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
- <phase>post-integration-test</phase>
+ <id>prepare-agent-for-unit-tests</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ <configuration>
+ <destFile>${project.build.directory}/jacoco-unit-test.exec</destFile>
+ <propertyName>jacoco.unit-test.args</propertyName>
+ <includes>
+ <include>org.rhq.*</include>
+ </includes>
+ </configuration>
+ </execution>
+ <execution>
+ <id>prepare-agent-for-integration-tests</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ <configuration>
+ <destFile>${project.build.directory}/jacoco-integration-test.exec</destFile>
+ <propertyName>jacoco.integration-test.args</propertyName>
+ </configuration>
+ </execution>
+ <execution>
+ <id>report-unit-tests</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ <configuration>
+ <dataFile>${project.build.directory}/jacoco-unit-test.exec</dataFile>
+ <outputDirectory>${project.reporting.outputDirectory}/coverage-report/unit-tests</outputDirectory>
+ <includes>
+ <include>org/rhq/**</include>
+ </includes>
+ </configuration>
+ </execution>
+ <execution>
+ <id>report-integration-tests</id>
+ <!-- Run this very late so that test, integration-test
+ have already been completed -->
+ <phase>verify</phase>
<goals>
- <goal>cobertura</goal>
+ <goal>report</goal>
</goals>
+ <configuration>
+ <dataFile>${project.build.directory}/jacoco-integration-test.exec</dataFile>
+ <outputDirectory>${project.reporting.outputDirectory}/coverage-report/integration-tests</outputDirectory>
+ <includes>
+ <include>org/rhq/**</include>
+ </includes>
+ </configuration>
</execution>
</executions>
- </plugin>
+ </plugin>
+
+ <!-- The following insanity merges the two separate coverage reports
+ and produces an overall report - the total test coverage including
+ both unit and integration tests (defined in the same module).
+ If the integration test resides in a separate module, it is only
+ possible to deduce the coverage from report generated by the
+ top-level code-coverage module that merges all the coverage
+ reports in the whole build. -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <!-- Copy the ant tasks jar. Needed for org.jacoco.ant.ReportTask . -->
+ <execution>
+ <id>jacoco-dependency-ant</id>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <phase>process-test-resources</phase>
+ <inherited>false</inherited>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.jacoco</groupId>
+ <artifactId>org.jacoco.ant</artifactId>
+ <version>${jacoco.version}</version>
+ </artifactItem>
+ </artifactItems>
+ <stripVersion>true</stripVersion>
+ <outputDirectory>${project.build.directory}/jacoco-jars</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>overall-chart-creation</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <!-- Execute an ant task within maven -->
+ <echo message="Generating Overall JaCoCo Report" />
+ <taskdef name="report" classname="org.jacoco.ant.ReportTask">
+ <classpath path="${project.build.directory}/jacoco-jars/org.jacoco.ant.jar" />
+ </taskdef>
+ <mkdir dir="${project.reporting.outputDirectory}/coverage-report/overall" />
+ <report>
+ <executiondata>
+ <fileset dir="${project.build.directory}">
+ <include name="jacoco-unit-test.exec" />
+ <include name="jacoco-integration-test.exec" />
+ </fileset>
+ </executiondata>
+ <structure name="Overall Code Coverage Report (including unit and integration tests)">
+ <classfiles>
+ <fileset dir="${project.build.directory}">
+ <include name="classes/org/rhq/**" />
+ <include name="generated-classes/*/org/rhq/**" />
+ </fileset>
+ </classfiles>
+ <sourcefiles>
+ <dirset dir="${basedir}">
+ <include name="src/main/java" />
+ <include name="target/generated-sources/*" />
+ </dirset>
+ </sourcefiles>
+ </structure>
+ <html destdir="${project.reporting.outputDirectory}/coverage-report/overall" />
+ <xml destfile="${project.reporting.outputDirectory}/coverage-report/overall/jacoco.xml" />
+ <csv destfile="${project.reporting.outputDirectory}/coverage-report/overall/jacoco.csv" />
+ </report>
+ </target>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.jacoco</groupId>
+ <artifactId>org.jacoco.ant</artifactId>
+ <version>${jacoco.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
</plugins>
</build>
</profile>
11 years, 6 months
[rhq] Branch 'rhq-on-as7' - modules/enterprise
by Jay Shaughnessy
modules/enterprise/server/itests-2/pom.xml | 2
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java | 55 ++++---
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java | 71 ++++++----
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerServiceMBean.java | 2
4 files changed, 83 insertions(+), 47 deletions(-)
New commits:
commit f6c306d980152330d8ab8213d4181b1b66e4bf49
Author: Jay Shaughnessy <jshaughn(a)jshaughn.csb>
Date: Mon Oct 29 17:22:55 2012 -0400
One test passing but unprepare stuff not finishing smoothly. Still,
progress...
diff --git a/modules/enterprise/server/itests-2/pom.xml b/modules/enterprise/server/itests-2/pom.xml
index 5f9b4a0..c2fa2b1 100644
--- a/modules/enterprise/server/itests-2/pom.xml
+++ b/modules/enterprise/server/itests-2/pom.xml
@@ -573,7 +573,7 @@
</datasource>
<!-- FOR RHQ TESTING -->
<datasource jta="false" jndi-name="java:jboss/datasources/NoTxRHQDS" pool-name="NoTxRHQDS" enabled="true" use-java-context="true">
- <connection-url>${rhq.server.database.connection-url:jdbc:postgres://127.0.0.1:5432/rhq}</connection-url>
+ <connection-url>${rhq.server.database.connection-url:jdbc:postgresql://127.0.0.1:5432/rhq}</connection-url>
<connection-property name="char.encoding">
UTF-8
</connection-property>
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
index 8fe71cd..76c6686 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
@@ -45,12 +45,14 @@ import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
import org.rhq.enterprise.server.content.RepoException;
import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.content.metadata.ContentSourceMetadataManagerLocal;
+import org.rhq.enterprise.server.plugin.pc.content.TestContentServerPluginService;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TransactionCallback;
import org.rhq.enterprise.server.util.LookupUtil;
public class RepoManagerBeanTest extends AbstractEJB3Test {
- private final static boolean ENABLED = true;
+ private final static boolean ENABLED = false;
//@Inject
protected RepoManagerLocal repoManager;
@@ -73,6 +75,7 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
overlord = LookupUtil.getSubjectManager().getOverlord();
System.out.println("*** 1");
prepareScheduler();
+
System.out.println("*** 2");
repoManager = LookupUtil.getRepoManagerLocal();
System.out.println("*** 3");
@@ -80,39 +83,47 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
System.out.println("*** 4");
contentSourceMetadataManager = LookupUtil.getContentSourceMetadataManager();
System.out.println("*** 5");
- //TestContentServerPluginService pluginService = new TestContentServerPluginService(this);
- getTransactionManager().begin();
- System.out.println("*** 6");
+ // start mock plugin container
+ @SuppressWarnings("unused")
+ TestContentServerPluginService pluginService = new TestContentServerPluginService(this);
+ //getTransactionManager().begin();
+ //System.out.println("*** 6");
}
@Override
public void afterMethod() throws Exception {
System.out.println("*** 7");
unprepareServerPluginService();
+
System.out.println("*** 8");
unprepareScheduler();
+
System.out.println("*** 9");
- getTransactionManager().rollback();
- System.out.println("*** 10");
+ //getTransactionManager().rollback();
+ //System.out.println("*** 10");
}
- @Test(enabled = ENABLED)
+ @Test
+ // (enabled = ENABLED)
public void createABunchOfRepos() throws Exception {
- PageList<Repo> repos = repoManager.findRepos(overlord, new PageControl());
- int origsize = 0;
- if (repos != null) {
- origsize = repos.size();
- }
- for (int i = 0; i < 10; i++) {
- Random r = new Random(System.currentTimeMillis());
- Repo repo = new Repo(r.nextLong() + "");
- repoManager.createRepo(overlord, repo);
- }
- repos = repoManager.findRepos(overlord, new PageControl());
-
- assert repos.size() == (origsize + 10);
-
- System.out.println("*** 11");
+ executeInTransaction(new TransactionCallback() {
+
+ public void execute() throws Exception {
+ PageList<Repo> repos = repoManager.findRepos(overlord, new PageControl());
+ int origsize = 0;
+ if (repos != null) {
+ origsize = repos.size();
+ }
+ for (int i = 0; i < 10; i++) {
+ Random r = new Random(System.currentTimeMillis());
+ Repo repo = new Repo(r.nextLong() + "");
+ repoManager.createRepo(overlord, repo);
+ }
+ repos = repoManager.findRepos(overlord, new PageControl());
+
+ assert repos.size() == (origsize + 10);
+ }
+ });
}
@Test(enabled = ENABLED)
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
index 1167807..c62b521 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
@@ -46,7 +46,9 @@ import org.rhq.enterprise.server.auth.SessionManager;
import org.rhq.enterprise.server.core.plugin.PluginDeploymentScanner;
import org.rhq.enterprise.server.core.plugin.PluginDeploymentScannerMBean;
import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceMBean;
import org.rhq.enterprise.server.scheduler.SchedulerService;
+import org.rhq.enterprise.server.scheduler.SchedulerServiceMBean;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.test.AssertUtils;
import org.rhq.test.MatchResult;
@@ -59,7 +61,6 @@ public abstract class AbstractEJB3Test extends Arquillian {
private SchedulerService schedulerService;
private ServerPluginService serverPluginService;
- private MBeanServer dummyJBossMBeanServer;
private PluginDeploymentScannerMBean pluginScannerService;
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
@@ -84,6 +85,7 @@ public abstract class AbstractEJB3Test extends Arquillian {
dialect = "postgres";
}
+ @SuppressWarnings("unused")
String dataSourceXml;
if (dialect.toLowerCase().contains("postgres")) {
dataSourceXml = "jbossas-postgres-ds.xml";
@@ -551,11 +553,16 @@ public abstract class AbstractEJB3Test extends Arquillian {
*/
public void prepareCustomServerPluginService(ServerPluginService testServiceMBean) {
try {
- // TODO: Fix
- // MBeanServer mbs = getJBossMBeanServer();
- // testServiceMBean.start();
- // mbs.registerMBean(testServiceMBean, ServerPluginServiceMBean.OBJECT_NAME);
- // serverPluginService = testServiceMBean;
+ // first, unregister the real service...
+ MBeanServer mbs = getPlatformMBeanServer();
+ if (mbs.isRegistered(ServerPluginService.OBJECT_NAME)) {
+ mbs.unregisterMBean(ServerPluginService.OBJECT_NAME);
+ }
+
+ // Now replace with the test service...
+ testServiceMBean.start();
+ mbs.registerMBean(testServiceMBean, ServerPluginServiceMBean.OBJECT_NAME);
+ serverPluginService = testServiceMBean;
return;
} catch (Exception e) {
throw new RuntimeException(e);
@@ -570,17 +577,14 @@ public abstract class AbstractEJB3Test extends Arquillian {
if (serverPluginService != null) {
serverPluginService.stopMasterPluginContainer();
serverPluginService.stop();
+ MBeanServer mbs = getPlatformMBeanServer();
if (beanOnly) {
- // TODO: Fix
- // if (mbs.isRegistered(ServerPluginService.OBJECT_NAME)) {
- // getJBossMBeanServer().unregisterMBean(ServerPluginService.OBJECT_NAME);
- // }
- // if (mbs.isRegistered(ServerPluginServiceMBean.OBJECT_NAME)) {
- // getJBossMBeanServer().unregisterMBean(ServerPluginServiceMBean.OBJECT_NAME);
- // }
+ if (mbs.isRegistered(ServerPluginService.OBJECT_NAME)) {
+ mbs.unregisterMBean(ServerPluginService.OBJECT_NAME);
+ }
} else {
- // releaseJBossMBeanServer();
+ //MBeanServerFactory.releaseMBeanServer(mbs);
}
serverPluginService = null;
}
@@ -596,15 +600,35 @@ public abstract class AbstractEJB3Test extends Arquillian {
return;
}
+ // first, unregister the real service...
+ MBeanServer mbs = getPlatformMBeanServer();
+ if (mbs.isRegistered(SchedulerService.SCHEDULER_MBEAN_NAME)) {
+ mbs.unregisterMBean(SchedulerService.SCHEDULER_MBEAN_NAME);
+ }
+
+ // Now replace with the test service...
Properties quartzProps = new Properties();
quartzProps.load(this.getClass().getClassLoader().getResourceAsStream("test-scheduler.properties"));
schedulerService = new SchedulerService();
schedulerService.setQuartzProperties(quartzProps);
schedulerService.start();
- //getJBossMBeanServer().registerMBean(schedulerService, SchedulerServiceMBean.SCHEDULER_MBEAN_NAME);
+ mbs.registerMBean(schedulerService, SchedulerServiceMBean.SCHEDULER_MBEAN_NAME);
schedulerService.startQuartzScheduler();
- return;
+
+ // MBeanServer mbs = getPlatformMBeanServer();
+ // schedulerService = MBeanServerInvocationHandler.newProxyInstance(mbs,
+ // SchedulerServiceMBean.SCHEDULER_MBEAN_NAME, SchedulerServiceMBean.class, false);
+ //
+ // Properties quartzProps = new Properties();
+ // quartzProps.load(this.getClass().getClassLoader().getResourceAsStream("test-scheduler.properties"));
+ // //schedulerService = LookupUtil.getSchedulerBean();
+ // //schedulerService = new SchedulerService();
+ // schedulerService.setQuartzProperties(quartzProps);
+ // //schedulerService.start();
+ // //getJBossMBeanServer().registerMBean(schedulerService, SchedulerServiceMBean.SCHEDULER_MBEAN_NAME);
+ // schedulerService.startQuartzScheduler();
+ // return;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
@@ -617,17 +641,18 @@ public abstract class AbstractEJB3Test extends Arquillian {
public void unprepareScheduler(boolean beanOnly) throws Exception {
if (schedulerService != null) {
- schedulerService.stop();
+ //schedulerService.stop();
+ schedulerService = null;
+
+ MBeanServer mbs = getPlatformMBeanServer();
if (beanOnly) {
- // MBeanServer mbs = getJBossMBeanServer();
- // if (mbs.isRegistered(SchedulerServiceMBean.SCHEDULER_MBEAN_NAME)) {
- // getJBossMBeanServer().unregisterMBean(SchedulerServiceMBean.SCHEDULER_MBEAN_NAME);
- // }
+ if (mbs.isRegistered(SchedulerService.SCHEDULER_MBEAN_NAME)) {
+ mbs.unregisterMBean(SchedulerService.SCHEDULER_MBEAN_NAME);
+ }
} else {
- // releaseJBossMBeanServer();
+ //MBeanServerFactory.releaseMBeanServer(mbs);
}
- schedulerService = null;
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerServiceMBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerServiceMBean.java
index 84c7ba3..25a4453 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerServiceMBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerServiceMBean.java
@@ -44,7 +44,7 @@ import org.rhq.enterprise.server.operation.OperationManagerLocal;
/**
* MBean interface which is also the local interface to the scheduler SLSB. This is essentially the same interface as
- * the Quartz scheduler. We have both an MBean and SLSB fascade to Quartz - see {@link SchedulerLocal}.
+ * the Quartz scheduler. We have both an MBean and SLSB facade to Quartz - see {@link SchedulerLocal}.
*/
public interface SchedulerServiceMBean extends Scheduler {
/**
11 years, 6 months
[rhq] Branch 'rhq-on-as7' - .classpath modules/core modules/enterprise
by Jay Shaughnessy
.classpath | 2
modules/core/domain/pom.xml | 6
modules/enterprise/server/itests-2/pom.xml | 756 ++
modules/enterprise/server/itests-2/src/test/java/org/rhq/core/domain/util/units/test/MeasurementConverterTest.java | 390 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElementTest.java | 98
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java | 703 ++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java | 436 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/DeleteAlertsTest.java | 123
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/auth/test/SubjectManagerBeanTest.java | 571 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/authz/test/AuthorizationManagerBeanTest.java | 849 ++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/authz/test/RoleManagerBeanTest.java | 286
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java | 1195 ++++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/TestBundleServerPluginService.java | 244
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/TestBundleServerPluginServiceMBean.java | 24
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java | 606 ++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBeanTest.java | 1121 +++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBeanUnitTest.java | 575 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/DynamicConfigurationPropertyBeanTest.java | 176
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/LargeGroupPluginConfigurationTest.java | 243
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/LargeGroupResourceConfigurationTest.java | 227
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBeanTest.java | 277
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/metadata/test/ContentSourcePluginHandlingTest.java | 200
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/metadata/test/TestBase.java | 85
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/AdvisoryManagerBeanTest.java | 149
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentManagerBeanMockTest.java | 456 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentManagerBeanTest.java | 1720 +++++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java | 1205 ++++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentUIManagerBeanEligiblePackagesTest.java | 339 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentUIManagerBeanTest.java | 327 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java | 94
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ProductVersionManagerBeanTest.java | 177
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/QuartzScheduleFormatTest.java | 55
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java | 511 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/RepoSyncingTest.java | 271
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/core/CoreServerServiceImplTest.java | 503 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/core/plugin/DatabaseAndFilePluginDeploymentTest.java | 605 ++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/db/DbSetupTest.java | 70
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/db/DbUpgradeTest.java | 98
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/discovery/DeletedResourceTypeFilterTest.java | 190
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.java | 361 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/DriftManagerBeanTest.java | 426 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/TestDefService.java | 72
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/event/test/EventManagerTest.java | 193
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/inventory/InventoryManagerBeanTest.java | 187
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/inventory/UninventoryTest.java | 216
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/legacy/rss/DownloadPatchTest.java | 159
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/legacy/rss/RssFeedJobTest.java | 218
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/AbstractMeasurementScheduleManagerTest.java | 129
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/AvailabilityManagerTest.java | 1409 ++++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementBaselineManagerTest.java | 616 ++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementDataManagerTest.java | 737 ++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementScheduleManagerTest.java | 366 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementViewManagerTest.java | 142
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/operation/OperationManagerBeanTest.java | 1708 +++++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/performance/test/AvailabilityInsertPurgeTest.java | 411 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/performance/test/CallTimeInsertPurgeTest.java | 153
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/performance/test/EventsInsertPurgeTest.java | 170
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java | 420 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerSyncContentProviderTest.java | 321 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerSyncRepoTest.java | 312 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentSourcePackageDetailsKeyTest.java | 69
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentProvider.java | 351 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginService.java | 168
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginServiceMBean.java | 24
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java | 215
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java | 219
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginServiceMBean.java | 24
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestLifecycleListener.java | 91
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/cluster/ClusterManagerBeanTest.java | 213
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java | 964 +++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/GroupWithUncommittedTest.java | 273
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/LDAPStringUtilTest.java | 50
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/LargeGroupCriteriaTest.java | 350 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/LdapGroupManagerBeanTest.java | 511 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/RecursiveResourceGroupTest.java | 476 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/AlertMetadataManagerBeanTest.java | 64
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ContentMetadataManagerBeanTest.java | 127
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/EventMetadataManagerBeanTest.java | 69
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MeasurementMetadataManagerBeanTest.java | 238
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MetadataBeanTest.java | 321 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest.java | 152
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest.java | 169
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/OperationMetadataManagerBeanTest.java | 134
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest.java | 407 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest.java | 201
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest.java | 224
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java | 702 ++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/PluginDescriptorValidationTest.java | 121
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/SubcategoryTest.java | 54
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java | 1302 ++++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateContentSubsystemTest.java | 26
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateEventsSubsystemTest.java | 256
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateMeasurementSubsystemTest.java | 352 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateNativesSubsystemTest.java | 133
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateOperationsSubsystemTest.java | 381 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdatePluginMetadataTestBase.java | 452 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateResourceSubsystemTest.java | 805 ++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateResourceTypeSubsystemTest.java | 363 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceFactoryManagerBeanTest.java | 743 ++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceGroupManagerBeanTest.java | 174
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java | 267
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceStorageTest.java | 222
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceWithStatus.java | 48
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/scheduler/jobs/DataPurgeJobTest.java | 587 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/scheduler/jobs/RepoSyncJobTest.java | 117
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/search/GenericSearchAssistTest.java | 109
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/search/RHQLTest.java | 171
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/search/TestAutoCompletionManager.java | 83
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/DeployedAgentPluginsValidatorTest.java | 220
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/ExportingInputStreamTest.java | 458 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/MaxCountValidatorTest.java | 52
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/MetricTemplateExporterTest.java | 221
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/MetricTemplateImporterTest.java | 412 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SynchronizationManagerBeanTest.java | 740 ++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsExporterTest.java | 166
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsImporterTest.java | 119
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsValidatorTest.java | 59
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/UniquenessValidatorTest.java | 51
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/system/SystemManagerBeanTest.java | 163
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3PerformanceTest.java | 199
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java | 741 ++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/LargeGroupTestBase.java | 411 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/OldAbstractEJB3Test.java | 445 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StandardServerPluginService.java | 103
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StandardServerPluginServiceMBean.java | 31
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java | 378 +
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerCommunicationsService.java | 248
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerCommunicationsServiceMBean.java | 29
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java | 113
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerPluginServiceMBean.java | 25
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TransactionCallback.java | 7
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TransactionCallbackReturnable.java | 7
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/ldap/FakeLdapContext.java | 2950 ++++++++++
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/ldap/FakeLdapCtxFactory.java | 61
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/ldap/FakeNamingEnumeration.java | 76
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/CriteriaQueryTest.java | 125
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/DbSetupUtility.java | 259
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/JaxbTest.java | 38
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/LoggerAntBuildListener.java | 105
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/ResourceTreeHelper.java | 282
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/SessionTestHelper.java | 286
modules/enterprise/server/itests-2/src/test/resources/application.xml | 11
modules/enterprise/server/itests-2/src/test/resources/arquillian.xml | 20
modules/enterprise/server/itests-2/src/test/resources/binary-blob-sample.jar |binary
modules/enterprise/server/itests-2/src/test/resources/default.persistence.properties | 22
modules/enterprise/server/itests-2/src/test/resources/ejb-jar.xml | 41
modules/enterprise/server/itests-2/src/test/resources/ejb3-interceptors-aop.xml | 360 +
modules/enterprise/server/itests-2/src/test/resources/jboss-deployment-structure.xml | 31
modules/enterprise/server/itests-2/src/test/resources/jboss-jms-beans.xml | 132
modules/enterprise/server/itests-2/src/test/resources/jbossas-oracle-ds.xml | 36
modules/enterprise/server/itests-2/src/test/resources/jbossas-postgres-ds.xml | 40
modules/enterprise/server/itests-2/src/test/resources/log4j.xml | 99
modules/enterprise/server/itests-2/src/test/resources/logging/log4j.properties | 17
modules/enterprise/server/itests-2/src/test/resources/login-config.xml | 72
modules/enterprise/server/itests-2/src/test/resources/obsolete/embedded-jboss-beans.xml | 168
modules/enterprise/server/itests-2/src/test/resources/obsolete/testng.bak.xml | 12
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.xml | 84
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/configuration/metadata/configuration_metadata_manager_bean_test_v1.xml | 95
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/configuration/metadata/configuration_metadata_manager_bean_test_v2.xml | 120
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.xml | 98
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-1.txt | 5
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-1.zip |binary
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-2.txt | 5
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-2.zip |binary
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/inventory/InventoryManagerBeanTest.xml | 121
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/AlertMetadataManagerBeanTest/plugin_v1.xml | 8
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/AlertMetadataManagerBeanTest/plugin_v2.xml | 7
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ContentMetadataManagerBeanTest/plugin_v1.xml | 45
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ContentMetadataManagerBeanTest/plugin_v2.xml | 49
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/EventMetadataManagerBeanTest/plugin_v1.xml | 23
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/EventMetadataManagerBeanTest/plugin_v2.xml | 23
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MeasurementMetadataManagerBeanTest/plugin_v1.xml | 48
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MeasurementMetadataManagerBeanTest/plugin_v2.xml | 40
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MetadataTest.xml | 298 +
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/child1_plugin_v1.xml | 19
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/child2_plugin_v1.xml | 19
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/parent_plugin_v1.xml | 18
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/parent_plugin_v2.xml | 18
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/child_plugin_v1.xml | 29
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/parent_plugin_v1.xml | 24
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/parent_plugin_v2.xml | 24
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/OperationMetadataManagerBeanTest/plugin_v1.xml | 42
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/OperationMetadataManagerBeanTest/plugin_v2.xml | 41
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/child_plugin_v1.xml | 17
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/parent_plugin_v1.xml | 49
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/parent_plugin_v2.xml | 67
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_1.xml | 7
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_2.xml | 10
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_3.xml | 8
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/child1_plugin_v1.xml | 19
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/child2_plugin_v1.xml | 19
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/parent_plugin_v1.xml | 18
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/parent_plugin_v2.xml | 18
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/dup_drift.xml | 19
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/parent_resource_type-plugin.xml | 29
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/plugin_v1.xml | 92
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/plugin_v2.xml | 110
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_bundle_drift_config_v1.xml | 20
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_bundle_drift_config_v2.xml | 7
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_types_v1.xml | 54
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_types_v2.xml | 8
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_plugin_v1.xml | 59
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_plugin_v2.xml | 73
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_remove_types_v1.xml | 54
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_remove_types_v2.xml | 8
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/util/db-data-combined-2.3.1.xml | 663 ++
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/util/db-schema-combined-2.3.1.xml | 1916 ++++++
modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/util/test-ds.properties | 7
modules/enterprise/server/itests-2/src/test/resources/perftest/AvailabilityInsertPurgeTest-testOne-data.xml.zip |binary
modules/enterprise/server/itests-2/src/test/resources/persistence.jar |binary
modules/enterprise/server/itests-2/src/test/resources/persistence.xml | 53
modules/enterprise/server/itests-2/src/test/resources/rhq-mdb-beans.xml | 25
modules/enterprise/server/itests-2/src/test/resources/security-beans.xml | 13
modules/enterprise/server/itests-2/src/test/resources/serverplugins/simple-generic-serverplugin.xml | 17
modules/enterprise/server/itests-2/src/test/resources/single-line-rhql.txt | 91
modules/enterprise/server/itests-2/src/test/resources/test-assist-color-number.txt | 46
modules/enterprise/server/itests-2/src/test/resources/test-ldap.properties | 2
modules/enterprise/server/itests-2/src/test/resources/test-scheduler.properties | 29
modules/enterprise/server/itests-2/src/test/resources/test/all_no_tx_ds.xml | 97
modules/enterprise/server/itests-2/src/test/resources/test/app_auth_type_ds.xml | 32
modules/enterprise/server/itests-2/src/test/resources/test/bad.xsl | 6
modules/enterprise/server/itests-2/src/test/resources/test/container_and_app_auth_type_ds.xml | 32
modules/enterprise/server/itests-2/src/test/resources/test/container_auth_type_ds.xml | 32
modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.0-feb-2.xml | 3
modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.0-feb.xml | 3
modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.0-june.xml | 3
modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.1-feb.xml | 3
modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.1-june.xml | 3
modules/enterprise/server/itests-2/src/test/resources/test/generic_ds.xml | 66
modules/enterprise/server/itests-2/src/test/resources/test/hsqldb_ds.xml | 106
modules/enterprise/server/itests-2/src/test/resources/test/hsqldb_encrypted_ds.xml | 125
modules/enterprise/server/itests-2/src/test/resources/test/informix_ds.xml | 34
modules/enterprise/server/itests-2/src/test/resources/test/metadata/alerts/type-with-metric.xml | 14
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/BZ_573034_v1.xml | 12
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/BZ_573034_v2.xml | 12
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/addDeleteTemplate1.xml | 14
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/addDeleteTemplate2.xml | 17
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/addDeleteTemplate3.xml | 17
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/constraint.xml | 24
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/constraintMinMax.xml | 17
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupDeleted-v1.xml | 28
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupDeleted-v2.xml | 14
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v1.xml | 27
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v2.xml | 28
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v3.xml | 315 +
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v4.xml | 275
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropMoved-v1.xml | 27
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropMoved-v2.xml | 27
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyChanging-v1.xml | 39
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyChanging-v2.xml | 44
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyList-simple.xml | 16
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyList-v1.xml | 46
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyList-v2.xml | 61
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyMap-v1.xml | 35
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyMap-v2.xml | 49
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/update5-v1_0.xml | 84
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/update5-v2_0.xml | 96
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/updateDefaultTemplate1.xml | 14
modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/updateDefaultTemplate2.xml | 14
modules/enterprise/server/itests-2/src/test/resources/test/metadata/content-source-update-v1.xml | 48
modules/enterprise/server/itests-2/src/test/resources/test/metadata/content-source-update-v2.xml | 49
modules/enterprise/server/itests-2/src/test/resources/test/metadata/events/event1-1.xml | 10
modules/enterprise/server/itests-2/src/test/resources/test/metadata/events/event1-2.xml | 11
modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/measurementDeletion-v1_0.xml | 12
modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/measurementDeletion-v2_0.xml | 10
modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update-v1_0.xml | 14
modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update-v2_0.xml | 20
modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update6-1.xml | 12
modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update6-2.xml | 12
modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update7-1.xml | 10
modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update7-2.xml | 11
modules/enterprise/server/itests-2/src/test/resources/test/metadata/natives/update5-v1_0.xml | 84
modules/enterprise/server/itests-2/src/test/resources/test/metadata/natives/update5-v2_0.xml | 96
modules/enterprise/server/itests-2/src/test/resources/test/metadata/noTypes.xml | 8
modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation1-1.xml | 11
modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation1-2.xml | 27
modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation2-1.xml | 17
modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation2-2.xml | 19
modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation3-1.xml | 18
modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation3-2.xml | 20
modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/update3-v1_0.xml | 60
modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/update3-v2_0.xml | 67
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/duplicateResourceType.xml | 11
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update2-v1_0.xml | 16
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update2-v2_0.xml | 16
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update4-v1_0.xml | 16
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update4-v2_0.xml | 12
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/updateResourceTypeBundleTarget-v1.xml | 27
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/updateResourceTypeBundleTarget-v2.xml | 23
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/illegal-subcat-1.xml | 15
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-2children.xml | 16
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-grandchild.xml | 17
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-services-v1_0.xml | 21
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-services-v2_0.xml | 19
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-v1_0.xml | 15
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-v1_1.xml | 15
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-v2_0.xml | 15
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/no-subcat.xml | 10
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v1_0.xml | 13
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v1_1.xml | 13
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v2_0.xml | 13
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v3_0.xml | 13
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/services-v1_0.xml | 13
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/services-v2_0.xml | 12
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/test-subcategories.xml | 26
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/test-subcategories2.xml | 26
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/test-subcategories3.xml | 33
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/two-subcat.xml | 13
modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/undefined-child-subcat-1.xml | 21
modules/enterprise/server/itests-2/src/test/resources/test/minimal_hsqldb_ds.xml | 24
modules/enterprise/server/itests-2/src/test/resources/test/msaccess_ds.xml | 32
modules/enterprise/server/itests-2/src/test/resources/test/no_auth_type_ds.xml | 32
modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_2_ds.xml | 44
modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_3_ds.xml | 43
modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_4_ds.xml | 42
modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_5_ds.xml | 40
modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_ds.xml | 44
modules/enterprise/server/itests-2/src/test/resources/test/too_many_ds.xml | 106
modules/enterprise/server/itests-2/src/test/resources/test/xpath_processor_test.xml | 42
modules/enterprise/server/itests-2/src/test/resources/transform/template_ds.xml | 6
modules/enterprise/server/itests-2/src/test/resources/transform/transform.xsl | 514 +
modules/enterprise/server/itests-2/src/test/resources/validation/datasourceResources.properties | 142
modules/enterprise/server/itests-2/src/test/resources/validation/datasource_validation.xml | 159
modules/enterprise/server/itests-2/src/test/resources/validation/default_validator_rules.xml | 47
modules/enterprise/server/itests-2/src/test/resources/velocity/local-datasource.vm | 8
modules/enterprise/server/itests/pom.xml | 6
modules/enterprise/server/jar/pom.xml | 112
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java | 14
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java | 30
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java | 34
modules/enterprise/server/jar/src/test/resources/application.xml | 11
modules/enterprise/server/jar/src/test/resources/arquillian.xml | 20
modules/enterprise/server/jar/src/test/resources/ejb-jar.xml | 41
modules/enterprise/server/jar/src/test/resources/embedded-jboss-beans.xml | 168
modules/enterprise/server/jar/src/test/resources/jbossas-oracle-ds.xml | 36
modules/enterprise/server/jar/src/test/resources/jbossas-postgres-ds.xml | 40
modules/enterprise/server/jar/src/test/resources/jndi.properties | 2
modules/enterprise/server/jar/src/test/resources/obsolete/embedded-jboss-beans.xml | 168
modules/enterprise/server/jar/src/test/resources/obsolete/testng.bak.xml | 12
modules/enterprise/server/jar/src/test/resources/test-persistence.xml | 53
modules/enterprise/server/jar/src/test/resources/testng.bak.xml | 12
341 files changed, 58670 insertions(+), 263 deletions(-)
New commits:
commit 0ce98632df3d6d03d16ebb485fde970460571b30
Author: Jay Shaughnessy <jshaughn(a)jshaughn.csb>
Date: Fri Oct 26 17:41:04 2012 -0400
IN PROGRESS: Server JAR Test Migration to Arquillian
- moving tests to new server/itests-2 module
- not yet in full build
- not yet working
diff --git a/.classpath b/.classpath
index 5570123..d8ecdc6 100644
--- a/.classpath
+++ b/.classpath
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="modules/common/ant-bundle/src/main/java"/>
+ <classpathentry kind="src" path="modules/enterprise/server/itests-2/src/test/java"/>
<classpathentry kind="src" path="modules/enterprise/scripting/javascript/src/main/java"/>
<classpathentry kind="src" path="modules/enterprise/scripting/python/src/main/java"/>
<classpathentry kind="src" path="modules/enterprise/scripting/python/src/test/java"/>
@@ -47,7 +48,6 @@
<classpathentry kind="src" path="modules/enterprise/server/xml-schemas/src/test/java"/>
<classpathentry kind="src" path="modules/enterprise/server/xml-schemas/target/generated-sources/xjc"/>
<classpathentry kind="src" path="modules/enterprise/server/jar/src/main/java"/>
- <classpathentry kind="src" path="modules/enterprise/server/jar/src/test/java"/>
<classpathentry kind="src" path="modules/enterprise/server/jar/target/generated-sources/antlr3"/>
<classpathentry kind="src" path="modules/enterprise/binding/src/main/java"/>
<classpathentry kind="src" path="modules/enterprise/binding/src/test/java"/>
diff --git a/modules/core/domain/pom.xml b/modules/core/domain/pom.xml
index 3279067..50f1857 100644
--- a/modules/core/domain/pom.xml
+++ b/modules/core/domain/pom.xml
@@ -338,6 +338,12 @@
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
+ <properties>
+ <property>
+ <name>listener</name>
+ <value>org.rhq.test.testng.StdoutReporter</value>
+ </property>
+ </properties>
<systemProperties>
<property>
<name>ejbjarDirectory</name>
diff --git a/modules/enterprise/server/itests-2/pom.xml b/modules/enterprise/server/itests-2/pom.xml
new file mode 100644
index 0000000..5f9b4a0
--- /dev/null
+++ b/modules/enterprise/server/itests-2/pom.xml
@@ -0,0 +1,756 @@
+<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-parent</artifactId>
+ <version>4.6.0-SNAPSHOT</version>
+ <relativePath>../../../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>rhq-server-itests-2</artifactId>
+
+ <name>RHQ Server JAR Integration Tests</name>
+ <description>RHQ enterprise server JAR integration tests</description>
+
+ <scm>
+ <connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/enterprise/server/...</connection>
+ <developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/enterprise/server/...</developerConnection>
+ </scm>
+
+ <properties>
+ <jboss.zip>${settings.localRepository}/org/jboss/as/jboss-as-dist/${jboss.version}/jboss-as-dist-${jboss.version}.zip</jboss.zip>
+ <jboss.unzip.location>${basedir}/target/jboss-as-${jboss.version}</jboss.unzip.location>
+
+ <!--
+ <rhq.server.datasource>java:/RHQDS</rhq.server.datasource>
+ <rhq.server.ds-mapping>PostgreSQL</rhq.server.ds-mapping>
+ -->
+ <!-- <jboss-embeddable-ejb3.version>1.0.0.Alpha9</jboss-embeddable-ejb3.version> -->
+ </properties>
+
+ <dependencies>
+ <!--================ Test Deps ================ -->
+
+ <!-- Note, the test dep ordering can be important. Maven orders the [test] classpath in the order listed
+ in the pom. -->
+
+ <dependency>
+ <groupId>org.jboss.as</groupId>
+ <artifactId>jboss-as-dist</artifactId>
+ <type>zip</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.spec</groupId>
+ <artifactId>jboss-javaee-6.0</artifactId>
+ <version>${jboss.javaee6.spec.version}</version>
+ <scope>provided</scope>
+ <type>pom</type>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.as</groupId>
+ <artifactId>jboss-as-arquillian-container-managed</artifactId>
+ <version>${jboss.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.testng</groupId>
+ <artifactId>arquillian-testng-container</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap</groupId>
+ <artifactId>shrinkwrap-impl-base</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.resolver</groupId>
+ <artifactId>shrinkwrap-resolver-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.resolver</groupId>
+ <artifactId>shrinkwrap-resolver-api-maven</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.resolver</groupId>
+ <artifactId>shrinkwrap-resolver-impl-maven</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.protocol</groupId>
+ <artifactId>arquillian-protocol-servlet</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-domain</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-domain</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-core-client-api</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>test-utils</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq.helpers</groupId>
+ <artifactId>perftest-support</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opensymphony.quartz</groupId>
+ <artifactId>quartz</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.liquibase</groupId>
+ <artifactId>liquibase-core</artifactId>
+ <version>2.0.3</version>
+ <scope>test</scope>
+ </dependency>
+
+
+ <!--
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-server</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-script-bindings</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-server</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-scripting-javascript</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-server-client-api</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-server</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <exclusions>
+ <exclusion>
+ <groupId>ant</groupId>
+ <artifactId>ant</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>ant</groupId>
+ <artifactId>ant-launcher</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ -->
+ <!-- Shrinkwrap to build up test plugins etc. -->
+
+ <!--
+ <dependency>
+ <groupId>org.jboss.shrinkwrap</groupId>
+ <artifactId>shrinkwrap-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap</groupId>
+ <artifactId>shrinkwrap-impl-base</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ -->
+
+ <!-- NOTE: The remaining test deps correspond to the classes contained in hibernate-all.jar and thirdparty-all.jar. -->
+
+ <!--
+ <dependency>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ -->
+ <!-- needed by embedded ejb container -->
+ <!--
+ <dependency>
+ <groupId>trove</groupId>
+ <artifactId>trove</artifactId>
+ <version>1.0.2</version>
+ <scope>test</scope>
+ </dependency>
+ -->
+ <!-- needed by embedded ejb container -->
+ <!--
+ <dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ <version>${xercesImpl.version}</version>
+ <scope>test</scope>
+ </dependency>
+ -->
+ <!-- 3rd Party Deps -->
+
+ <!-- required by RHQ server classes, as well as EJB3 Embedded -->
+ <!--
+ <dependency>
+ <groupId>dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ <version>1.6.1-jboss</version>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.mail</groupId>
+ <artifactId>mail</artifactId>
+ <version>1.4</version>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.4</version>
+ <scope>provided
+ </dependency>
+
+
+ <dependency>
+ <groupId>org.opensymphony.quartz</groupId>
+ <artifactId>quartz-oracle</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ -->
+ <!-- This is needed cglib which is in turn needed by hibernate -->
+
+ <!--
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <version>2.2</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.freemarker</groupId>
+ <artifactId>freemarker</artifactId>
+ <version>2.3.18</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ <version>${resteasy.version}</version>
+ </dependency>
+
+ -->
+ <!-- Dependencies for RHQ components needed for integration tests -->
+ <!--
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-serverplugin-drift</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ -->
+ </dependencies>
+
+
+ <build>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ <filtering>true</filtering>
+ </testResource>
+ </testResources>
+
+ <plugins>
+ <!--
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ -->
+ <!-- in order to get JMS to work properly in embedded test container, extract jms-rs.rar classes -->
+ <!--
+ <execution>
+ <id>Extract JMS classes from RAR needed for JMS tests</id>
+ <phase>process-classes</phase>
+ <configuration>
+ <target>
+ <unzip
+ src="src/test/resources/jms-ra.rar"
+ dest="target">
+ <patternset>
+ <include name="jms-ra.jar" />
+ </patternset>
+ </unzip>
+ <unzip
+ src="target/jms-ra.jar"
+ dest="target/test-classes">
+ <patternset>
+ <include name="org/**" />
+ </patternset>
+ </unzip>
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ -->
+
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+
+ <execution>
+ <id>prepare AS container</id>
+ <phase>process-test-resources</phase>
+ <configuration>
+ <target>
+ <echo>Unzipping JBossAS ${jboss.version} found at ${jboss.zip}</echo>
+ <unzip
+ src="${jboss.zip}"
+ dest="${jboss.unzip.location}/.." />
+ <echo>JBossAS ${jboss.version} should now be at: ${jboss.unzip.location}</echo>
+ <property
+ name="jboss.conf"
+ location="${jboss.unzip.location}/standalone/configuration/standalone.xml" />
+ <echo>Will now add test configuration to JBossAS config file: ${jboss.conf}</echo>
+ <replace file="${jboss.conf}">
+
+ <replacefilter>
+ <replacetoken></security-domains></replacetoken>
+ <replacevalue><![CDATA[
+ <!-- FOR RHQ TESTING -->
+ <security-domain name="RHQDSSecurityDomain" cache-type="default">
+ <authentication>
+ <login-module code="SecureIdentity" flag="required">
+ <module-option name="username" value="rhqadmin"/>
+ <module-option name="password" value="1eeb2f255e832171df8592078de921bc"/>
+ </login-module>
+ </authentication>
+ </security-domain>
+ </security-domains>]]></replacevalue>
+ </replacefilter>
+
+ <replacefilter>
+ <replacetoken></session-bean></replacetoken>
+ <replacevalue><![CDATA[
+ </session-bean>
+ <!-- FOR RHQ TESTING -->
+ <mdb>
+ <resource-adapter-ref resource-adapter-name="hornetq-ra"/>
+ <bean-instance-pool-ref pool-name="mdb-strict-max-pool"/>
+ </mdb>]]></replacevalue>
+ </replacefilter>
+
+ <replacefilter>
+ <replacetoken><extension module="org.jboss.as.naming"/></replacetoken>
+ <replacevalue><![CDATA[
+ <!-- FOR RHQ TESTING -->
+ <extension module="org.jboss.as.messaging"/>
+ <extension module="org.jboss.as.naming"/>]]></replacevalue>
+ </replacefilter>
+
+ <replacefilter>
+ <replacetoken><socket-binding name="https" port="8443"/></replacetoken>
+ <replacevalue><![CDATA[
+ <socket-binding name="https" port="8443"/>
+ <!-- FOR RHQ TESTING -->
+ <socket-binding name="messaging" port="${rhq.server.socket.binding.port.messaging:4445}"/>
+ <socket-binding name="messaging-throughput" port="${rhq.server.socket.binding.port.messaging-throughput:4455}"/>]]></replacevalue>
+ </replacefilter>
+
+ <replacefilter>
+ <replacetoken><subsystem xmlns="urn:jboss:domain:naming:1.1"/></replacetoken>
+ <replacevalue><![CDATA[
+ <!-- FOR RHQ TESTING -->
+ <subsystem xmlns="urn:jboss:domain:messaging:1.1">
+ <hornetq-server>
+ <persistence-enabled>true</persistence-enabled>
+ <journal-file-size>102400</journal-file-size>
+ <journal-min-files>2</journal-min-files>
+
+ <connectors>
+ <netty-connector name="netty" socket-binding="messaging"/>
+ <netty-connector name="netty-throughput" socket-binding="messaging-throughput">
+ <param key="batch-delay" value="50"/>
+ </netty-connector>
+ <in-vm-connector name="in-vm" server-id="0"/>
+ </connectors>
+
+ <acceptors>
+ <netty-acceptor name="netty" socket-binding="messaging"/>
+ <netty-acceptor name="netty-throughput" socket-binding="messaging-throughput">
+ <param key="batch-delay" value="50"/>
+ <param key="direct-deliver" value="false"/>
+ </netty-acceptor>
+ <in-vm-acceptor name="in-vm" server-id="0"/>
+ </acceptors>
+
+ <security-settings>
+ <security-setting match="#">
+ <permission type="send" roles="guest"/>
+ <permission type="consume" roles="guest"/>
+ <permission type="createNonDurableQueue" roles="guest"/>
+ <permission type="deleteNonDurableQueue" roles="guest"/>
+ </security-setting>
+ </security-settings>
+
+ <address-settings>
+ <address-setting match="#">
+ <dead-letter-address>jms.queue.DLQ</dead-letter-address>
+ <expiry-address>jms.queue.ExpiryQueue</expiry-address>
+ <redelivery-delay>0</redelivery-delay>
+ <max-size-bytes>10485760</max-size-bytes>
+ <address-full-policy>BLOCK</address-full-policy>
+ <message-counter-history-day-limit>10</message-counter-history-day-limit>
+ </address-setting>
+ </address-settings>
+
+ <jms-connection-factories>
+ <connection-factory name="InVmConnectionFactory">
+ <connectors>
+ <connector-ref connector-name="in-vm"/>
+ </connectors>
+ <entries>
+ <entry name="java:/ConnectionFactory"/>
+ </entries>
+ </connection-factory>
+ <connection-factory name="RemoteConnectionFactory">
+ <connectors>
+ <connector-ref connector-name="netty"/>
+ </connectors>
+ <entries>
+ <entry name="RemoteConnectionFactory"/>
+ <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>
+ </entries>
+ </connection-factory>
+ <pooled-connection-factory name="hornetq-ra">
+ <transaction mode="xa"/>
+ <connectors>
+ <connector-ref connector-name="in-vm"/>
+ </connectors>
+ <entries>
+ <entry name="java:/JmsXA"/>
+ </entries>
+ </pooled-connection-factory>
+ </jms-connection-factories>
+
+ <jms-destinations>
+ <jms-queue name="testQueue">
+ <entry name="queue/test"/>
+ <entry name="java:jboss/exported/jms/queue/test"/>
+ </jms-queue>
+ <jms-queue name="AlertConditionQueue">
+ <entry name="queue/AlertConditionQueue"/>
+ <durable>true</durable>
+ </jms-queue>
+ <jms-queue name="DriftChangesetQueue">
+ <entry name="queue/DriftChangesetQueue"/>
+ <durable>true</durable>
+ </jms-queue>
+ <jms-queue name="DriftFileQueue">
+ <entry name="queue/DriftFileQueue"/>
+ <durable>true</durable>
+ </jms-queue>
+ <jms-topic name="testTopic">
+ <entry name="topic/test"/>
+ <entry name="java:jboss/exported/jms/topic/test"/>
+ </jms-topic>
+ </jms-destinations>
+ </hornetq-server>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:naming:1.1"/>]]></replacevalue>
+ </replacefilter>
+
+ <replacefilter>
+ <replacetoken></datasource></replacetoken>
+ <replacevalue><![CDATA[
+ </datasource>
+ <!-- FOR RHQ TESTING -->
+ <datasource jta="false" jndi-name="java:jboss/datasources/NoTxRHQDS" pool-name="NoTxRHQDS" enabled="true" use-java-context="true">
+ <connection-url>${rhq.server.database.connection-url:jdbc:postgres://127.0.0.1:5432/rhq}</connection-url>
+ <connection-property name="char.encoding">
+ UTF-8
+ </connection-property>
+ <driver>postgres</driver>
+ <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
+ <pool>
+ <min-pool-size>2</min-pool-size>
+ <max-pool-size>5</max-pool-size>
+ </pool>
+ <security>
+ <security-domain>RHQDSSecurityDomain</security-domain>
+ </security>
+ <validation>
+ <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker"/>
+ <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter"/>
+ </validation>
+ <timeout>
+ <blocking-timeout-millis>30000</blocking-timeout-millis>
+ <idle-timeout-minutes>15</idle-timeout-minutes>
+ </timeout>
+ <statement>
+ <prepared-statement-cache-size>75</prepared-statement-cache-size>
+ </statement>
+ </datasource>
+ <xa-datasource jta="true" jndi-name="java:jboss/datasources/RHQDS" pool-name="RHQDS" enabled="true" use-java-context="true">
+ <xa-datasource-property name="DatabaseName">
+ ${rhq.server.database.db-name:rhq}
+ </xa-datasource-property>
+ <xa-datasource-property name="PortNumber">
+ ${rhq.server.database.port:5432}
+ </xa-datasource-property>
+ <xa-datasource-property name="ServerName">
+ ${rhq.server.database.server-name:127.0.0.1}
+ </xa-datasource-property>
+ <driver>postgres</driver>
+ <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
+ <xa-pool>
+ <min-pool-size>5</min-pool-size>
+ <max-pool-size>50</max-pool-size>
+ </xa-pool>
+ <security>
+ <security-domain>RHQDSSecurityDomain</security-domain>
+ </security>
+ <validation>
+ <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker"/>
+ <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter"/>
+ </validation>
+ <timeout>
+ <blocking-timeout-millis>30000</blocking-timeout-millis>
+ <idle-timeout-minutes>15</idle-timeout-minutes>
+ </timeout>
+ <statement>
+ <prepared-statement-cache-size>75</prepared-statement-cache-size>
+ </statement>
+ </xa-datasource>]]></replacevalue>
+ </replacefilter>
+
+ <replacefilter>
+ <replacetoken></drivers></replacetoken>
+ <replacevalue><![CDATA[
+ <!-- FOR RHQ TESTING -->
+ <driver name="postgres" module="org.rhq.postgres">
+ <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
+ </driver>
+ <driver name="oracle" module="org.rhq.oracle">
+ <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
+ </driver>
+ </drivers>]]></replacevalue>
+ </replacefilter>
+
+ <replacefilter>
+ <replacetoken></cache-container></replacetoken>
+ <replacevalue><![CDATA[
+ </cache-container>
+ <!-- FOR RHQ TESTING -->
+ <cache-container name="rhq" jndi-name="java:jboss/infinispan/rhq">
+ <local-cache name="rhqCache">
+ <transaction mode="NONE"/>
+ <eviction strategy="LRU" max-entries="50000"/>
+ <expiration max-idle="100000"/>
+ </local-cache>
+ </cache-container>]]></replacevalue>
+ </replacefilter>
+
+ </replace>
+
+ <property
+ name="jboss.modules.dir"
+ location="${jboss.unzip.location}/modules" />
+ <echo>Adding JDBC modules to ${jboss.modules.dir} ...</echo>
+ <copy
+ file="${settings.localRepository}/com/oracle/ojdbc6/${ojdbc6.version}/ojdbc6-${ojdbc6.version}.jar"
+ toDir="${jboss.modules.dir}/org/rhq/oracle/main"
+ failonerror="false"
+ verbose="true" />
+ <echo file="${jboss.modules.dir}/org/rhq/oracle/main/module.xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<module xmlns="urn:jboss:module:1.1" name="org.rhq.oracle">
+ <resources>
+ <resource-root path="ojdbc6-${ojdbc6.version}.jar"/>
+ </resources>
+ <dependencies>
+ <module name="javax.api"/>
+ <module name="javax.transaction.api"/>
+ </dependencies>
+</module>
+]]></echo>
+ <copy
+ file="${settings.localRepository}/postgresql/postgresql/${postgresql.version}/postgresql-${postgresql.version}.jar"
+ toDir="${jboss.modules.dir}/org/rhq/postgres/main"
+ verbose="true" />
+ <echo file="${jboss.modules.dir}/org/rhq/postgres/main/module.xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<module xmlns="urn:jboss:module:1.1" name="org.rhq.postgres">
+ <resources>
+ <resource-root path="postgresql-${postgresql.version}.jar"/>
+ </resources>
+ <dependencies>
+ <module name="javax.api"/>
+ <module name="javax.transaction.api"/>
+ </dependencies>
+</module>
+]]></echo>
+
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+
+ <configuration>
+ <skipTests>true</skipTests>
+ <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+ <groups>${rhq.testng.includedGroups}</groups>
+ <properties>
+ <property>
+ <name>listener</name>
+ <value>org.rhq.test.testng.StdoutReporter</value>
+ </property>
+ </properties>
+ <systemPropertyVariables>
+ <embeddedDeployment>true</embeddedDeployment>
+ <deploymentDirectory>target/classes</deploymentDirectory>
+ <hibernate.dialect>${rhq.test.ds.hibernate-dialect}</hibernate.dialect>
+ <clean.db>${clean.db}</clean.db>
+ <log4j.configDebug>false</log4j.configDebug>
+ </systemPropertyVariables>
+ <additionalClasspathElements>
+ <!-- The below is required for tests to run against Oracle. -->
+ <additionalClasspathElement>${settings.localRepository}/com/oracle/ojdbc6/${ojdbc6.version}/ojdbc6-${ojdbc6.version}.jar</additionalClasspathElement>
+ </additionalClasspathElements>
+ </configuration>
+
+ <executions>
+
+ <execution>
+ <id>allExceptDbTests</id>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <skipTests>${skipTests}</skipTests>
+ <excludes>
+ <exclude>com/**/*.java</exclude>
+ <exclude>org/rhq/**/performance/**/*.java</exclude>
+ <exclude>org/rhq/enterprise/server/db/**</exclude>
+ </excludes>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/core/domain/util/units/test/MeasurementConverterTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/core/domain/util/units/test/MeasurementConverterTest.java
new file mode 100644
index 0000000..b4f64e4
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/core/domain/util/units/test/MeasurementConverterTest.java
@@ -0,0 +1,390 @@
+/*
+ * 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, 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.core.domain.util.units.test;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.rhq.core.server.MeasurementConverter;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.measurement.composite.MeasurementNumericValueAndUnits;
+import org.rhq.core.domain.measurement.util.MeasurementConversionException;
+import org.rhq.core.server.MeasurementParser;
+
+// TODO two tests in here need to be re-enables once the GWT client issues are resolved
+@Test
+public class MeasurementConverterTest extends AbstractEJB3Test {
+ private final double POSITIVE = 300;
+ private final double NEGATIVE = -42;
+
+ private final String[] WHITESPACE = new String[] { " ", "\f", "\n", "\r", "\t" };
+
+ private ThreadLocal<Integer> precisionScalingTestCount = null;
+
+ private void incrementPrecisionScalingTestCount() {
+ if (precisionScalingTestCount == null) {
+ precisionScalingTestCount = new ThreadLocal<Integer>() {
+ @Override
+ protected Integer initialValue() {
+ return 0;
+ }
+ };
+ }
+ precisionScalingTestCount.set(precisionScalingTestCount.get() + 1);
+ }
+
+ @Test(groups = "integration.ejb3", enabled = false)
+ // TODO fix me
+ public void testPrecisionScaling() throws Exception {
+
+ // if all values are equal, it will format to the max precision
+
+ testPrecisionScaling(new double[] { 1.41, 1.41, 1.41, 1.41, 1.41 }, MeasurementUnits.NONE, new String[] {
+ "1.41", "1.41", "1.41", "1.41", "1.41" }, MeasurementUnits.NONE);
+
+ // if all values are unique, it won't need to format any of them to more digits
+ testPrecisionScaling(new double[] { 1.41, 1.42, 1.43, 1.44, 1.45 }, MeasurementUnits.NONE, new String[] {
+ "1.41", "1.42", "1.43", "1.44", "1.45" }, MeasurementUnits.NONE);
+
+ // even if only two are equal, it will scale all the way to max precision looking for uniqueness
+ testPrecisionScaling(new double[] { 1.4, 1.4, 1.5, 1.6, 1.7 }, MeasurementUnits.NONE, new String[] { "1.4",
+ "1.4", "1.5", "1.6", "1.7" }, MeasurementUnits.NONE);
+
+ // to final a "good looking" target scaling units, it will use the mathematical mean
+ // NOTE: formatting doesn't round up/down, thus introducing error from cutting digits (256 -> 0.2KB [instead of 0.25KB])
+ testPrecisionScaling(new double[] { 128, 256, 512, 1024, 8192 }, MeasurementUnits.BYTES, new String[] {
+ "0.1KB", "0.2KB", "0.5KB", "1KB", "8KB" }, MeasurementUnits.KILOBYTES);
+
+ // same test with negative numbers
+ testPrecisionScaling(new double[] { -128, -256, -512, -1024, -8192 }, MeasurementUnits.BYTES, new String[] {
+ "-0.1KB", "-0.2KB", "-0.5KB", "-1KB", "-8KB" }, MeasurementUnits.KILOBYTES);
+
+ // test self scaling relative units
+ testPrecisionScaling(new double[] { 0.0, 0.065, 1.0, 0.123456 }, MeasurementUnits.PERCENTAGE, new String[] {
+ "0%", "6.5%", "100%", "12.3%" }, MeasurementUnits.PERCENTAGE);
+
+ // test self scaling relative units
+ testPrecisionScaling(new double[] { 0.0621, 0.065, 0.0620, 0.6202 }, MeasurementUnits.PERCENTAGE, new String[] {
+ "6.21%", "6.5%", "6.2%", "62.02%" }, MeasurementUnits.PERCENTAGE);
+ }
+
+ private void testPrecisionScaling(double[] values, MeasurementUnits units, String[] expectedResults,
+ MeasurementUnits expectedUnits) {
+ incrementPrecisionScalingTestCount();
+
+ String[] results = MeasurementConverter.formatToSignificantPrecision(values, units, true);
+ for (int i = 0; i < results.length; i++) {
+ String expected = expectedResults[i];
+ String actual = results[i];
+
+ // The expected output is in Locale.US. Handle running the tests in a different default locale
+ if (expected.contains(".") && (!Locale.getDefault().equals(Locale.US))) {
+ Locale defaultLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ MeasurementNumericValueAndUnits vu = MeasurementParser.parse(expected, expectedUnits);
+ Locale.setDefault(defaultLocale);
+ expected = MeasurementConverter.format(vu.getValue(), expectedUnits, false, null, 4);
+ }
+
+ assert actual.equals(expected) : "Test " + precisionScalingTestCount.get() + ": " + "Index " + i + ", "
+ + "Expected " + expected + ", " + "Received " + actual + ", " + "Units " + units.getName();
+ }
+ }
+
+ @Test(groups = "integration.ejb3", enabled = false)
+ // TODO fix me
+ public void testConversionSuccess() throws Exception {
+ // test the straight-forward, non-whitespace cases
+ for (MeasurementUnits units : MeasurementUnits.values()) {
+ validateFormatConvert(POSITIVE, units);
+ validateFormatConvert(NEGATIVE, units);
+ }
+
+ List<String> signVariations;
+ List<String> magnitudeVariations;
+ List<String> unitsVariations;
+
+ // use the same NumberFormat that the MeasurementConverter uses, so that we get the correct expected results
+ NumberFormat nf = DecimalFormat.getNumberInstance();
+ nf.setMinimumFractionDigits(1);
+ nf.setMaximumFractionDigits(1);
+
+ // test a couple hundred thousand variations of whitespace around each positive number with units
+ signVariations = getWhitespaceVariationsAroundSingleTokens("", "+");
+ magnitudeVariations = getWhitespaceVariationsAroundSingleTokens(nf.format(POSITIVE));
+ for (MeasurementUnits units : MeasurementUnits.values()) {
+ unitsVariations = getWhitespaceVariationsAroundSingleTokens(units.toString());
+
+ // splice all combinations together and test conversion validity
+ for (String signVariation : signVariations) {
+ for (String magnitudeVariation : magnitudeVariations) {
+ if (MeasurementUnits.Family.RELATIVE == units.getFamily()) {
+ magnitudeVariation = nf.format(MeasurementUnits.scaleUp(nf.parse(magnitudeVariation.trim())
+ .doubleValue(), units));
+ }
+
+ for (String unitVariation : unitsVariations) {
+ String original = MeasurementConverter.format(POSITIVE, units, false);
+ String toBeTested = magnitudeVariation.trim() + unitVariation.trim();
+
+ assert original.equals(toBeTested) : "Error constructing whitespace string: " + "Expected '"
+ + original + "', " + "Received '" + toBeTested + "' " + "for units '" + units.name() + "'";
+
+ validateConvert(POSITIVE, signVariation + magnitudeVariation + unitVariation, units);
+ }
+ }
+ }
+ }
+
+ // test a couple hundred thousand variations of whitespace around each negative number with units
+ signVariations = getWhitespaceVariationsAroundSingleTokens("-");
+ for (MeasurementUnits units : MeasurementUnits.values()) {
+ unitsVariations = getWhitespaceVariationsAroundSingleTokens(units.toString());
+
+ for (String signVariation : signVariations) {
+ for (String magnitudeVariation : magnitudeVariations) {
+ if (units == MeasurementUnits.PERCENTAGE) {
+ magnitudeVariation = nf.format(100 * nf.parse(magnitudeVariation.trim()).doubleValue());
+ }
+
+ for (String unitVariation : unitsVariations) {
+ String original = MeasurementConverter.format(-POSITIVE, units, false);
+ String toBeTested = "-" + magnitudeVariation.trim() + unitVariation.trim();
+
+ assert original.equals(toBeTested) : "Error constructing whitespace string: " + "Expected '"
+ + original + "', " + "Received '" + toBeTested + "' " + "for units '" + units.name() + "'";
+
+ validateConvert(-POSITIVE, signVariation + magnitudeVariation + unitVariation, units);
+ }
+ }
+ }
+ }
+ }
+
+ @Test(groups = "integration.ejb3")
+ public void testScalingSuccess() throws Exception {
+ // Family.BYTES
+ validateScaleAndInverse(1024.0, MeasurementUnits.BYTES, 1.0, MeasurementUnits.KILOBYTES);
+ validateScaleAndInverse(1048576.0, MeasurementUnits.BYTES, 1.0, MeasurementUnits.MEGABYTES);
+ validateScaleAndInverse(1073741824.0, MeasurementUnits.BYTES, 1.0, MeasurementUnits.GIGABYTES);
+ validateScaleAndInverse(1099511627776.0, MeasurementUnits.BYTES, 1.0, MeasurementUnits.TERABYTES);
+ validateScaleAndInverse(1125899906842624.0, MeasurementUnits.BYTES, 1.0, MeasurementUnits.PETABYTES);
+
+ validateScaleAndInverse(1024.0, MeasurementUnits.KILOBYTES, 1.0, MeasurementUnits.MEGABYTES);
+ validateScaleAndInverse(1048576.0, MeasurementUnits.KILOBYTES, 1.0, MeasurementUnits.GIGABYTES);
+ validateScaleAndInverse(1073741824.0, MeasurementUnits.KILOBYTES, 1.0, MeasurementUnits.TERABYTES);
+ validateScaleAndInverse(1099511627776.0, MeasurementUnits.KILOBYTES, 1.0, MeasurementUnits.PETABYTES);
+
+ validateScaleAndInverse(1024.0, MeasurementUnits.MEGABYTES, 1.0, MeasurementUnits.GIGABYTES);
+ validateScaleAndInverse(1048576.0, MeasurementUnits.MEGABYTES, 1.0, MeasurementUnits.TERABYTES);
+ validateScaleAndInverse(1073741824.0, MeasurementUnits.MEGABYTES, 1.0, MeasurementUnits.PETABYTES);
+
+ validateScaleAndInverse(1024.0, MeasurementUnits.GIGABYTES, 1.0, MeasurementUnits.TERABYTES);
+ validateScaleAndInverse(1048576.0, MeasurementUnits.GIGABYTES, 1.0, MeasurementUnits.PETABYTES);
+
+ validateScaleAndInverse(1024.0, MeasurementUnits.TERABYTES, 1.0, MeasurementUnits.PETABYTES);
+
+ // Family.BITS
+ validateScaleAndInverse(1024.0, MeasurementUnits.BITS, 1.0, MeasurementUnits.KILOBITS);
+ validateScaleAndInverse(1048576.0, MeasurementUnits.BITS, 1.0, MeasurementUnits.MEGABITS);
+ validateScaleAndInverse(1073741824.0, MeasurementUnits.BITS, 1.0, MeasurementUnits.GIGABITS);
+ validateScaleAndInverse(1099511627776.0, MeasurementUnits.BITS, 1.0, MeasurementUnits.TERABITS);
+ validateScaleAndInverse(1125899906842624.0, MeasurementUnits.BITS, 1.0, MeasurementUnits.PETABITS);
+
+ validateScaleAndInverse(1024.0, MeasurementUnits.KILOBITS, 1.0, MeasurementUnits.MEGABITS);
+ validateScaleAndInverse(1048576.0, MeasurementUnits.KILOBITS, 1.0, MeasurementUnits.GIGABITS);
+ validateScaleAndInverse(1073741824.0, MeasurementUnits.KILOBITS, 1.0, MeasurementUnits.TERABITS);
+ validateScaleAndInverse(1099511627776.0, MeasurementUnits.KILOBITS, 1.0, MeasurementUnits.PETABITS);
+
+ validateScaleAndInverse(1024.0, MeasurementUnits.MEGABITS, 1.0, MeasurementUnits.GIGABITS);
+ validateScaleAndInverse(1048576.0, MeasurementUnits.MEGABITS, 1.0, MeasurementUnits.TERABITS);
+ validateScaleAndInverse(1073741824.0, MeasurementUnits.MEGABITS, 1.0, MeasurementUnits.PETABITS);
+
+ validateScaleAndInverse(1024.0, MeasurementUnits.GIGABITS, 1.0, MeasurementUnits.TERABITS);
+ validateScaleAndInverse(1048576.0, MeasurementUnits.GIGABITS, 1.0, MeasurementUnits.PETABITS);
+
+ validateScaleAndInverse(1024.0, MeasurementUnits.TERABITS, 1.0, MeasurementUnits.PETABITS);
+
+ // Family.DURATION
+ validateScaleAndInverse(1000.0, MeasurementUnits.EPOCH_MILLISECONDS, 1.0, MeasurementUnits.EPOCH_SECONDS);
+
+ // Family.TIME
+ validateScaleAndInverse(1000.0, MeasurementUnits.MILLISECONDS, 1.0, MeasurementUnits.SECONDS);
+ validateScaleAndInverse(60000.0, MeasurementUnits.MILLISECONDS, 1.0, MeasurementUnits.MINUTES);
+ validateScaleAndInverse(3600000.0, MeasurementUnits.MILLISECONDS, 1.0, MeasurementUnits.HOURS);
+ validateScaleAndInverse(86400000.0, MeasurementUnits.MILLISECONDS, 1.0, MeasurementUnits.DAYS);
+
+ validateScaleAndInverse(60.0, MeasurementUnits.SECONDS, 1.0, MeasurementUnits.MINUTES);
+ validateScaleAndInverse(3600.0, MeasurementUnits.SECONDS, 1.0, MeasurementUnits.HOURS);
+ validateScaleAndInverse(86400.0, MeasurementUnits.SECONDS, 1.0, MeasurementUnits.DAYS);
+
+ validateScaleAndInverse(60.0, MeasurementUnits.MINUTES, 1.0, MeasurementUnits.HOURS);
+ validateScaleAndInverse(1440.0, MeasurementUnits.MINUTES, 1.0, MeasurementUnits.DAYS);
+
+ validateScaleAndInverse(24.0, MeasurementUnits.HOURS, 1.0, MeasurementUnits.DAYS);
+ }
+
+ private void validateScaleAndInverse(double fromValue, MeasurementUnits fromUnits, double toValue,
+ MeasurementUnits toUnits) {
+ validateScale(fromValue, fromUnits, toValue, toUnits);
+ validateScale(toValue, toUnits, fromValue, fromUnits);
+ }
+
+ private void validateScale(double fromValue, MeasurementUnits fromUnits, double toValue, MeasurementUnits toUnits) {
+ MeasurementNumericValueAndUnits valueAndUnits = new MeasurementNumericValueAndUnits(fromValue, fromUnits);
+ try {
+ double derived = MeasurementConverter.scale(valueAndUnits, toUnits);
+ assert Math.abs(toValue - derived) < 1e-9 : "Scale conversion error: " +
+
+ "From value '" + fromValue + "', " + "with units of '" + fromUnits.name() + "', " + "displayed as '"
+ + fromUnits + "', " +
+
+ "To value '" + toValue + "', " + "with units of '" + toUnits.name() + "', " + "displayed as '"
+ + toUnits + "', " +
+
+ "Received value '" + derived + "'";
+
+ } catch (MeasurementConversionException mce) {
+ assert false : "Unexpected MeasurementConversionException: " +
+
+ "From value '" + fromValue + "', " + "with units of '" + fromUnits.name() + "', " + "displayed as '"
+ + fromUnits + "', " +
+
+ "To value '" + toValue + "', " + "with units of '" + toUnits.name() + "', " + "displayed as '"
+ + toUnits;
+ }
+ }
+
+ private void validateFormatConvert(double value, MeasurementUnits units) {
+ validateFormatConvert(value, value, units);
+ }
+
+ private void validateFormatConvert(double passedValue, double expectedValue, MeasurementUnits units) {
+ try {
+ String intermediate = MeasurementConverter.format(passedValue, units, false);
+ MeasurementNumericValueAndUnits results = MeasurementParser.parse(intermediate, units);
+
+ assert (Math.abs(results.getValue() - expectedValue) < 1e-9 && results.getUnits() == units) : "double input was '"
+ + passedValue
+ + "', "
+ + "units input was '"
+ + units.name()
+ + "', "
+ +
+
+ "intermediate string was '"
+ + intermediate
+ + "', "
+ +
+
+ "Expected value '"
+ + expectedValue
+ + "', "
+ + "with units of '"
+ + units.name()
+ + "', "
+ + "displayed as '"
+ + units
+ + "', "
+ +
+
+ "Received value '"
+ + results.getValue()
+ + "', "
+ + "with units of '"
+ + results.getUnits().getName()
+ + "', " + "displayed as '" + results.getUnits() + "'";
+ } catch (MeasurementConversionException mce) {
+ assert false : "Error during conversion: " + mce.getMessage();
+ }
+ }
+
+ private void validateConvert(double value, String intermediate, MeasurementUnits units) {
+ validateConvert(value, value, intermediate, units);
+ }
+
+ private void validateConvert(double passedValue, double expectedValue, String intermediate, MeasurementUnits units) {
+ try {
+ MeasurementNumericValueAndUnits results = MeasurementParser.parse(intermediate, units);
+
+ assert (Math.abs(results.getValue() - expectedValue) < 1e-9 && results.getUnits() == units) : "double input was '"
+ + passedValue
+ + "', "
+ + "units input was '"
+ + units.name()
+ + "', "
+ +
+
+ "intermediate string was '"
+ + intermediate
+ + "', "
+ +
+
+ "Expected value '"
+ + expectedValue
+ + "', "
+ + "with units of '"
+ + units.name()
+ + "', "
+ + "displayed as '"
+ + units
+ + "', "
+ +
+
+ "Received value '"
+ + results.getValue()
+ + "', "
+ + "with units of '"
+ + results.getUnits().getName()
+ + "', " + "displayed as '" + results.getUnits() + "'";
+ } catch (MeasurementConversionException mce) {
+ assert false : "Error during conversion: " + mce.getMessage();
+ }
+ }
+
+ private List<String> getWhitespaceVariationsAroundSingleTokens(String... tokens) {
+ List<String> variations = new ArrayList<String>();
+
+ for (String token : tokens) {
+ for (String white : WHITESPACE) {
+ variations.add(token);
+ //variations.add( token + white );
+ //variations.add( white + token );
+ //variations.add( white + token + white );
+
+ variations.add(token + white + white);
+ //variations.add( white + white + token );
+ //variations.add( white + white + token + white + white );
+ }
+ }
+
+ return variations;
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElementTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElementTest.java
new file mode 100644
index 0000000..eb01b1c
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElementTest.java
@@ -0,0 +1,98 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.alert.engine.model;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.alert.AlertConditionOperator;
+
+/**
+ * there are two ways we can check the value compared to the range, each with either inclusivness or exclusivness.
+ * inclusive means if value equals either the lo or hi, it is considered inside the range.
+ * exclusive means if value equals either the lo or hi, it is NOT considered inside the range, it is outside the range
+ * < - if the value is inside the range (i.e. between the low and high values), exclusive
+ * > - if the value is outside the range (i.e. lower than the low value or higher than the high value), exclusive
+ * <= - if the value is inside the range (i.e. between the low and high values), inclusive
+ * >= - if the value is outside the range (i.e. lower than the low value or higher than the high value), inclusive
+ *
+ * Example:
+ * Given a value of 20, with a low-high range of 20...50.
+ * < (inside, exclusive) - NO match - 20 is not considered inside the range but we are looking for values inside the range
+ * > (outside, exclusive) - MATCH - 20 is not considered inside the range and we are looking for values outside the range
+ * <= (inside, inclusive) - MATCH - 20 is considered inside the range and we are looking for values inside the range
+ * >= (outside, inclusive) - NO match - 20 is considered inside the range but we are looking for values outside the range
+ */
+@Test
+public class MeasurementRangeNumericCacheElementTest {
+ private final Double lo = Double.valueOf(20.0);
+ private final Double hi = Double.valueOf(50.0);
+ private final Double inside = Double.valueOf(30.0); // inside the range
+ private final Double outsideLo = Double.valueOf(1.0); // outside the range on the lo side
+ private final Double outsideHi = Double.valueOf(111.0); // outside the range on the hi side
+
+ public void testInsideExclusive() {
+ MeasurementRangeNumericCacheElement ele = createCacheElement(AlertConditionOperator.LESS_THAN);
+ assert true == ele.matches(inside);
+ assert false == ele.matches(outsideLo);
+ assert false == ele.matches(outsideHi);
+ assert false == ele.matches(lo);
+ assert false == ele.matches(hi);
+ }
+
+ public void testOutsideExclusive() {
+ MeasurementRangeNumericCacheElement ele = createCacheElement(AlertConditionOperator.GREATER_THAN);
+ assert false == ele.matches(inside);
+ assert true == ele.matches(outsideLo);
+ assert true == ele.matches(outsideHi);
+ assert true == ele.matches(lo);
+ assert true == ele.matches(hi);
+ }
+
+ public void testInsideInclusive() {
+ MeasurementRangeNumericCacheElement ele = createCacheElement(AlertConditionOperator.LESS_THAN_OR_EQUAL_TO);
+ assert true == ele.matches(inside);
+ assert false == ele.matches(outsideLo);
+ assert false == ele.matches(outsideHi);
+ assert true == ele.matches(lo);
+ assert true == ele.matches(hi);
+ }
+
+ public void testOutsideInclusive() {
+ MeasurementRangeNumericCacheElement ele = createCacheElement(AlertConditionOperator.GREATER_THAN_OR_EQUAL_TO);
+ assert false == ele.matches(inside);
+ assert true == ele.matches(outsideLo);
+ assert true == ele.matches(outsideHi);
+ assert false == ele.matches(lo);
+ assert false == ele.matches(hi);
+ }
+
+ public void testUnsupportedComparator() {
+ try {
+ createCacheElement(AlertConditionOperator.EQUALS);
+ assert false : "should not be able to support EQUALS";
+ } catch (Exception ok) {
+ // this is OK and to be expected
+ }
+ }
+
+ private MeasurementRangeNumericCacheElement createCacheElement(AlertConditionOperator op) {
+ return new MeasurementRangeNumericCacheElement(op, lo, hi, 0);
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java
new file mode 100644
index 0000000..97694e3
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java
@@ -0,0 +1,703 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.alert.test;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.transaction.TransactionManager;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.alert.Alert;
+import org.rhq.core.domain.alert.AlertCondition;
+import org.rhq.core.domain.alert.AlertConditionCategory;
+import org.rhq.core.domain.alert.AlertConditionLog;
+import org.rhq.core.domain.alert.AlertConditionOperator;
+import org.rhq.core.domain.alert.AlertDampening;
+import org.rhq.core.domain.alert.AlertDampening.Category;
+import org.rhq.core.domain.alert.AlertDefinition;
+import org.rhq.core.domain.alert.AlertPriority;
+import org.rhq.core.domain.alert.BooleanExpression;
+import org.rhq.core.domain.cloud.Server;
+import org.rhq.core.domain.criteria.AlertCriteria;
+import org.rhq.core.domain.criteria.ResourceCriteria;
+import org.rhq.core.domain.discovery.AvailabilityReport;
+import org.rhq.core.domain.discovery.AvailabilityReport.Datum;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementSchedule;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
+import org.rhq.enterprise.server.alert.AlertManagerLocal;
+import org.rhq.enterprise.server.measurement.AvailabilityManagerLocal;
+import org.rhq.enterprise.server.measurement.MeasurementDataManagerLocal;
+import org.rhq.enterprise.server.resource.metadata.test.UpdatePluginMetadataTestBase;
+import org.rhq.enterprise.server.scheduler.SchedulerLocal;
+import org.rhq.enterprise.server.scheduler.jobs.AlertAvailabilityDurationJob;
+import org.rhq.enterprise.server.test.TransactionCallbackReturnable;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.test.JPAUtils;
+import org.rhq.test.TransactionCallbackWithContext;
+
+@Test
+public class AlertConditionTest extends UpdatePluginMetadataTestBase {
+ private static final boolean ENABLED = true;
+
+ // this must match the constant found in ServerManagerBean
+ private static final String RHQ_SERVER_NAME_PROPERTY = "rhq.server.high-availability.name";
+ private static final String RHQ_SERVER_NAME_PROPERTY_VALUE = "AlertConditionTestServer";
+
+ private Resource resource;
+ private Server server;
+
+ @Override
+ protected String getSubsystemDirectory() {
+ return "alerts";
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void removePersistedResource() throws Exception {
+ if (resource != null) {
+ deleteNewResource(resource);
+ resource = null;
+ }
+
+ deleteServerIdentity();
+
+ return;
+ }
+
+ @BeforeClass(alwaysRun = true)
+ public void setSysProp() {
+ System.setProperty(RHQ_SERVER_NAME_PROPERTY, RHQ_SERVER_NAME_PROPERTY_VALUE);
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void unsetSysProp() {
+ System.setProperty(RHQ_SERVER_NAME_PROPERTY, "");
+ }
+
+ @Test(enabled = ENABLED)
+ public void testBZ735262_InsideRangeCondition() throws Exception {
+ // create our resource with alert definition
+ MeasurementDefinition metricDef = createResourceWithMetricSchedule();
+ createAlertDefinitionWithOneInsideRangeCondition(metricDef, resource.getId()); // this test would fail if we used createAlertDefinitionWithTwoConditionsALL
+
+ // re-load the resource so we get the measurement schedule
+ Resource resourceWithSchedules = loadResourceWithSchedules(resource.getId());
+ MeasurementSchedule schedule = resourceWithSchedules.getSchedules().iterator().next();
+
+ // simulate a measurement report coming from the agent - two values, but neither fit in our range, so no alerts are fired
+ MeasurementScheduleRequest request = new MeasurementScheduleRequest(schedule);
+ MeasurementReport report = new MeasurementReport();
+ report.addData(new MeasurementDataNumeric(getTimestamp(60), request, Double.valueOf(20.0))); // 20 < 60 but !(20 > 40)
+ report.addData(new MeasurementDataNumeric(getTimestamp(30), request, Double.valueOf(70.0))); // !(70 < 60) but 70 > 40
+ MeasurementDataManagerLocal dataManager = LookupUtil.getMeasurementDataManager();
+ dataManager.mergeMeasurementReport(report);
+
+ // wait for our JMS messages to process and see if we get any alerts
+ Thread.sleep(5000);
+
+ // make sure no alert was triggered
+ PageList<Alert> alerts = getAlerts(resourceWithSchedules.getId());
+ assert alerts.size() == 0 : "no alerts should have fired: " + alerts;
+
+ // simulate another measurement report coming from the agent - one values that fits in our range, so 1 alert is fired
+ request = new MeasurementScheduleRequest(schedule);
+ report = new MeasurementReport();
+ report.addData(new MeasurementDataNumeric(getTimestamp(15), request, Double.valueOf(50.0))); // 50 < 60 AND 50 > 40
+ dataManager.mergeMeasurementReport(report);
+
+ // wait for our JMS messages to process and see if we get any alerts
+ Thread.sleep(5000);
+
+ // make sure one alert was triggered
+ alerts = getAlerts(resourceWithSchedules.getId());
+ assert alerts.size() == 1 : "1 alert should have fired: " + alerts;
+ return;
+ }
+
+ @Test(enabled = ENABLED)
+ public void testBZ735262_OutsideRangeCondition() throws Exception {
+ // create our resource with alert definition
+ MeasurementDefinition metricDef = createResourceWithMetricSchedule();
+ createAlertDefinitionWithOneOutsideRangeCondition(metricDef, resource.getId()); // this test would fail if we used createAlertDefinitionWithTwoConditionsALL
+
+ // re-load the resource so we get the measurement schedule
+ Resource resourceWithSchedules = loadResourceWithSchedules(resource.getId());
+ MeasurementSchedule schedule = resourceWithSchedules.getSchedules().iterator().next();
+
+ // simulate a measurement report coming from the agent - one value that is inside our range, so no alerts are fired
+ MeasurementScheduleRequest request = new MeasurementScheduleRequest(schedule);
+ MeasurementReport report = new MeasurementReport();
+ report.addData(new MeasurementDataNumeric(getTimestamp(60), request, Double.valueOf(50.0))); // 50 is inside the range 40...60
+ MeasurementDataManagerLocal dataManager = LookupUtil.getMeasurementDataManager();
+ dataManager.mergeMeasurementReport(report);
+
+ // wait for our JMS messages to process and see if we get any alerts
+ Thread.sleep(5000);
+
+ // make sure no alert was triggered
+ PageList<Alert> alerts = getAlerts(resourceWithSchedules.getId());
+ assert alerts.size() == 0 : "no alerts should have fired: " + alerts;
+
+ // simulate another measurement report coming from the agent - one value that is outside the range, so 1 alert is fired
+ request = new MeasurementScheduleRequest(schedule);
+ report = new MeasurementReport();
+ report.addData(new MeasurementDataNumeric(getTimestamp(15), request, Double.valueOf(20.0))); // 20 is outside 40...60
+ dataManager.mergeMeasurementReport(report);
+
+ // wait for our JMS messages to process and see if we get any alerts
+ Thread.sleep(5000);
+
+ // make sure one alert was triggered
+ alerts = getAlerts(resourceWithSchedules.getId());
+ assert alerts.size() == 1 : "1 alert should have fired: " + alerts;
+ return;
+ }
+
+ @Test(enabled = ENABLED)
+ public void testBZ736685_DeleteConditionLogButNoAlert() throws Exception {
+ // create our resource with alert definition
+ MeasurementDefinition metricDef = createResourceWithMetricSchedule();
+ AlertDefinition alertDef = createAlertDefinitionWithTwoConditionsALL(metricDef, resource.getId());
+
+ // re-load the resource so we get the measurement schedule
+ Resource resourceWithSchedules = loadResourceWithSchedules(resource.getId());
+ MeasurementSchedule schedule = resourceWithSchedules.getSchedules().iterator().next();
+
+ // simulate a measurement report coming from the agent
+ // with a single metric that makes a condition trigger but does not fire an alert
+ MeasurementScheduleRequest request = new MeasurementScheduleRequest(schedule);
+ MeasurementReport report = new MeasurementReport();
+ report.addData(new MeasurementDataNumeric(getTimestamp(60), request, Double.valueOf(20.0))); // 20 < 60 but !(20 > 40)
+ MeasurementDataManagerLocal dataManager = LookupUtil.getMeasurementDataManager();
+ dataManager.mergeMeasurementReport(report);
+
+ // wait for our JMS messages to process and see if we get any alerts
+ Thread.sleep(5000);
+
+ PageList<Alert> alerts = getAlerts(resourceWithSchedules.getId());
+ assert alerts.size() == 0 : "no alerts should have fired: " + alerts;
+
+ // ...but make sure a condition was true (the condition we know is true is "< 60")
+ int condId = 0;
+ for (AlertCondition cond : alertDef.getConditions()) {
+ if (cond.getComparator().equals("<")) {
+ condId = cond.getId();
+ break;
+ }
+ }
+ assert condId > 0 : "failed to get the condition ID - something is wrong with test setup";
+ AlertCondition conditionWithLogs = getAlertConditionWithLogs(condId); // should eagerly load logs
+ Set<AlertConditionLog> logs = conditionWithLogs.getConditionLogs();
+ assert logs != null && logs.size() > 0 : "missing condition log - we should have one that was generated";
+ AlertConditionLog log = logs.iterator().next();
+ assert log.getAlert() == null : "condition should not have fired an alert: " + logs;
+
+ // purge the resource fully, which should remove all alert defs and alert conditions and condition logs
+ int resourceId = resource.getId();
+ deleteNewResource(resource);
+ resource = null;
+
+ AlertDefinitionManagerLocal alertDefManager = LookupUtil.getAlertDefinitionManager();
+ PageList<AlertDefinition> defs = alertDefManager.findAlertDefinitions(getOverlord(), resourceId,
+ PageControl.getUnlimitedInstance());
+ assert defs.isEmpty() : "failed to delete the alert definition - are condition logs still around?";
+
+ return;
+ }
+
+ @Test(enabled = ENABLED)
+ public void testAvailChangeAlert() throws Exception {
+ // create our resource with alert definition
+ MeasurementDefinition metricDef = createResourceWithMetricSchedule();
+ createAlertDefinitionWithAvailChangeCondition(resource.getId(), AlertConditionOperator.AVAIL_GOES_DOWN);
+ createAlertDefinitionWithAvailChangeCondition(resource.getId(), AlertConditionOperator.AVAIL_GOES_NOT_UP);
+
+ // resource has initial UNKNOWN ResourceAvailability and no Availability records. simulate an avail report
+ // coming from the agent and setting the initial avail to UP.
+ AvailabilityReport availReport = new AvailabilityReport(AGENT_NAME);
+ availReport.addAvailability(new Datum(resource.getId(), AvailabilityType.UP, System.currentTimeMillis()));
+ AvailabilityManagerLocal availManager = LookupUtil.getAvailabilityManager();
+ availManager.mergeAvailabilityReport(availReport);
+
+ // wait for our JMS messages to process and see if we get any alerts
+ Thread.sleep(3000);
+
+ PageList<Alert> alerts = getAlerts(resource.getId());
+ assert alerts.size() == 0 : "No alert should have fired on the initial avail reporting: " + alerts;
+
+ // Now simulate the down avail
+ availReport = new AvailabilityReport(AGENT_NAME);
+ availReport
+ .addAvailability(new Datum(resource.getId(), AvailabilityType.DOWN, System.currentTimeMillis() + 10));
+ availManager.mergeAvailabilityReport(availReport);
+
+ // wait for our JMS messages to process and see if we get any alerts
+ Thread.sleep(3000);
+
+ alerts = getAlerts(resource.getId());
+ assert alerts.size() == 2 : "Two alerts should have fired on the avail change: " + alerts;
+
+ assert !alerts.get(0).getAlertDefinition().getName().equals(alerts.get(1).getAlertDefinition().getName()) : "Alerts should have been from different definitions";
+
+ // purge the resource fully, which should remove all alert defs and alert conditions and condition logs
+ int resourceId = resource.getId();
+ deleteNewResource(resource);
+ resource = null;
+
+ AlertDefinitionManagerLocal alertDefManager = LookupUtil.getAlertDefinitionManager();
+ PageList<AlertDefinition> defs = alertDefManager.findAlertDefinitions(getOverlord(), resourceId,
+ PageControl.getUnlimitedInstance());
+ assert defs.isEmpty() : "failed to delete the alert definition - are condition logs still around?";
+
+ return;
+ }
+
+ @Test(enabled = ENABLED)
+ public void testAvailDurationAlert() throws Exception {
+ try {
+ prepareScheduler();
+ SchedulerLocal scheduler = LookupUtil.getSchedulerBean();
+ scheduler.scheduleTriggeredJob(AlertAvailabilityDurationJob.class, false, null);
+
+ // create our resource with alert definition
+ MeasurementDefinition metricDef = createResourceWithMetricSchedule();
+ // use a 10s duration, this is not allowed in general, the gui forces 1 minute minimum
+ createAlertDefinitionWithAvailDurationCondition(resource.getId(),
+ AlertConditionOperator.AVAIL_DURATION_DOWN, 10);
+
+ // resource has initial UNKNOWN ResourceAvailability and no Availability records. simulate an avail report
+ // coming from the agent and setting the initial avail to UP.
+ AvailabilityReport availReport = new AvailabilityReport(AGENT_NAME);
+ availReport.addAvailability(new Datum(resource.getId(), AvailabilityType.UP, System.currentTimeMillis()));
+ AvailabilityManagerLocal availManager = LookupUtil.getAvailabilityManager();
+ availManager.mergeAvailabilityReport(availReport);
+
+ // wait for our JMS messages to process and see if we get any alerts
+ Thread.sleep(3000);
+
+ PageList<Alert> alerts = getAlerts(resource.getId());
+ assert alerts.size() == 0 : "No alert should have fired on the initial avail reporting: " + alerts;
+
+ // Now simulate the down avail
+ availReport = new AvailabilityReport(AGENT_NAME);
+ availReport.addAvailability(new Datum(resource.getId(), AvailabilityType.DOWN,
+ System.currentTimeMillis() + 10));
+ availManager.mergeAvailabilityReport(availReport);
+
+ // wait for our JMS messages to process and see if we get any alerts
+ Thread.sleep(5000);
+
+ alerts = getAlerts(resource.getId());
+ assert alerts.size() == 0 : "No alert should have fired after 30s, will take at least a minute: " + alerts;
+
+ // wait for our JMS messages to process and see if we get any alerts
+ Thread.sleep(6000);
+
+ alerts = getAlerts(resource.getId());
+ assert alerts.size() == 1 : "One alert should have fired on the avail duration: " + alerts;
+
+ // purge the resource fully, which should remove all alert defs and alert conditions and condition logs
+ int resourceId = resource.getId();
+ deleteNewResource(resource);
+ resource = null;
+
+ AlertDefinitionManagerLocal alertDefManager = LookupUtil.getAlertDefinitionManager();
+ PageList<AlertDefinition> defs = alertDefManager.findAlertDefinitions(getOverlord(), resourceId,
+ PageControl.getUnlimitedInstance());
+ assert defs.isEmpty() : "failed to delete the alert definition - are condition logs still around?";
+
+ } finally {
+ unprepareScheduler();
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testBZ830463_updateDef() throws Exception {
+ // create our resource with alert definition
+ MeasurementDefinition metricDef = createResourceWithMetricSchedule();
+ AlertDefinition alertDef = createAlertDefinitionWithOneInsideRangeCondition(metricDef, resource.getId());
+
+ assert alertDef.getConditions().size() == 1 : "1 alertDef condition should exist";
+ AlertCondition condition = alertDef.getConditions().iterator().next();
+ int conditionId = condition.getId();
+
+ // re-load the resource so we get the measurement schedule
+ Resource resourceWithSchedules = loadResourceWithSchedules(resource.getId());
+ MeasurementSchedule schedule = resourceWithSchedules.getSchedules().iterator().next();
+
+ // simulate a measurement report coming from the agent - one values that fits in our range, so 1 alert is fired
+ MeasurementScheduleRequest request = new MeasurementScheduleRequest(schedule);
+ MeasurementReport report = new MeasurementReport();
+ report.addData(new MeasurementDataNumeric(getTimestamp(15), request, Double.valueOf(50.0))); // 50 < 60 AND 50 > 40
+ MeasurementDataManagerLocal dataManager = LookupUtil.getMeasurementDataManager();
+ dataManager.mergeMeasurementReport(report);
+
+ // wait for our JMS messages to process and see if we get any alerts
+ Thread.sleep(5000);
+
+ // make sure one alert was triggered
+ List<Alert> alerts = getAlerts(resourceWithSchedules.getId());
+ assert alerts.size() == 1 : "1 alert should have fired: " + alerts;
+ Alert alert = alerts.get(0);
+
+ assert alert.getConditionLogs().size() == 1 : "1 condition log should exist";
+ AlertConditionLog conditionLog = alert.getConditionLogs().iterator().next();
+ Assert.assertEquals(conditionLog.getCondition().getId(), conditionId,
+ "original condition should have been associated with the alert");
+
+ // update a non-condition aspect of the def and then update the def
+ String updatedDesc = "Updated Description";
+ alertDef.setDescription(updatedDesc);
+ AlertDefinition updatedAlertDef = LookupUtil.getAlertDefinitionManager().updateAlertDefinition(getOverlord(),
+ alertDef.getId(), alertDef, false); // note that resetMatching is false
+ assert updatedDesc.equals(updatedAlertDef.getDescription()) : "Description should be updated";
+ assert updatedAlertDef.getConditions().size() == 1 : "1 alertDef condition should exist after the update";
+ assert updatedAlertDef.getConditions().iterator().next().getId() == condition.getId() : "condition should not be updated";
+
+ // get the alert again, and make sure it still has a log with the same condition
+ alerts = getAlerts(resourceWithSchedules.getId());
+ assert alerts.size() == 1 : "1 alert should have fired: " + alerts;
+ alert = alerts.get(0);
+
+ assert alert.getConditionLogs().size() == 1 : "1 condition log should exist after the update";
+ conditionLog = alert.getConditionLogs().iterator().next();
+ Assert.assertEquals(conditionLog.getCondition().getId(), conditionId,
+ "original condition should still have been associated with the alert");
+
+ // update the condition on the def and then update the def
+ condition.setThreshold(Double.valueOf(41.0));
+ updatedAlertDef = LookupUtil.getAlertDefinitionManager().updateAlertDefinition(getOverlord(), alertDef.getId(),
+ alertDef, true); // note that resetMatching is true
+ assert updatedAlertDef.getConditions().size() == 1 : "1 alertDef condition should exist after the update";
+ assert updatedAlertDef.getConditions().iterator().next().getId() != condition.getId() : "condition should be updated";
+
+ // get the alert again, and make sure it still has a log with the same condition
+ alerts = getAlerts(resourceWithSchedules.getId());
+ assert alerts.size() == 1 : "1 alert should have fired: " + alerts;
+ alert = alerts.get(0);
+
+ assert alert.getConditionLogs().size() == 1 : "1 condition log should exist after the update";
+ conditionLog = alert.getConditionLogs().iterator().next();
+ Assert.assertEquals(conditionLog.getCondition().getId(), conditionId,
+ "original condition should still have been associated with the alert");
+
+ return;
+ }
+
+ private PageList<Alert> getAlerts(int resourceId) {
+ AlertManagerLocal alertManager = LookupUtil.getAlertManager();
+ AlertCriteria alertCriteria = new AlertCriteria();
+ alertCriteria.addFilterResourceIds(resourceId);
+ alertCriteria.fetchConditionLogs(true);
+ PageList<Alert> alerts = alertManager.findAlertsByCriteria(getOverlord(), alertCriteria);
+ return alerts;
+ }
+
+ private AlertCondition getAlertConditionWithLogs(final int conditionId) {
+ return executeInTransaction(new TransactionCallbackReturnable<AlertCondition>() {
+ @Override
+ public AlertCondition execute() throws Exception {
+ AlertCondition cond = em.find(AlertCondition.class, conditionId);
+ cond.getConditionLogs().size(); // force the load
+ return cond;
+ }
+ });
+ }
+
+ private Resource loadResourceWithSchedules(int resourceId) {
+ ResourceCriteria resourceCriteria = new ResourceCriteria();
+ resourceCriteria.addFilterId(resourceId);
+ resourceCriteria.fetchSchedules(true);
+ Resource resourceWithSchedules = getResource(resourceCriteria);
+ assert resourceWithSchedules != null : "could not obtain resource from DB";
+ assert resourceWithSchedules.getSchedules() != null && resourceWithSchedules.getSchedules().size() == 1 : "missing schedule";
+ return resourceWithSchedules;
+ }
+
+ private AlertDefinition createAlertDefinitionWithTwoConditionsALL(MeasurementDefinition metricDef, int resourceId) {
+ // create alert definition with the conditions "metric value > 40 AND metric value < 60"
+ HashSet<AlertCondition> conditions = new HashSet<AlertCondition>(2);
+ AlertCondition cond1 = new AlertCondition();
+ cond1.setCategory(AlertConditionCategory.THRESHOLD);
+ cond1.setName(metricDef.getDisplayName());
+ cond1.setComparator(">");
+ cond1.setThreshold(Double.valueOf(40.0)); // value > 40 threshold
+ cond1.setOption(null);
+ cond1.setMeasurementDefinition(metricDef);
+ conditions.add(cond1);
+
+ AlertCondition cond2 = new AlertCondition();
+ cond2.setCategory(AlertConditionCategory.THRESHOLD);
+ cond2.setName(metricDef.getDisplayName());
+ cond2.setComparator("<");
+ cond2.setThreshold(Double.valueOf(60.0)); // value < 60 threshold
+ cond2.setOption(null);
+ cond2.setMeasurementDefinition(metricDef);
+ conditions.add(cond2);
+
+ AlertDefinition alertDefinition = new AlertDefinition();
+ alertDefinition.setName("two condition ALL alert");
+ alertDefinition.setEnabled(true);
+ alertDefinition.setPriority(AlertPriority.HIGH);
+ alertDefinition.setAlertDampening(new AlertDampening(Category.NONE));
+ alertDefinition.setRecoveryId(Integer.valueOf(0));
+ alertDefinition.setConditionExpression(BooleanExpression.ALL);
+ alertDefinition.setConditions(conditions);
+
+ AlertDefinitionManagerLocal alertDefManager = LookupUtil.getAlertDefinitionManager();
+ int defId = alertDefManager.createAlertDefinition(getOverlord(), alertDefinition, resourceId, true);
+ alertDefinition = alertDefManager.getAlertDefinition(getOverlord(), defId); // load it back so we get its ID and all condition IDs
+ assert alertDefinition != null && alertDefinition.getId() > 0 : "did not persist alert def properly: "
+ + alertDefinition;
+
+ // now that we created an alert def, we have to reload the alert condition cache
+ reloadAllAlertConditionCaches();
+
+ return alertDefinition;
+ }
+
+ private AlertDefinition createAlertDefinitionWithOneInsideRangeCondition(MeasurementDefinition metricDef,
+ int resourceId) {
+ // create alert definition with the range condition "metric value between 40...60"
+ HashSet<AlertCondition> conditions = new HashSet<AlertCondition>(1);
+ AlertCondition cond1 = new AlertCondition();
+ cond1.setCategory(AlertConditionCategory.RANGE);
+ cond1.setName(metricDef.getDisplayName());
+ cond1.setThreshold(Double.valueOf(40.0)); // threshold is always the low value of the range
+ cond1.setOption(Double.valueOf(60.0).toString()); // option is a stringified double that is always the high value of the range
+ cond1.setComparator("<"); // the value must be inside the range
+ cond1.setMeasurementDefinition(metricDef);
+ conditions.add(cond1);
+
+ AlertDefinition alertDefinition = new AlertDefinition();
+ alertDefinition.setName("one inside-range condition alert");
+ alertDefinition.setEnabled(true);
+ alertDefinition.setPriority(AlertPriority.HIGH);
+ alertDefinition.setAlertDampening(new AlertDampening(Category.NONE));
+ alertDefinition.setRecoveryId(Integer.valueOf(0));
+ alertDefinition.setConditionExpression(BooleanExpression.ALL);
+ alertDefinition.setConditions(conditions);
+
+ AlertDefinitionManagerLocal alertDefManager = LookupUtil.getAlertDefinitionManager();
+ int defId = alertDefManager.createAlertDefinition(getOverlord(), alertDefinition, resourceId, true);
+ alertDefinition = alertDefManager.getAlertDefinition(getOverlord(), defId); // load it back so we get its ID and all condition IDs
+ assert alertDefinition != null && alertDefinition.getId() > 0 : "did not persist alert def properly: "
+ + alertDefinition;
+
+ // now that we created an alert def, we have to reload the alert condition cache
+ reloadAllAlertConditionCaches();
+
+ return alertDefinition;
+ }
+
+ private AlertDefinition createAlertDefinitionWithAvailChangeCondition(int resourceId,
+ AlertConditionOperator condition) {
+ HashSet<AlertCondition> conditions = new HashSet<AlertCondition>(1);
+ AlertCondition cond1 = new AlertCondition();
+ cond1.setCategory(AlertConditionCategory.AVAILABILITY);
+ cond1.setName(condition.name());
+ cond1.setThreshold(null);
+ cond1.setOption(null);
+ cond1.setComparator(null);
+ cond1.setMeasurementDefinition(null);
+ conditions.add(cond1);
+
+ AlertDefinition alertDefinition = new AlertDefinition();
+ alertDefinition.setName("avail change: " + condition.name());
+ alertDefinition.setEnabled(true);
+ alertDefinition.setPriority(AlertPriority.HIGH);
+ alertDefinition.setAlertDampening(new AlertDampening(Category.NONE));
+ alertDefinition.setRecoveryId(Integer.valueOf(0));
+ alertDefinition.setConditionExpression(BooleanExpression.ALL);
+ alertDefinition.setConditions(conditions);
+
+ AlertDefinitionManagerLocal alertDefManager = LookupUtil.getAlertDefinitionManager();
+ int defId = alertDefManager.createAlertDefinition(getOverlord(), alertDefinition, resourceId, true);
+ alertDefinition = alertDefManager.getAlertDefinition(getOverlord(), defId); // load it back so we get its ID and all condition IDs
+ assert alertDefinition != null && alertDefinition.getId() > 0 : "did not persist alert def properly: "
+ + alertDefinition;
+
+ // now that we created an alert def, we have to reload the alert condition cache
+ reloadAllAlertConditionCaches();
+
+ return alertDefinition;
+ }
+
+ private AlertDefinition createAlertDefinitionWithAvailDurationCondition(int resourceId,
+ AlertConditionOperator condition, int duration) {
+ HashSet<AlertCondition> conditions = new HashSet<AlertCondition>(1);
+ AlertCondition cond1 = new AlertCondition();
+ cond1.setCategory(AlertConditionCategory.AVAIL_DURATION);
+ cond1.setName(condition.name());
+ cond1.setThreshold(null);
+ cond1.setOption(String.valueOf(duration));
+ cond1.setComparator(null);
+ cond1.setMeasurementDefinition(null);
+ conditions.add(cond1);
+
+ AlertDefinition alertDefinition = new AlertDefinition();
+ alertDefinition.setName("avail duration: " + condition.name());
+ alertDefinition.setEnabled(true);
+ alertDefinition.setPriority(AlertPriority.HIGH);
+ alertDefinition.setAlertDampening(new AlertDampening(Category.NONE));
+ alertDefinition.setRecoveryId(Integer.valueOf(0));
+ alertDefinition.setConditionExpression(BooleanExpression.ALL);
+ alertDefinition.setConditions(conditions);
+
+ AlertDefinitionManagerLocal alertDefManager = LookupUtil.getAlertDefinitionManager();
+ int defId = alertDefManager.createAlertDefinition(getOverlord(), alertDefinition, resourceId, true);
+ alertDefinition = alertDefManager.getAlertDefinition(getOverlord(), defId); // load it back so we get its ID and all condition IDs
+ assert alertDefinition != null && alertDefinition.getId() > 0 : "did not persist alert def properly: "
+ + alertDefinition;
+
+ // now that we created an alert def, we have to reload the alert condition cache
+ reloadAllAlertConditionCaches();
+
+ return alertDefinition;
+ }
+
+ private AlertDefinition createAlertDefinitionWithOneOutsideRangeCondition(MeasurementDefinition metricDef,
+ int resourceId) {
+ // create alert definition with the range condition "metric value outside 40...60"
+ HashSet<AlertCondition> conditions = new HashSet<AlertCondition>(1);
+ AlertCondition cond1 = new AlertCondition();
+ cond1.setCategory(AlertConditionCategory.RANGE);
+ cond1.setName(metricDef.getDisplayName());
+ cond1.setThreshold(Double.valueOf(40.0)); // threshold is always the low value of the range
+ cond1.setOption(Double.valueOf(60.0).toString()); // option is a stringified double that is always the high value of the range
+ cond1.setComparator(">"); // the value must be outside the range
+ cond1.setMeasurementDefinition(metricDef);
+ conditions.add(cond1);
+
+ AlertDefinition alertDefinition = new AlertDefinition();
+ alertDefinition.setName("one outside-range condition alert");
+ alertDefinition.setEnabled(true);
+ alertDefinition.setPriority(AlertPriority.HIGH);
+ alertDefinition.setAlertDampening(new AlertDampening(Category.NONE));
+ alertDefinition.setRecoveryId(Integer.valueOf(0));
+ alertDefinition.setConditionExpression(BooleanExpression.ALL);
+ alertDefinition.setConditions(conditions);
+
+ AlertDefinitionManagerLocal alertDefManager = LookupUtil.getAlertDefinitionManager();
+ int defId = alertDefManager.createAlertDefinition(getOverlord(), alertDefinition, resourceId, true);
+ alertDefinition = alertDefManager.getAlertDefinition(getOverlord(), defId); // load it back so we get its ID and all condition IDs
+ assert alertDefinition != null && alertDefinition.getId() > 0 : "did not persist alert def properly: "
+ + alertDefinition;
+
+ // now that we created an alert def, we have to reload the alert condition cache
+ reloadAllAlertConditionCaches();
+
+ return alertDefinition;
+ }
+
+ /**
+ * Creates a resource, stores it in the "resource" data field and returns the measurement definition
+ * that the schedule is for.
+ *
+ * @return measurement definition that was used to create the schedule for the new resource
+ * @throws Exception
+ */
+ private MeasurementDefinition createResourceWithMetricSchedule() throws Exception {
+ registerPlugin("type-with-metric.xml");
+ ResourceType resourceType = getResourceType("TypeWithMetrics");
+ assert resourceType != null : "failed to deploy resource type";
+ assert resourceType.getMetricDefinitions() != null : "failed to create metric defs";
+ assert resourceType.getMetricDefinitions().size() == 1 : "do not have the expected number of metric defs";
+
+ final MeasurementDefinition metricDef = resourceType.getMetricDefinitions().iterator().next();
+
+ resource = persistNewResource(resourceType.getName()); // will have UNKNOWN avail
+ assert resource != null && resource.getId() > 0 : "failed to create test resource";
+
+ JPAUtils.executeInTransaction(new TransactionCallbackWithContext<Object>() {
+ @Override
+ public Object execute(TransactionManager tm, EntityManager em) throws Exception {
+ MeasurementSchedule schedule = new MeasurementSchedule(metricDef, resource);
+ em.persist(schedule);
+ return null;
+ }
+ });
+
+ // create a server which attaches our agent to it - we need this for the alert subsystem to do its thing
+ createServerIdentity();
+ return metricDef;
+ }
+
+ /**
+ * Returns a epoch millis timestamp that is the current time minus the given number of seconds.
+ * In other words, this returns a time in the past - how far in the past is determined by the
+ * number of seconds parameter.
+ * @param secondsAgo
+ */
+ private long getTimestamp(long secondsAgo) {
+ return System.currentTimeMillis() - (secondsAgo * 1000);
+ }
+
+ private void reloadAllAlertConditionCaches() {
+ LookupUtil.getAlertConditionCacheManager().reloadAllCaches();
+ }
+
+ private void createServerIdentity() {
+ server = new Server();
+ server.setName(RHQ_SERVER_NAME_PROPERTY_VALUE);
+ server.setAddress("localhost");
+ server.setPort(7080);
+ server.setSecurePort(7443);
+ server.setComputePower(1);
+ server.setOperationMode(Server.OperationMode.MAINTENANCE);
+ int serverId = LookupUtil.getServerManager().create(server);
+ assert serverId > 0 : "could not create our server identity in the DB";
+
+ // simulate the agent being "connected" to the server
+ try {
+ Agent agent = getAgent(getEntityManager());
+ agent.setServer(server);
+ LookupUtil.getAgentManager().updateAgent(agent);
+ } catch (NoResultException nre) {
+ // no agent to attach
+ }
+ }
+
+ private void deleteServerIdentity() throws Exception {
+ if (server != null) {
+ cleanupAgent(); // can't remove the server before we purge the agent
+ LookupUtil.getCloudManager().deleteServer(server.getId());
+ server = null;
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java
new file mode 100644
index 0000000..131db7d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java
@@ -0,0 +1,436 @@
+package org.rhq.enterprise.server.alert.test;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.alert.Alert;
+import org.rhq.core.domain.alert.AlertCondition;
+import org.rhq.core.domain.alert.AlertConditionCategory;
+import org.rhq.core.domain.alert.AlertConditionLog;
+import org.rhq.core.domain.alert.AlertConditionOperator;
+import org.rhq.core.domain.event.EventSeverity;
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.measurement.NumericType;
+import org.rhq.core.domain.operation.OperationRequestStatus;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.alert.AlertManagerBean;
+import org.rhq.enterprise.server.alert.i18n.AlertI18NFactory;
+import org.rhq.enterprise.server.alert.i18n.AlertI18NResourceKeys;
+
+@Test
+public class AlertManagerBeanTest {
+
+ private static final String TEN_PERCENT = String.format("%2.1f%%", 10d);
+ private static final String TWELVE_DOT_5_B = String.format("%2.1fB", 12.5d);
+ private String pretty;
+
+ public void testPrettyPrintAVAILABILITY() {
+ AlertCondition condition = createCondition(AlertConditionCategory.AVAILABILITY,
+ AlertConditionOperator.AVAIL_GOES_UP.name(), null, null, null, null);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_UP);
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_UP_SHORT);
+
+ condition = createCondition(AlertConditionCategory.AVAILABILITY, AlertConditionOperator.AVAIL_GOES_DOWN.name(),
+ null, null, null, null);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_DOWN);
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_DOWN_SHORT);
+
+ condition = createCondition(AlertConditionCategory.AVAILABILITY,
+ AlertConditionOperator.AVAIL_GOES_DISABLED.name(), null, null, null, null);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_DISABLED);
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_DISABLED_SHORT);
+
+ condition = createCondition(AlertConditionCategory.AVAILABILITY,
+ AlertConditionOperator.AVAIL_GOES_UNKNOWN.name(), null, null, null, null);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_UNKNOWN);
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_UNKNOWN_SHORT);
+
+ }
+
+ public void testPrettyPrintAVAILABILITY_DURATION() {
+ AlertCondition condition = createCondition(AlertConditionCategory.AVAIL_DURATION,
+ AlertConditionOperator.AVAIL_DURATION_DOWN.name(), null, null, "120", null);
+ pretty = getPrettyAlertConditionString(condition);
+ assert "Availability stays DOWN [2m]".equals(pretty) : pretty;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert "Avail stays DOWN [2m]".equals(pretty) : pretty;
+
+ condition = createCondition(AlertConditionCategory.AVAIL_DURATION,
+ AlertConditionOperator.AVAIL_DURATION_NOT_UP.name(), null, null, "120", null);
+ pretty = getPrettyAlertConditionString(condition);
+ assert "Availability stays NOT UP [2m]".equals(pretty) : pretty;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert "Avail stays NOT UP [2m]".equals(pretty) : pretty;
+ }
+
+ public void testPrettyPrintTHRESHOLD() {
+ MeasurementDefinition md = createDynamicMeasurementDefinition();
+ AlertCondition condition = createCondition(AlertConditionCategory.THRESHOLD, md.getDisplayName(), ">", 12.5d,
+ null, md);
+ pretty = getPrettyAlertConditionString(condition);
+ String ref = String.format("Foo Prop > %2.1fB",12.5d);
+ assert ref.equals(pretty) : pretty;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert ref.equals(pretty) : pretty;
+ }
+
+ public void testPrettyPrintTHRESHOLD_Calltime() {
+ MeasurementDefinition md = createCalltimeMeasurementDefinition();
+ String regex = "some.*(reg)?ex$"; // this is the "name" of the condition
+
+ AlertCondition condition = createCondition(AlertConditionCategory.THRESHOLD, regex, ">", 12.5d, "MAX", md);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_THRESHOLD_WITH_EXPR, "CT Prop", "MAX", ">",
+ TWELVE_DOT_5_B, regex);
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_THRESHOLD_WITH_EXPR_SHORT, "CT Prop", "MAX", ">",
+ TWELVE_DOT_5_B, regex);
+
+ // no regex
+ condition = createCondition(AlertConditionCategory.THRESHOLD, null, ">", 12.5d, "MAX", md);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_THRESHOLD,"CT Prop","MAX",">", TWELVE_DOT_5_B);
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_THRESHOLD_SHORT, "CT Prop", "MAX", ">",
+ TWELVE_DOT_5_B);
+ }
+
+ public void testPrettyPrintBASELINE() {
+ MeasurementDefinition md = createDynamicMeasurementDefinition();
+ AlertCondition condition = createCondition(AlertConditionCategory.BASELINE, md.getDisplayName(), ">", 0.10d,
+ "mean", md);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_BASELINE_MEAN,"Foo Prop",">", TEN_PERCENT);
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_BASELINE_MEAN_SHORT,"Foo Prop",">", TEN_PERCENT);
+
+ condition = createCondition(AlertConditionCategory.BASELINE, md.getDisplayName(), ">", 0.10d, "min", md);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_BASELINE_MIN,"Foo Prop",">", TEN_PERCENT);
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_BASELINE_MIN_SHORT,"Foo Prop",">", TEN_PERCENT);
+
+ condition = createCondition(AlertConditionCategory.BASELINE, md.getDisplayName(), ">", 0.10d, "max", md);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_BASELINE_MAX,"Foo Prop",">", TEN_PERCENT);
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_BASELINE_MAX_SHORT,"Foo Prop",">", TEN_PERCENT);
+ }
+
+ public void testPrettyPrintCHANGE() {
+ MeasurementDefinition md = createDynamicMeasurementDefinition();
+ AlertCondition condition = createCondition(AlertConditionCategory.CHANGE, md.getDisplayName(), null, null,
+ null, md);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_METRIC_CHANGED, "Foo Prop");
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_METRIC_CHANGED_SHORT, "Foo Prop");
+ }
+
+ public void testPrettyPrintCHANGE_Calltime() {
+ MeasurementDefinition md = createCalltimeMeasurementDefinition();
+ String regex = "some.*(reg)?ex$"; // this is the "name" of the condition
+
+ AlertCondition condition = createCondition(AlertConditionCategory.CHANGE, regex, "LO", 0.10d, "MIN", md);
+ pretty = getPrettyAlertConditionString(condition);
+ String msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_SHRINKS);
+ String ref = "Calltime Metric CT Prop MIN %s by at least %2.1f%% with calltime destination matching \"some.*(reg)?ex$\"";
+ String refs = "CT Prop MIN %s by %2.1f%% matching \"some.*(reg)?ex$\"";
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert String.format(refs,msg,10.0f).equals(pretty) : pretty + " \n<=> " +String.format(refs,msg,10.0f);
+
+ condition = createCondition(AlertConditionCategory.CHANGE, regex, "CH", 0.10d, "MIN", md);
+ pretty = getPrettyAlertConditionString(condition);
+ msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_CHANGES);
+ assert String.format(ref,msg,10.0f).equals(pretty) ;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert String.format(refs,msg,10.0f).equals(pretty) ;
+
+
+ condition = createCondition(AlertConditionCategory.CHANGE, regex, "HI", 0.10d, "MIN", md);
+ msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_GROWS);
+ pretty = getPrettyAlertConditionString(condition);
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert String.format(refs,msg,10.0f).equals(pretty) : pretty + " \n<=> " +String.format(refs,msg,10.0f);
+
+ ref = "Calltime Metric CT Prop MAX %s by at least %2.1f%% with calltime destination matching \"some.*(reg)?ex$\"";
+ refs = "CT Prop MAX %s by %2.1f%% matching \"some.*(reg)?ex$\"";
+
+ condition = createCondition(AlertConditionCategory.CHANGE, regex, "LO", 0.10d, "MAX", md);
+ msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_SHRINKS);
+ pretty = getPrettyAlertConditionString(condition);
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert String.format(refs,msg,10.0f).equals(pretty) : pretty + " \n<=> " +String.format(refs,msg,10.0f);
+
+ condition = createCondition(AlertConditionCategory.CHANGE, regex, "CH", 0.10d, "MAX", md);
+ msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_CHANGES);
+ pretty = getPrettyAlertConditionString(condition);
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert String.format(refs,msg,10.0f).equals(pretty) : pretty + " \n<=> " +String.format(refs,msg,10.0f);
+
+ condition = createCondition(AlertConditionCategory.CHANGE, regex, "HI", 0.10d, "MAX", md);
+ msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_GROWS);
+ pretty = getPrettyAlertConditionString(condition);
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert String.format(refs,msg,10.0f).equals(pretty) : pretty + " \n<=> " +String.format(refs,msg,10.0f);
+
+ ref = "Calltime Metric CT Prop AVG %s by at least %2.1f%% with calltime destination matching \"some.*(reg)?ex$\"";
+ refs = "CT Prop AVG %s by %2.1f%% matching \"some.*(reg)?ex$\"";
+
+ condition = createCondition(AlertConditionCategory.CHANGE, regex, "LO", 0.10d, "AVG", md);
+ msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_SHRINKS);
+ pretty = getPrettyAlertConditionString(condition);
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert String.format(refs,msg,10.0f).equals(pretty) : pretty + " \n<=> " +String.format(refs,msg,10.0f);
+
+ condition = createCondition(AlertConditionCategory.CHANGE, regex, "CH", 0.10d, "AVG", md);
+ msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_CHANGES);
+ pretty = getPrettyAlertConditionString(condition);
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert String.format(refs,msg,10.0f).equals(pretty) : pretty + " \n<=> " +String.format(refs,msg,10.0f);
+
+ condition = createCondition(AlertConditionCategory.CHANGE, regex, "HI", 0.10d, "AVG", md);
+ msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_GROWS);
+ pretty = getPrettyAlertConditionString(condition);
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert String.format(refs,msg,10.0f).equals(pretty) : pretty + " \n<=> " +String.format(refs,msg,10.0f);
+
+ // no regex
+ ref = "Calltime Metric CT Prop AVG %s by at least %2.1f%%";
+ refs = "CT Prop AVG %s by %2.1f%%";
+
+ condition = createCondition(AlertConditionCategory.CHANGE, null, "LO", 0.10d, "AVG", md);
+ msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_SHRINKS);
+ pretty = getPrettyAlertConditionString(condition);
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert String.format(refs,msg,10.0f).equals(pretty) : pretty + " \n<=> " +String.format(refs,msg,10.0f);
+
+ condition = createCondition(AlertConditionCategory.CHANGE, null, "CH", 0.10d, "AVG", md);
+ msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_CHANGES);
+ pretty = getPrettyAlertConditionString(condition);
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert String.format(refs,msg,10.0f).equals(pretty) : pretty + " \n<=> " +String.format(refs,msg,10.0f);
+
+ condition = createCondition(AlertConditionCategory.CHANGE, null, "HI", 0.10d, "AVG", md);
+ msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_GROWS);
+ pretty = getPrettyAlertConditionString(condition);
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert String.format(refs,msg,10.0f).equals(pretty) : pretty + " \n<=> " +String.format(refs,msg,10.0f);
+ }
+
+ public void testPrettyPrintTRAIT() {
+ MeasurementDefinition md = createTraitMeasurementDefinition();
+ AlertCondition condition = createCondition(AlertConditionCategory.TRAIT, md.getDisplayName(), null, null, null,
+ md);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_METRIC_CHANGED,"Blah Trait");
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_METRIC_CHANGED_SHORT,"Blah Trait");
+ }
+
+ public void testPrettyPrintCONTROL() {
+ AlertCondition condition = createCondition(AlertConditionCategory.CONTROL, "opNameHere", null, null,
+ OperationRequestStatus.FAILURE.name(), null);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_OPERATION,"opNameHere","FAILURE");
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_OPERATION_SHORT,"opNameHere","FAILURE");
+
+ condition = createCondition(AlertConditionCategory.CONTROL, "opNameHere", null, null,
+ OperationRequestStatus.SUCCESS.name(), null);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_OPERATION,"opNameHere","SUCCESS");
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_OPERATION_SHORT,"opNameHere","SUCCESS");
+ }
+
+ public void testPrettyPrintEVENT() {
+ String regex = "some.*(reg)?ex$";
+
+ AlertCondition condition = createCondition(AlertConditionCategory.EVENT, EventSeverity.WARN.name(), null, null,
+ regex, null);
+ pretty = getPrettyAlertConditionString(condition);
+ assert ("Event With Severity [WARN] Matching Expression \"" + regex + "\"").equals(pretty) : pretty;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert ("[WARN] Event Matching \"" + regex + "\"").equals(pretty) : pretty;
+
+ // no regex
+ condition = createCondition(AlertConditionCategory.EVENT, EventSeverity.WARN.name(), null, null, null, null);
+ pretty = getPrettyAlertConditionString(condition);
+ assert "Event With Severity [WARN]".equals(pretty) : pretty;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert "[WARN] Event".equals(pretty) : pretty;
+ }
+
+ public void testPrettyPrintRESOURCECONFIG() {
+ AlertCondition condition = createCondition(AlertConditionCategory.RESOURCE_CONFIG, null, null, null, null, null);
+ pretty = getPrettyAlertConditionString(condition);
+ assert "Resource Configuration Changed".equals(pretty) : pretty;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert "Res Config Chg".equals(pretty) : pretty;
+ }
+
+ public void testPrettyPrintDRIFT() {
+ AlertCondition condition = createCondition(AlertConditionCategory.DRIFT, "?riftName", null, null, "fil.*", null);
+ pretty = getPrettyAlertConditionString(condition);
+ assert "Drift detected for files that match \"fil.*\" and for drift definition [?riftName]".equals(pretty) : pretty;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert "Drift matching \"fil.*\", config=[?riftName]".equals(pretty) : pretty;
+
+ condition = createCondition(AlertConditionCategory.DRIFT, null, null, null, "fil.*", null);
+ pretty = getPrettyAlertConditionString(condition);
+ assert "Drift detected for files that match \"fil.*\"".equals(pretty) : pretty;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert "Drift matching \"fil.*\"".equals(pretty) : pretty;
+
+ condition = createCondition(AlertConditionCategory.DRIFT, "?riftName", null, null, null, null);
+ pretty = getPrettyAlertConditionString(condition);
+ assert "Drift detected for drift definition [?riftName]".equals(pretty) : pretty;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert "Drift! config=[?riftName]".equals(pretty) : pretty;
+
+ condition = createCondition(AlertConditionCategory.DRIFT, null, null, null, null, null);
+ pretty = getPrettyAlertConditionString(condition);
+ assert "Drift Detected".equals(pretty) : pretty;
+ pretty = getShortPrettyAlertConditionString(condition);
+ assert "Drift!".equals(pretty) : pretty;
+ }
+
+ public void testPrettyPrintRANGE() {
+ MeasurementDefinition md = createDynamicMeasurementDefinition();
+ AlertCondition condition = createCondition(AlertConditionCategory.RANGE, md.getDisplayName(), "<=", 1.0,
+ "22.2", md);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_RANGE_INSIDE_INCL,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_RANGE_INSIDE_INCL_SHORT,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
+
+ condition = createCondition(AlertConditionCategory.RANGE, md.getDisplayName(), ">=", 1.0, "22.2", md);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_RANGE_OUTSIDE_INCL,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_RANGE_OUTSIDE_INCL_SHORT,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
+
+ condition = createCondition(AlertConditionCategory.RANGE, md.getDisplayName(), "<", 1.0, "22.2", md);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_RANGE_INSIDE_EXCL,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_RANGE_INSIDE_EXCL_SHORT,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
+
+ condition = createCondition(AlertConditionCategory.RANGE, md.getDisplayName(), ">", 1.0, "22.2", md);
+ pretty = getPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_RANGE_OUTSIDE_EXCL,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
+ pretty = getShortPrettyAlertConditionString(condition);
+ check(AlertI18NResourceKeys.ALERT_RANGE_OUTSIDE_EXCL_SHORT,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
+ }
+
+ private String getPrettyAlertConditionString(AlertCondition condition) {
+ AlertManagerBean pojo = new AlertManagerBean();
+ String s = extractCondition(pojo.prettyPrintAlertConditions(createAlert(condition), false));
+ System.out.println("long===>" + s);
+ return s;
+ }
+
+ private String getShortPrettyAlertConditionString(AlertCondition condition) {
+ AlertManagerBean pojo = new AlertManagerBean();
+ String s = extractCondition(pojo.prettyPrintAlertConditions(createAlert(condition), true));
+ System.out.println("short-->" + s);
+ return s;
+ }
+
+ private MeasurementDefinition createDynamicMeasurementDefinition() {
+ ResourceType resourceType = new ResourceType("testType", "testPlugin", ResourceCategory.PLATFORM, null);
+ MeasurementDefinition md = new MeasurementDefinition(resourceType, "fooMetric");
+ md.setDataType(DataType.MEASUREMENT);
+ md.setDisplayName("Foo Prop");
+ md.setMeasurementType(NumericType.DYNAMIC);
+ md.setRawNumericType(NumericType.DYNAMIC);
+ md.setUnits(MeasurementUnits.BYTES);
+ return md;
+ }
+
+ private MeasurementDefinition createCalltimeMeasurementDefinition() {
+ ResourceType resourceType = new ResourceType("testType", "testPlugin", ResourceCategory.PLATFORM, null);
+ MeasurementDefinition md = new MeasurementDefinition(resourceType, "ctMetric");
+ md.setDataType(DataType.CALLTIME);
+ md.setDisplayName("CT Prop");
+ md.setMeasurementType(NumericType.DYNAMIC);
+ md.setRawNumericType(NumericType.DYNAMIC);
+ md.setUnits(MeasurementUnits.BYTES);
+ md.setDestinationType("/wot gorilla");
+ return md;
+ }
+
+ private MeasurementDefinition createTraitMeasurementDefinition() {
+ ResourceType resourceType = new ResourceType("testType", "testPlugin", ResourceCategory.PLATFORM, null);
+ MeasurementDefinition md = new MeasurementDefinition(resourceType, "traitMetric");
+ md.setDataType(DataType.TRAIT);
+ md.setDisplayName("Blah Trait");
+ md.setUnits(MeasurementUnits.BYTES);
+ return md;
+ }
+
+ private Alert createAlert(AlertCondition condition) {
+ Alert alert = new Alert();
+ AlertConditionLog conditionLog = new AlertConditionLog(condition, System.currentTimeMillis());
+ alert.addConditionLog(conditionLog);
+ return alert;
+ }
+
+ private AlertCondition createCondition(AlertConditionCategory category, String name, String comparator,
+ Double threshold, String option, MeasurementDefinition measDef) {
+ AlertCondition condition = new AlertCondition();
+ condition.setCategory(category);
+ condition.setName(name);
+ condition.setComparator(comparator);
+ condition.setThreshold(threshold);
+ condition.setOption(option);
+ condition.setMeasurementDefinition(measDef);
+ return condition;
+ }
+
+ private String extractCondition(String prettyString) {
+ String cond = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_CONDITION_PATTERN); // Take i18n into account
+ //System.out.println(prettyString);
+ Pattern pattern = Pattern.compile("- " + cond + " 1: (.*)\n"); //en short form has " - Cond 1: ...", long form has " - Condition 1: ..."
+ Matcher matcher = pattern.matcher(prettyString);
+ assert matcher.find() : "could not find the condition string";
+ return matcher.group(1);
+ }
+
+ private void check(String msg) {
+ String ref = AlertI18NFactory.getMessage(msg);
+ assert ref != null : "Could not find reference message";
+ assert ref.equals(pretty) : pretty;
+ }
+
+ private void check(String msg, Object... args) {
+ String ref = AlertI18NFactory.getMessage(msg,args);
+ assert ref != null : "Could not find reference message";
+ assert ref.equals(pretty) : "Got : >>" + pretty + "<< Expect: >>" + ref + "<<";
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/DeleteAlertsTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/DeleteAlertsTest.java
new file mode 100644
index 0000000..487a0ea
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/DeleteAlertsTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.enterprise.server.alert.test;
+
+import java.sql.Connection;
+import java.util.List;
+
+import org.dbunit.database.DatabaseConnection;
+import org.dbunit.database.IDatabaseConnection;
+import org.dbunit.dataset.IDataSet;
+import org.dbunit.dataset.xml.FlatXmlDataSet;
+import org.dbunit.dataset.xml.FlatXmlProducer;
+import org.dbunit.operation.DatabaseOperation;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.xml.sax.InputSource;
+
+import org.rhq.core.domain.alert.AlertConditionLog;
+import org.rhq.core.domain.alert.notification.AlertNotificationLog;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.common.EntityContext;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.enterprise.server.alert.AlertManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Test for {@link AlertManagerLocal} SLSB.
+ */
+@Test(enabled = false)
+public class DeleteAlertsTest extends AbstractEJB3Test {
+ private AlertManagerLocal alertManager;
+ private Subject superuser;
+ private Resource newResource;
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ alertManager = LookupUtil.getAlertManager();
+ superuser = LookupUtil.getSubjectManager().getOverlord();
+
+ Connection connection = null;
+
+ try {
+ connection = getConnection();
+ IDatabaseConnection dbUnitConnection = new DatabaseConnection(connection);
+ DatabaseOperation.REFRESH.execute(dbUnitConnection, getDataSet());
+ } finally {
+ if (connection != null) {
+ connection.close();
+ }
+ }
+
+ newResource = getEntityManager().find(Resource.class, 1);
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ if ("true".equals(System.getProperty("clean.db"))) {
+ Connection connection = null;
+
+ try {
+ connection = getConnection();
+ IDatabaseConnection dbUnitConnection = new DatabaseConnection(connection);
+ DatabaseOperation.DELETE.execute(dbUnitConnection, getDataSet());
+ } finally {
+ if (connection != null) {
+ connection.close();
+ }
+ }
+ }
+ }
+
+ IDataSet getDataSet() throws Exception {
+ FlatXmlProducer xmlProducer = new FlatXmlProducer(new InputSource(getClass().getResourceAsStream(
+ "AlertManagerBeanTest.xml")));
+ xmlProducer.setColumnSensing(true);
+ return new FlatXmlDataSet(xmlProducer);
+ }
+
+ public void deleteAlertsForResource() {
+ assert 1 == alertManager.deleteAlertsByContext(superuser, EntityContext.forResource(newResource.getId()));
+ }
+
+ @SuppressWarnings("unchecked")
+ public void deleteAlertsForResourceTemplate() {
+ int resourceTypeId = 1;
+ int deletedCount = alertManager.deleteAlertsByContext(superuser, EntityContext.forTemplate(resourceTypeId));
+
+ List<AlertConditionLog> alertConditionLogs = getEntityManager()
+ .createQuery("from AlertConditionLog log where log.id = :id").setParameter("id", 2).getResultList();
+
+ List<AlertNotificationLog> notificationLogs = getEntityManager()
+ .createQuery("from AlertNotificationLog log where log.id = :id").setParameter("id", 2).getResultList();
+
+ assertEquals("Failed to delete alerts by template", 1, deletedCount);
+ assertEquals("Failed to delete alert condition logs when deleting alerts by template", 0,
+ alertConditionLogs.size());
+ assertEquals("Failed to delete alert notification logs when deleting alerts by template", 0,
+ notificationLogs.size());
+ }
+
+ public void testAlertDeleteInRange() {
+ assert 2 == alertManager.deleteAlerts(0L, System.currentTimeMillis() + 600000L); // go out into the future to make sure we get our alert
+ }
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/auth/test/SubjectManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/auth/test/SubjectManagerBeanTest.java
new file mode 100644
index 0000000..8426843
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/auth/test/SubjectManagerBeanTest.java
@@ -0,0 +1,571 @@
+/*
+ * 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.enterprise.server.auth.test;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.security.auth.login.LoginException;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.authz.Role;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.criteria.SubjectCriteria;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
+import org.rhq.enterprise.server.auth.SessionManager;
+import org.rhq.enterprise.server.auth.SessionNotFoundException;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.authz.AuthorizationManagerLocal;
+import org.rhq.enterprise.server.authz.PermissionException;
+import org.rhq.enterprise.server.authz.RoleManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Tests the subject manager.
+ */
+@Test
+public class SubjectManagerBeanTest extends AbstractEJB3Test {
+
+ private SubjectManagerLocal subjectManager;
+ private AuthorizationManagerLocal authorizationManager;
+ private RoleManagerLocal roleManager;
+
+ /**
+ * Prepares things for the entire test class.
+ */
+ @BeforeClass
+ public void beforeClass() {
+ subjectManager = LookupUtil.getSubjectManager();
+ authorizationManager = LookupUtil.getAuthorizationManager();
+ roleManager = LookupUtil.getRoleManager();
+ }
+
+ /**
+ * This runs after each test method. It clears out all sessions.
+ */
+ @AfterMethod
+ public void purgeAllSessions() {
+ // create a list of all users we know our tests have used
+ List<String> usernames = new ArrayList<String>();
+ usernames.add("admin");
+ usernames.add("rhqadmin");
+ usernames.add("new_user");
+
+ SessionManager session_manager = SessionManager.getInstance();
+
+ // clean out all users' sessions (a user can have more than one session)
+ while (usernames.size() > 0) {
+ try {
+ String doomed_user = usernames.get(0);
+ session_manager.invalidate(doomed_user);
+ } finally {
+ usernames.remove(0);
+ }
+ }
+ }
+
+ /**
+ * Tests persisting and retrieving user configuration.
+ *
+ * @throws Exception
+ */
+ public void testUserConfiguration() throws Exception {
+ Subject superuser;
+
+ getTransactionManager().begin();
+
+ try {
+ superuser = subjectManager.getOverlord();
+
+ // create the user
+ Subject new_user = new Subject("dummy-user", true, false);
+ new_user = subjectManager.createSubject(superuser, new_user);
+ assert new_user.getUserConfiguration() == null : "There should not be any configuration yet";
+
+ // set and persist an empty configuration
+ Configuration config = new Configuration();
+ new_user.setUserConfiguration(config);
+ assert new_user.getUserConfiguration() != null : "An empty configuration should have been set";
+ assert new_user.getUserConfiguration().getProperties().size() == 0 : "An empty config should have been set";
+ assert new_user.getUserConfiguration().getId() == 0 : "Configuration wasn't persisted - should not have an ID";
+
+ new_user = subjectManager.updateSubject(superuser, new_user); // let superuser change it
+ config = new_user.getUserConfiguration();
+ assert config != null : "An empty configuration should have been persisted";
+ assert config.getProperties().size() == 0 : "An empty config should have been persisted";
+ assert config.getId() != 0 : "Configuration was persisted - should have an ID";
+
+ // set and persist a non-empty configuration
+ config.put(new PropertySimple("firstname", "firstvalue"));
+ config.put(new PropertySimple("secondname", "secondvalue"));
+ assert new_user.getUserConfiguration() != null : "A full configuration should have been set";
+ assert new_user.getUserConfiguration().getProperties().size() == 2 : "A full config should have been set";
+
+ new_user = createSession(new_user);
+ new_user = subjectManager.updateSubject(new_user, new_user); // let the user itself change it
+ config = new_user.getUserConfiguration();
+ assert config != null : "A full configuration should have been persisted";
+ assert config.getProperties().size() == 2 : "A full config should have been persisted";
+ assert config.getId() != 0 : "Configuration was persisted - should have an ID";
+ assert config.getSimple("firstname").getStringValue().equals("firstvalue") : "Configuration wasn't persisted properly";
+ assert config.getSimple("secondname").getStringValue().equals("secondvalue") : "Configuration wasn't persisted properly!";
+
+ // let's try the load method to make sure it can eagerly load the configuration
+ Subject loaded = subjectManager.loadUserConfiguration(new_user.getId());
+ config = loaded.getUserConfiguration();
+ assert config != null : "A full configuration should have been persisted";
+ assert config.getProperties().size() == 2 : "A full config should have been persisted";
+ assert config.getId() != 0 : "Configuration was persisted - should have an ID";
+ assert config.getSimple("firstname").getStringValue().equals("firstvalue") : "Configuration wasn't persisted properly";
+ assert config.getSimple("secondname").getStringValue().equals("secondvalue") : "Configuration wasn't persisted properly!";
+
+ // set and persist a null configuration
+ new_user.setUserConfiguration(null);
+ assert new_user.getUserConfiguration() == null : "There should not be any configuration anymore";
+
+ new_user = subjectManager.updateSubject(superuser, new_user); // let superuser change it
+ assert new_user.getUserConfiguration() == null : "An empty configuration should have been persisted";
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ /**
+ * Makes sure you cannot disable super users.
+ *
+ * @throws Exception
+ */
+ public void testTryToDisableSuperUsers() throws Exception {
+ Subject superuser;
+ Subject rhqadmin;
+
+ getTransactionManager().begin();
+ try {
+ superuser = subjectManager.getOverlord();
+ rhqadmin = subjectManager.getSubjectByName("rhqadmin");
+ rhqadmin = createSession(rhqadmin);
+
+ try {
+ superuser.setFactive(false);
+ subjectManager.updateSubject(rhqadmin, superuser);
+ assert false : "You should not be able to disable the superuser";
+ } catch (PermissionException se) {
+ superuser.setFactive(true);
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ getTransactionManager().begin();
+ try {
+ try {
+ rhqadmin.setFactive(false);
+ subjectManager.updateSubject(superuser, rhqadmin);
+ assert false : "You should not be able to delete the rhqadmin user";
+ } catch (PermissionException se) {
+ rhqadmin.setFactive(true);
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ /**
+ * Makes sure you cannot delete the super users.
+ *
+ * @throws Exception
+ */
+ public void testTryToDeleteSuperUsers() throws Exception {
+ Subject superuser;
+ Subject rhqadmin;
+
+ getTransactionManager().begin();
+ try {
+ superuser = subjectManager.getOverlord();
+ superuser = createSession(superuser);
+ rhqadmin = subjectManager.getSubjectByName("rhqadmin");
+ rhqadmin = createSession(rhqadmin);
+
+ try {
+ subjectManager.deleteUsers(superuser, new int[] { rhqadmin.getId() });
+ assert false : "You should not be able to delete the rhqadmin user";
+ } catch (PermissionException se) {
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ getTransactionManager().begin();
+ try {
+ try {
+ subjectManager.deleteUsers(rhqadmin, new int[] { superuser.getId() });
+ assert false : "You should not be able to delete the superuser";
+ } catch (PermissionException se) {
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ // but you should be allowed to change the rhqadmin's principal password
+ getTransactionManager().begin();
+ try {
+ subjectManager.changePassword(rhqadmin, rhqadmin.getName(), "change-me");
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ /**
+ * Tests CRUD on subjects.
+ *
+ * @throws Exception
+ */
+ public void testSubjects() throws Exception {
+ Subject new_user = null;
+
+ getTransactionManager().begin();
+
+ List<Permission> all_global_perms = new ArrayList<Permission>();
+ all_global_perms.add(Permission.MANAGE_SECURITY);
+ all_global_perms.add(Permission.MANAGE_INVENTORY);
+ all_global_perms.add(Permission.MANAGE_SETTINGS);
+
+ // get the system super subject
+ Subject superuser = subjectManager.getSubjectById(1);
+ assert superuser.getId() == 1;
+ assert superuser.getName().equals("admin");
+ assert authorizationManager.getExplicitGlobalPermissions(superuser).containsAll(all_global_perms);
+
+ // get the rhqadmin subject
+ Subject rhqadmin = subjectManager.getSubjectByName("rhqadmin");
+ assert rhqadmin.getId() == 2;
+ assert rhqadmin.getName().equals("rhqadmin");
+ assert authorizationManager.getExplicitGlobalPermissions(rhqadmin).containsAll(all_global_perms);
+
+ rhqadmin = createSession(rhqadmin); // our test needs to ensure the rhqadmin user has a session
+
+ // check the subjects that do and do not have principals
+ Collection<String> all_users_with_principals = subjectManager.findAllUsersWithPrincipals();
+ assert !all_users_with_principals.contains(superuser.getName());
+ assert all_users_with_principals.contains(rhqadmin.getName());
+ assert !subjectManager.isUserWithPrincipal(superuser.getName());
+ assert subjectManager.isUserWithPrincipal(rhqadmin.getName());
+
+ // get all subjects, whether or not they have a principal
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ Subject subject = null;
+ try {
+ subject = subjectManager.loginUnauthenticated("rhqadmin");
+ } catch (Exception e) {
+ assert false : "There must be at least rhqadmin user";
+ }
+
+ SubjectCriteria c = new SubjectCriteria();
+ c.addFilterFsystem(false);
+ c.addSortName(PageOrdering.ASC);
+ PageList<Subject> all_subjects = subjectManager.findSubjectsByCriteria(subject, c);
+
+ assert all_subjects.size() >= 1 : "There must be at least rhqadmin user";
+ assert !all_subjects.contains(superuser) : "The superuser should not have been returned in the list";
+ assert all_subjects.contains(rhqadmin) : "Missing user [" + rhqadmin + "] from: " + all_subjects;
+
+ // create, modify then delete the user
+ new_user = new Subject();
+ new_user.setFsystem(false);
+ new_user.setFactive(true);
+ new_user.setName("dummy-user");
+ new_user.setFirstName("my-firstname");
+ new_user.setLastName("my-lastname");
+ new_user.setEmailAddress("email(a)address.com");
+ new_user.setPhoneNumber("1-800-555-1212");
+ new_user.setSmsAddress("sms address");
+ new_user.setDepartment("my-department");
+
+ new_user = subjectManager.createSubject(rhqadmin, new_user);
+ new_user = createSession(new_user);
+ assert !subjectManager.isUserWithPrincipal(new_user.getName());
+ subjectManager.createPrincipal(subjectManager.getOverlord(), new_user.getName(), "my-password");
+ assert subjectManager.isUserWithPrincipal(new_user.getName());
+
+ // make sure it was persisted and you can actually login with it
+ assert new_user.getId() != 0;
+ Subject login_new_user = subjectManager.loginUnauthenticated(new_user.getName());
+ assert login_new_user.equals(new_user);
+ new_user = login_new_user; // login_new_user was given a new session ID
+
+ subjectManager.changePassword(new_user, new_user.getName(), "my-new-password");
+ subjectManager.changePassword(rhqadmin, new_user.getName(), "my-new-password"); // see that rhqadmin can change it too
+
+ getTransactionManager().commit();
+ getTransactionManager().begin();
+
+ try {
+ subjectManager.changePassword(new_user, rhqadmin.getName(), "not-allowed");
+ assert false : "The new user does not have permission to change another's password";
+ } catch (PermissionException se) {
+ } finally {
+ // PermissionException causes a rollback, let's start a new tx
+ getTransactionManager().rollback();
+ }
+
+ getTransactionManager().begin();
+
+ // this new user has no roles - therefore, no global permissions
+ assert authorizationManager.getExplicitGlobalPermissions(new_user).size() == 0;
+
+ try {
+ subjectManager.deleteUsers(new_user, new int[] { new_user.getId() });
+ assert false : "The new user should not have had the permission to delete itself";
+ } catch (PermissionException e) {
+ } finally {
+ // PermissionException causes a rollback, let's start a new tx
+ getTransactionManager().rollback();
+ }
+
+ getTransactionManager().begin();
+
+ // delete the new user
+ assert subjectManager.getSubjectByName(new_user.getName()).equals(new_user);
+ assert subjectManager.isUserWithPrincipal(new_user.getName());
+ subjectManager.deleteUsers(rhqadmin, new int[] { new_user.getId() });
+ assert subjectManager.getSubjectByName(new_user.getName()) == null;
+ assert !subjectManager.isUserWithPrincipal(new_user.getName());
+
+ getTransactionManager().commit();
+ }
+
+ /**
+ * Tests getting a super user subject.
+ *
+ * @throws Exception
+ */
+ public void testGetSuperUser() throws Exception {
+ getTransactionManager().begin();
+
+ try {
+ Subject superuser1 = subjectManager.getOverlord();
+ assert superuser1.getId() == 1;
+
+ Subject superuser2 = subjectManager.getOverlord();
+ assert superuser2.getId() == 1;
+
+ assert superuser1.equals(superuser2);
+
+ // that second call should have used the same session since not enough time elapsed to expire the session
+ assert superuser1.getSessionId().equals(superuser2.getSessionId());
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ /**
+ * Tests logging in and out when not requiring passwords.
+ *
+ * @throws Exception
+ */
+ public void testLoginUnauthenticated() throws Exception {
+ getTransactionManager().begin();
+
+ try {
+ Subject subject1 = subjectManager.loginUnauthenticated("rhqadmin");
+ int session1 = subject1.getSessionId();
+
+ Thread.sleep(500); // just wait a bit
+
+ Subject subject2 = subjectManager.loginUnauthenticated("rhqadmin");
+ int session2 = subject2.getSessionId();
+
+ assert session1 != session2 : "The same sessionId should never be assigned when logging in twice";
+ assert subject1.equals(subject2);
+
+ Subject s = subjectManager.getSubjectByNameAndSessionId("rhqadmin", subject1.getSessionId());
+ assert s.getSessionId() == session1;
+ s = subjectManager.getSubjectByNameAndSessionId("rhqadmin", subject2.getSessionId());
+ assert s.getSessionId() == session2;
+
+ subjectManager.logout(session1);
+ try {
+ s = subjectManager.getSubjectByNameAndSessionId("rhqadmin", subject1.getSessionId());
+ assert false : "Session should be invalid";
+ } catch (SessionNotFoundException ok) {
+ }
+
+ s = subjectManager.getSubjectByNameAndSessionId("rhqadmin", subject2.getSessionId());
+ assert s.getSessionId() == session2;
+
+ // this should ne a no-op, no exception
+ subjectManager.logout(session1);
+
+ subjectManager.logout(session2);
+ try {
+ s = subjectManager.getSubjectByNameAndSessionId("rhqadmin", subject2.getSessionId());
+ fail("Session should be invalid");
+ } catch (SessionNotFoundException e) {
+ // expected
+ }
+
+ try {
+ subjectManager.loginUnauthenticated("rhqadminX");
+ assert false : "Should not have logged in - provided a bad username";
+ } catch (LoginException ok) {
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ public void testDeleteUser() throws Exception {
+ getTransactionManager().begin();
+
+ try {
+ Subject overlord = subjectManager.getOverlord();
+
+ Subject new_user = new Subject("dummy-user", true, false);
+ new_user = subjectManager.createSubject(overlord, new_user);
+
+ Role new_role = new Role("dummy-role");
+ RoleManagerLocal roleManager = LookupUtil.getRoleManager();
+ new_role = roleManager.createRole(overlord, new_role);
+
+ // new_user.addRole(new_role);
+ int[] subjectIds = new int[] { new_user.getId() };
+ roleManager.addSubjectsToRole(overlord, new_role.getId(), subjectIds);
+ assert new_role.getSubjects().contains(new_user) : "New_role does not contain new_user";
+ int count = new_role.getSubjects().size();
+
+ subjectManager.deleteUsers(overlord, subjectIds);
+
+ assert new_role.getSubjects().size() == count - 1 : "User was not deleted from new_role";
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ }
+
+ public void testViewUsersPermission_subjectWithViewUsersRoleCanViewOtherUsers() throws Exception {
+ getTransactionManager().begin();
+
+ try {
+ Subject overlord = subjectManager.getOverlord();
+ Subject rhqadmin = subjectManager.getSubjectByName("rhqadmin");
+
+ Role roleWithViewUsersPerm = new Role("role" + UUID.randomUUID());
+ roleWithViewUsersPerm.addPermission(Permission.VIEW_USERS);
+ roleWithViewUsersPerm = roleManager.createRole(overlord, roleWithViewUsersPerm);
+
+ Subject subjectWithViewUsersRole = new Subject("subject" + UUID.randomUUID(), true, false);
+ subjectWithViewUsersRole.addRole(roleWithViewUsersPerm);
+ subjectWithViewUsersRole = subjectManager.createSubject(overlord, subjectWithViewUsersRole, "password");
+ subjectWithViewUsersRole = subjectManager.loginUnauthenticated(subjectWithViewUsersRole.getName());
+
+ Subject anotherSubject = new Subject("subject" + UUID.randomUUID(), true, false);
+ anotherSubject = subjectManager.createSubject(overlord, anotherSubject, "password");
+
+ PageList<Subject> subjects = subjectManager.findSubjectsByCriteria(subjectWithViewUsersRole, new SubjectCriteria());
+ Set<Subject> subjectSet = new HashSet<Subject>(subjects);
+ assertTrue(subjectSet.contains(subjectWithViewUsersRole));
+ assertTrue(subjectSet.contains(anotherSubject));
+ assertTrue(subjectSet.contains(rhqadmin));
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ public void testViewUsersPermission_rhqadminCanViewOtherUsers() throws Exception {
+ getTransactionManager().begin();
+
+ try {
+ Subject overlord = subjectManager.getOverlord();
+
+ Subject rhqadmin = subjectManager.getSubjectByName("rhqadmin");
+ rhqadmin = subjectManager.loginUnauthenticated(rhqadmin.getName());
+
+ Subject anotherSubject = new Subject("subject" + UUID.randomUUID(), true, false);
+ anotherSubject = subjectManager.createSubject(overlord, anotherSubject, "password");
+
+ PageList<Subject> subjects = subjectManager.findSubjectsByCriteria(rhqadmin, new SubjectCriteria());
+ Set<Subject> subjectSet = new HashSet<Subject>(subjects);
+ assertTrue(subjectSet.contains(anotherSubject));
+ assertTrue(subjectSet.contains(rhqadmin));
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ public void testViewUsersPermission_subjectWithNonViewUsersRoleCannotViewOtherUsers() throws Exception {
+ getTransactionManager().begin();
+
+ try {
+ Subject overlord = subjectManager.getOverlord();
+
+ Role roleWithoutViewUsersPerm = new Role("role" + UUID.randomUUID());
+ roleWithoutViewUsersPerm = roleManager.createRole(overlord, roleWithoutViewUsersPerm);
+
+ Subject subjectWithNonViewUsersRole = new Subject("subject" + UUID.randomUUID(), true, false);
+ subjectWithNonViewUsersRole.addRole(roleWithoutViewUsersPerm);
+ subjectWithNonViewUsersRole = subjectManager.createSubject(overlord, subjectWithNonViewUsersRole, "password");
+ subjectWithNonViewUsersRole = subjectManager.loginUnauthenticated(subjectWithNonViewUsersRole.getName());
+
+ Subject anotherSubject = new Subject("subject" + UUID.randomUUID(), true, false);
+ anotherSubject = subjectManager.createSubject(overlord, anotherSubject, "password");
+
+ PageList<Subject> subjects = subjectManager.findSubjectsByCriteria(subjectWithNonViewUsersRole, new SubjectCriteria());
+ Set<Subject> subjectSet = new HashSet<Subject>(subjects);
+ assertEquals(1, subjectSet.size());
+ assertTrue(subjectSet.contains(subjectWithNonViewUsersRole));
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ public void testViewUsersPermission_subjectWithNoRolesCannotViewOtherUsers() throws Exception {
+ getTransactionManager().begin();
+
+ try {
+ Subject overlord = subjectManager.getOverlord();
+
+ Subject subjectWithNoRoles = new Subject("subject" + UUID.randomUUID(), true, false);
+ subjectWithNoRoles = subjectManager.createSubject(overlord, subjectWithNoRoles, "password");
+ subjectWithNoRoles = subjectManager.loginUnauthenticated(subjectWithNoRoles.getName());
+
+ Subject anotherSubject = new Subject("subject" + UUID.randomUUID(), true, false);
+ anotherSubject = subjectManager.createSubject(overlord, anotherSubject, "password");
+
+ PageList<Subject> subjects = subjectManager.findSubjectsByCriteria(subjectWithNoRoles, new SubjectCriteria());
+ Set<Subject> subjectSet = new HashSet<Subject>(subjects);
+ assertEquals(1, subjectSet.size());
+ assertTrue(subjectSet.contains(subjectWithNoRoles));
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/authz/test/AuthorizationManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/authz/test/AuthorizationManagerBeanTest.java
new file mode 100644
index 0000000..ccd8eec
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/authz/test/AuthorizationManagerBeanTest.java
@@ -0,0 +1,849 @@
+/*
+ * 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.enterprise.server.authz.test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.authz.Role;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.enterprise.server.authz.AuthorizationManagerLocal;
+import org.rhq.enterprise.server.authz.RoleManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.SessionTestHelper;
+
+@Test
+public class AuthorizationManagerBeanTest extends AbstractEJB3Test {
+ private AuthorizationManagerLocal authorizationManager;
+
+ @BeforeMethod
+ @SuppressWarnings( { "unused" })
+ private void init() {
+ try {
+ authorizationManager = LookupUtil.getAuthorizationManager();
+ } catch (Throwable t) {
+ // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
+ // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+
+ /*
+ * Test methods: getGlobalPermissions(Subject) hasGlobalPermission(Subject, Permission)
+ */
+ @Test(groups = "integration.session")
+ public void testGlobalPermissions() throws Exception {
+ /*
+ * accuracy test: all global permissions applied to a single role
+ *
+ * p (all & only global perms) | subject -- role
+ */
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ /* bootstrap */
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole1 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole1");
+
+ /* setup permissions */
+ Set<Permission> globalPermissions = SessionTestHelper.getAllGlobalPerms();
+ testRole1.getPermissions().addAll(globalPermissions);
+ em.merge(testRole1);
+ em.flush();
+
+ /* verify getGlobalPermissions test */
+ Set<Permission> globalResults = authorizationManager.getExplicitGlobalPermissions(testSubject);
+ assert SessionTestHelper.samePermissions(globalPermissions, globalResults) : "Failed to get 1-subject, 1-role global permissions";
+
+ /* verify hasGlobalPermission test */
+ for (Permission permission : globalPermissions) {
+ assert (authorizationManager.hasGlobalPermission(testSubject, permission)) : "Failed to get global permission "
+ + permission.toString();
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ /*
+ * accuracy test: redundant global permissions in 2 roles
+ *
+ * p (all & only global perms) | subject -- role \ \- role |
+ * p (all & only global perms)
+ */
+ getTransactionManager().begin();
+ em = getEntityManager();
+ try {
+ /* bootstrap */
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole1 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole1");
+ Role testRole2 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole2");
+
+ /* setup permissions */
+ Set<Permission> globalPermissions = SessionTestHelper.getAllGlobalPerms();
+ testRole1.getPermissions().addAll(globalPermissions);
+ testRole2.getPermissions().addAll(globalPermissions);
+ em.merge(testRole1);
+ em.merge(testRole2);
+ em.flush();
+
+ /* verify getGlobalPermissions test */
+ Set<Permission> globalResults = authorizationManager.getExplicitGlobalPermissions(testSubject);
+ assert SessionTestHelper.samePermissions(globalPermissions, globalResults) : "Failed to get 1-subject, 2-role distinct global permissions";
+
+ /* verify hasGlobalPermission test */
+ for (Permission permission : globalPermissions) {
+ assert (authorizationManager.hasGlobalPermission(testSubject, permission)) : "Failed to get global permission "
+ + permission.toString();
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ /*
+ * negative test: no global perms on either role
+ *
+ * p (no global perms) | subject -- role \ \- role | p
+ * (no global perms)
+ */
+ getTransactionManager().begin();
+ em = getEntityManager();
+ try {
+ /* bootstrap */
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole1 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole1");
+ Role testRole2 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole2");
+
+ /* setup permissions */
+ testRole1.getPermissions().add(Permission.CONTROL);
+ testRole2.getPermissions().add(Permission.CONFIGURE_WRITE);
+ em.merge(testRole1);
+ em.merge(testRole2);
+ em.flush();
+
+ /* verify getGlobalPermissions test */
+ Set<Permission> noPermissions = EnumSet.noneOf(Permission.class);
+ Set<Permission> noResults = authorizationManager.getExplicitGlobalPermissions(testSubject);
+ assert SessionTestHelper.samePermissions(noPermissions, noResults) : "Failed by getting resource permissions as global permissions";
+
+ /* verify hasGlobalPermission test */
+ Set<Permission> globalPermissions = SessionTestHelper.getAllGlobalPerms();
+ for (Permission permission : globalPermissions) {
+ assert (!authorizationManager.hasGlobalPermission(testSubject, permission)) : "Failed by a resource permission as a global permission "
+ + permission.toString();
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ /*
+ * Test methods: getGroupPermissions(Subject, ResourceGroup) hasGroupPermission(Subject, Permission,
+ * ResourceGroup)
+ */
+ @Test(groups = "integration.session")
+ public void testGroupPermissions() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ /*
+ * accuracy test: simplest case
+ *
+ * p (mixed permissions) | subject -- role -- group
+ */
+ try {
+ /* bootstrap */
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole1 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole1");
+ ResourceGroup testGroup1 = SessionTestHelper.createNewMixedGroupForRole(em, testRole1, "testGroup1", false);
+
+ /* setup permissions */
+ Set<Permission> someMixedPermissions = EnumSet.of(Permission.CONFIGURE_WRITE, Permission.CONTROL,
+ Permission.MANAGE_SECURITY);
+ testRole1.getPermissions().addAll(someMixedPermissions);
+ em.merge(testRole1);
+ em.flush();
+
+ /* verify getGroupPermissions test */
+ Set<Permission> someMixedResults = authorizationManager.getExplicitGroupPermissions(testSubject, testGroup1
+ .getId());
+ assert SessionTestHelper.samePermissions(someMixedPermissions, someMixedResults) : "Failed to get all 1-role, 1-group permissions";
+
+ /* verify hasGroupPermission test */
+ for (Permission permission : someMixedPermissions) {
+ assert (authorizationManager.hasGroupPermission(testSubject, permission, testGroup1.getId())) : "Failed to get single single 1-role, 1-group permission "
+ + permission.toString();
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ /*
+ * accuracy test: no overlap of permissions, groups should return different sets
+ *
+ * p (some permissions) | subject -- role -- group \ \- role -- group
+ * | p (other permissions)
+ */
+ getTransactionManager().begin();
+ em = getEntityManager();
+ try {
+ /* bootstrap */
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole1 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole1");
+ ResourceGroup testGroup1 = SessionTestHelper.createNewMixedGroupForRole(em, testRole1, "testGroup1", false);
+
+ Role testRole2 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole2");
+ ResourceGroup testGroup2 = SessionTestHelper.createNewMixedGroupForRole(em, testRole2, "testGroup2", false);
+
+ /* setup permissions */
+ Set<Permission> someMixedPermissions = EnumSet.of(Permission.MANAGE_INVENTORY, Permission.MANAGE_CONTENT,
+ Permission.DELETE_RESOURCE);
+ testRole1.getPermissions().addAll(someMixedPermissions);
+ em.merge(testRole1);
+ em.flush();
+
+ Set<Permission> otherMixedPermissions = EnumSet.of(Permission.CONFIGURE_WRITE, Permission.MANAGE_INVENTORY,
+ Permission.MANAGE_SECURITY);
+ testRole2.getPermissions().addAll(otherMixedPermissions);
+ em.merge(testRole2);
+ em.flush();
+
+ /* verify getGroupPermissions test */
+ Set<Permission> someMixedResults = authorizationManager.getExplicitGroupPermissions(testSubject, testGroup1
+ .getId());
+ assert SessionTestHelper.samePermissions(someMixedPermissions, someMixedResults) : "Failed to get all 2-role, 2-group permissions";
+
+ /* verify hasGroupPermission test */
+ for (Permission permission : someMixedPermissions) {
+ assert (authorizationManager.hasGroupPermission(testSubject, permission, testGroup1.getId())) : "Failed to get single single 1-role, 1-group permission "
+ + permission.toString();
+ }
+
+ /* verify getGroupPermissions test */
+ Set<Permission> otherMixedResults = authorizationManager.getExplicitGroupPermissions(testSubject,
+ testGroup2.getId());
+ assert SessionTestHelper.samePermissions(otherMixedPermissions, otherMixedResults) : "Failed to get all 2-role, 2-group permissions";
+
+ /* verify hasGroupPermission test */
+ for (Permission permission : otherMixedPermissions) {
+ assert (authorizationManager.hasGroupPermission(testSubject, permission, testGroup2.getId())) : "Failed to get single single 1-role, 1-group permission "
+ + permission.toString();
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ /*
+ * accuracy test: disjoint sets of permissions, results should be the simple union
+ *
+ * p | subject -- role -- group \ / \- role -/ |
+ * p
+ */
+ getTransactionManager().begin();
+ em = getEntityManager();
+ try {
+ /* bootstrap */
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole1 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole1");
+ Role testRole2 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole2");
+ ResourceGroup testGroup1 = SessionTestHelper.createNewMixedGroupForRole(em, testRole1, "testGroup1", false);
+
+ testRole2.getResourceGroups().add(testGroup1);
+ testGroup1.addRole(testRole2);
+ em.merge(testRole2);
+ em.merge(testGroup1);
+ em.flush();
+
+ /* setup permissions */
+ Set<Permission> someMixedPermissions = EnumSet.of(Permission.CONFIGURE_WRITE, Permission.CONTROL,
+ Permission.MANAGE_SECURITY);
+ testRole1.getPermissions().addAll(someMixedPermissions);
+ em.merge(testRole1);
+ em.flush();
+
+ Set<Permission> otherMixedPermissions = EnumSet.of(Permission.MANAGE_INVENTORY, Permission.MANAGE_CONTENT,
+ Permission.DELETE_RESOURCE);
+ testRole2.getPermissions().addAll(otherMixedPermissions);
+ em.merge(testRole2);
+ em.flush();
+
+ /* setup shared object for result testing */
+ Set<Permission> totalMixedPermissions = EnumSet.noneOf(Permission.class);
+ totalMixedPermissions.addAll(someMixedPermissions);
+ totalMixedPermissions.addAll(otherMixedPermissions);
+
+ /* verify getGroupPermissions test */
+ Set<Permission> totalMixedResults = authorizationManager.getExplicitGroupPermissions(testSubject,
+ testGroup1.getId());
+ assert SessionTestHelper.samePermissions(totalMixedPermissions, totalMixedResults) : "Failed to get all 1-role, 2-group permissions";
+
+ /* verify hasGroupPermission test */
+ for (Permission permission : totalMixedPermissions) {
+ assert (authorizationManager.hasGroupPermission(testSubject, permission, testGroup1.getId())) : "Failed to get single single 1-role, 2-group permission "
+ + permission.toString();
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ /*
+ * accuracy test: intersecting sets of permissions, results should be the distinct union
+ *
+ * p | subject -- role -- group \ / \- role -/ |
+ * p
+ */
+ getTransactionManager().begin();
+ em = getEntityManager();
+ try {
+ /* bootstrap */
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole1 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole1");
+ Role testRole2 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole2");
+ ResourceGroup testGroup1 = SessionTestHelper.createNewMixedGroupForRole(em, testRole1, "testGroup1", false);
+
+ testRole2.getResourceGroups().add(testGroup1);
+ testGroup1.addRole(testRole2);
+ em.merge(testRole2);
+ em.merge(testGroup1);
+ em.flush();
+
+ /* setup permissions */
+ Set<Permission> someMixedPermissions = EnumSet.of(Permission.CONFIGURE_WRITE, Permission.CONTROL,
+ Permission.MANAGE_SECURITY);
+ testRole1.getPermissions().addAll(someMixedPermissions);
+ em.merge(testRole1);
+ em.flush();
+
+ Set<Permission> otherMixedPermissions = EnumSet.of(Permission.MANAGE_INVENTORY, Permission.MANAGE_CONTENT,
+ Permission.DELETE_RESOURCE);
+ testRole2.getPermissions().addAll(otherMixedPermissions);
+ em.merge(testRole2);
+ em.flush();
+
+ /* setup redundant permissions */
+ testRole2.getPermissions().addAll(someMixedPermissions);
+ em.merge(testRole2);
+ em.flush();
+
+ /* setup shared object for result testing */
+ Set<Permission> totalMixedPermissions = EnumSet.noneOf(Permission.class);
+ totalMixedPermissions.addAll(someMixedPermissions);
+ totalMixedPermissions.addAll(otherMixedPermissions);
+
+ /* verify getGroupPermissions test */
+ Set<Permission> totalMixedDistinctResults = authorizationManager.getExplicitGroupPermissions(testSubject,
+ testGroup1.getId());
+ assert SessionTestHelper.samePermissions(totalMixedPermissions, totalMixedDistinctResults) : "Failed to get all 1-role, 2-group distinct permissions";
+
+ /* verify hasGroupPermission test */
+ for (Permission permission : totalMixedPermissions) {
+ assert (authorizationManager.hasGroupPermission(testSubject, permission, testGroup1.getId())) : "Failed to get single single 1-role, 2-group distinct permission "
+ + permission.toString();
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test
+ public void testCanViewResourcesWhenSubjectIsInRole() throws Exception {
+ getTransactionManager().begin();
+ EntityManager entityMgr = getEntityManager();
+
+ try {
+ Subject subject = SessionTestHelper.createNewSubject(entityMgr, "testSubject");
+
+ Role roleWithSubject = SessionTestHelper.createNewRoleForSubject(entityMgr, subject, "role with subject");
+ roleWithSubject.addPermission(Permission.VIEW_RESOURCE);
+
+ ResourceGroup group = SessionTestHelper.createNewCompatibleGroupForRole(entityMgr, roleWithSubject,
+ "accessible group");
+
+ Resource r1 = SessionTestHelper.createNewResourceForGroup(entityMgr, group, "r1");
+ Resource r2 = SessionTestHelper.createNewResourceForGroup(entityMgr, group, "r2");
+
+ entityMgr.flush();
+
+ List<Integer> resourceIds = Arrays.asList(r1.getId(), r2.getId());
+
+ assertTrue("The subject should have permission to view the resources", authorizationManager
+ .canViewResources(subject, resourceIds));
+
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test
+ public void testCanViewResourceWhenSubjectIsInMultipleRolesAndResourcesInMultipleGroups() throws Exception {
+ getTransactionManager().begin();
+ EntityManager entityMgr = getEntityManager();
+
+ try {
+ Subject subject = SessionTestHelper.createNewSubject(entityMgr, "testSubject");
+
+ Role role1 = SessionTestHelper.createNewRoleForSubject(entityMgr, subject, "role1");
+ role1.addPermission(Permission.VIEW_RESOURCE);
+
+ Role role2 = SessionTestHelper.createNewRoleForSubject(entityMgr, subject, "role2");
+ role2.addPermission(Permission.VIEW_RESOURCE);
+
+ ResourceGroup group1 = SessionTestHelper.createNewCompatibleGroupForRole(entityMgr, role1, "group 1");
+ ResourceGroup group2 = SessionTestHelper.createNewCompatibleGroupForRole(entityMgr, role2, "group 2");
+
+ Resource r1 = SessionTestHelper.createNewResourceForGroup(entityMgr, group1, "r1");
+ Resource r2 = SessionTestHelper.createNewResourceForGroup(entityMgr, group2, "r2");
+
+ entityMgr.flush();
+
+ List<Integer> resourceIds = Arrays.asList(r1.getId(), r2.getId());
+
+ assertTrue(
+ "The subject should have permission to view the resources in different groups since the subject is in roles for those groups",
+ authorizationManager.canViewResources(subject, resourceIds));
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test
+ public void testCanViewResourcesWhenSubjectIsNotInRole() throws Exception {
+ getTransactionManager().begin();
+ EntityManager entityMgr = getEntityManager();
+
+ try {
+ Subject subject = SessionTestHelper.createNewSubject(entityMgr, "testSubject");
+ Subject subjectNotInRole = SessionTestHelper.createNewSubject(entityMgr, "subjectNotInRole");
+
+ Role roleWithSubject = SessionTestHelper.createNewRoleForSubject(entityMgr, subject, "role with subject");
+ roleWithSubject.addPermission(Permission.VIEW_RESOURCE);
+
+ ResourceGroup group = SessionTestHelper.createNewCompatibleGroupForRole(entityMgr, roleWithSubject,
+ "accessible group");
+
+ Resource r1 = SessionTestHelper.createNewResourceForGroup(entityMgr, group, "r1");
+ Resource r2 = SessionTestHelper.createNewResourceForGroup(entityMgr, group, "r2");
+
+ entityMgr.flush();
+
+ List<Integer> resourceIds = Arrays.asList(r1.getId(), r2.getId());
+
+ assertFalse("The subject should not have permission to view the resources", authorizationManager
+ .canViewResources(subjectNotInRole, resourceIds));
+
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ /*
+ * Test methods: getResourcePermissions(Subject, Resource) hasResourcePermission(Subject, Permission, Resource)
+ * hasResourcePermission(Subject, Permission, Collection<Resource>)
+ */
+ @Test(groups = "integration.session")
+ public void testResourcePermissions() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ /*
+ * p | subject -- role -- group -- resource
+ */
+ try {
+ /* bootstrap */
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole1 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole1");
+ ResourceGroup testGroup1 = SessionTestHelper.createNewMixedGroupForRole(em, testRole1, "testGroup1", false);
+ Resource resource1 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource1");
+ Resource resource2 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource2");
+ Resource resource3 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource3");
+
+ /* setup permissions */
+ Set<Permission> allPermissions = EnumSet.allOf(Permission.class);
+ testRole1.getPermissions().addAll(allPermissions);
+ em.merge(testRole1);
+ em.flush();
+
+ /* verify getResourcePermissions test */
+ Set<Permission> allPermissionsResults = authorizationManager.getExplicitResourcePermissions(testSubject,
+ resource1.getId());
+ assert SessionTestHelper.samePermissions(allPermissions, allPermissionsResults) : "Failed to get all 1-role, 1-group, 1-resource permissions";
+
+ /* verify hasResourcePermission test */
+ for (Permission permission : allPermissions) {
+ assert (authorizationManager.hasResourcePermission(testSubject, permission, resource1.getId())) : "Failed to get single 1-role, 1-group, 1-resource permission";
+ }
+
+ /* verify hasResourcePermission(collection) test */
+ Collection<Integer> allResources = SessionTestHelper.getResourceList(resource1, resource2, resource3);
+
+ for (Permission permission : allPermissions) {
+ assert (authorizationManager.hasResourcePermission(testSubject, permission, allResources)) : "Failed to get every positive 1-role, 1-group, resource-list permission";
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ /*
+ * p | subject -- role -- group -- resource \ / \- role -/
+ * | p without redundant permissions
+ */
+ getTransactionManager().begin();
+ em = getEntityManager();
+ try {
+ /* bootstrap */
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole1 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole1");
+ ResourceGroup testGroup1 = SessionTestHelper.createNewMixedGroupForRole(em, testRole1, "testGroup1", false);
+ Resource resource1 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource1");
+ Resource resource2 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource2");
+ Resource resource3 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource3");
+
+ Role testRole2 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole2");
+ testRole2.getResourceGroups().add(testGroup1);
+ testGroup1.addRole(testRole2);
+ em.merge(testRole2);
+ em.merge(testGroup1);
+ em.flush();
+
+ /* setup permissions */
+ Set<Permission> somePermissions = EnumSet.of(Permission.CONFIGURE_WRITE);
+ Set<Permission> otherPermissions = EnumSet.of(Permission.CONTROL);
+ testRole1.getPermissions().addAll(somePermissions);
+ testRole2.getPermissions().addAll(otherPermissions);
+ em.merge(testRole1);
+ em.merge(testRole2);
+ em.flush();
+
+ /* setup shared object for result testing */
+ Set<Permission> allPermissions = EnumSet.noneOf(Permission.class);
+ allPermissions.addAll(somePermissions);
+ allPermissions.addAll(otherPermissions);
+
+ /* verify getResourcePermissions test */
+ Set<Permission> allPermissionsResults = authorizationManager.getExplicitResourcePermissions(testSubject,
+ resource1.getId());
+ assert SessionTestHelper.samePermissions(allPermissions, allPermissionsResults) : "Failed to get all 2-role, 1-group, 1-resource permissions";
+
+ /* verify hasResourcePermission test */
+ for (Permission permission : allPermissions) {
+ assert (authorizationManager.hasResourcePermission(testSubject, permission, resource1.getId())) : "Failed to get single 2-role, 1-group, 1-resource permission";
+ }
+
+ /* verify hasResourcePermission(collection) test */
+ Collection<Integer> allResources = SessionTestHelper.getResourceList(resource1, resource2, resource3);
+ for (Permission permission : allPermissions) {
+ assert (authorizationManager.hasResourcePermission(testSubject, permission, allResources)) : "Failed to get every positive 2-role, 1-group, resource-list permission";
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ /*
+ * p | subject -- role -- group -- resource \ / \- role --
+ * group -/ | p without redundant permissions
+ */
+ getTransactionManager().begin();
+ em = getEntityManager();
+ try {
+ /* bootstrap */
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole1 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole1");
+ ResourceGroup testGroup1 = SessionTestHelper.createNewMixedGroupForRole(em, testRole1, "testGroup1", false);
+ Resource resource1 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource1");
+ Resource resource2 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource2");
+ Resource resource3 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource3");
+
+ Role testRole2 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole2");
+ ResourceGroup testGroup2 = SessionTestHelper.createNewMixedGroupForRole(em, testRole2, "testGroup2", false);
+
+ testGroup2.addExplicitResource(resource1);
+ resource1.getExplicitGroups().add(testGroup2);
+
+ /*
+ * Single resource implies the implicit resource list should mirror the explicit one
+ */
+ testGroup2.addImplicitResource(resource1);
+ resource1.getImplicitGroups().add(testGroup2);
+
+ em.merge(testGroup2);
+ em.merge(resource1);
+ em.flush();
+
+ /* setup permissions */
+ Set<Permission> sharedPermissions = EnumSet.of(Permission.MANAGE_CONTENT);
+ Set<Permission> otherPermissions = EnumSet.of(Permission.MANAGE_SECURITY);
+ testRole1.getPermissions().addAll(sharedPermissions);
+ testRole2.getPermissions().addAll(otherPermissions);
+ em.merge(testRole1);
+ em.merge(testRole2);
+ em.flush();
+
+ /* setup shared object for result testing */
+ Set<Permission> allPermissions = EnumSet.noneOf(Permission.class);
+ allPermissions.addAll(sharedPermissions);
+ allPermissions.addAll(otherPermissions);
+
+ /* verify getResourcePermissions test */
+ Set<Permission> allPermissionsResults = authorizationManager.getExplicitResourcePermissions(testSubject,
+ resource1.getId());
+ assert SessionTestHelper.samePermissions(allPermissions, allPermissionsResults) : "Failed to get all 2-role, 2-group, 1-resource permissions";
+
+ /* verify hasResourcePermission test */
+ for (Permission permission : allPermissions) {
+ assert (authorizationManager.hasResourcePermission(testSubject, permission, resource1.getId())) : "Failed to get single 2-role, 2-group, 1-resource permission";
+ }
+
+ /* verify hasResourcePermission(collection) test */
+ Collection<Integer> allResources = SessionTestHelper.getResourceList(resource1, resource2, resource3);
+
+ for (Permission permission : sharedPermissions) {
+ assert (authorizationManager.hasResourcePermission(testSubject, permission, allResources)) : "Failed to get every positive 2-role, 2-group, resource-list permission";
+ }
+
+ for (Permission permission : otherPermissions) {
+ assert (!authorizationManager.hasResourcePermission(testSubject, permission, allResources)) : "Failed to get every negative 2-role, 2-group, resource-list permission";
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ /*
+ * p | subject -- role -- group -- resource \ / \-
+ * group -/
+ */
+ getTransactionManager().begin();
+ em = getEntityManager();
+ try {
+ /* bootstrap */
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole1 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole1");
+ ResourceGroup testGroup1 = SessionTestHelper.createNewMixedGroupForRole(em, testRole1, "testGroup1", false);
+ Resource resource1 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource1");
+ Resource resource2 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource2");
+ Resource resource3 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource3");
+
+ ResourceGroup testGroup2 = SessionTestHelper.createNewMixedGroupForRole(em, testRole1, "testGroup2", false);
+
+ testGroup2.addExplicitResource(resource1);
+ resource1.getExplicitGroups().add(testGroup2);
+
+ /*
+ * Single resource implies the implicit resource list should mirror the explicit one
+ */
+ testGroup2.addImplicitResource(resource1);
+ resource1.getImplicitGroups().add(testGroup2);
+
+ em.merge(testGroup2);
+ em.merge(resource1);
+ em.flush();
+
+ /* setup permissions */
+ Set<Permission> sharedPermissions = EnumSet.of(Permission.MANAGE_SETTINGS, Permission.MANAGE_ALERTS);
+ testRole1.getPermissions().addAll(sharedPermissions);
+ em.merge(testRole1);
+ em.flush();
+
+ /* verify getResourcePermissions test */
+ Set<Permission> somePermissionsResults = authorizationManager.getExplicitResourcePermissions(testSubject,
+ resource1.getId());
+ assert SessionTestHelper.samePermissions(sharedPermissions, somePermissionsResults) : "Failed to get all 1-role, 2-group, 1-resource permissions";
+
+ /* verify hasResourcePermission test */
+ for (Permission permission : sharedPermissions) {
+ assert (authorizationManager.hasResourcePermission(testSubject, permission, resource1.getId())) : "Failed to get single 1-role, 2-group, 1-resource permission";
+ }
+
+ /* verify hasResourcePermission(collection) test */
+ Collection<Integer> allResources = SessionTestHelper.getResourceList(resource1, resource2, resource3);
+ for (Permission permission : sharedPermissions) {
+ assert (authorizationManager.hasResourcePermission(testSubject, permission, allResources)) : "Failed to get every positive 1-role, 2-group, resource-list permission";
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ /*
+ * p | subject -- role -- group -- resource \ \/ / \ /\
+ * / \ role -- group / | p with highly redundant permissions
+ */
+ getTransactionManager().begin();
+ em = getEntityManager();
+ try {
+ /* bootstrap */
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole1 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole1");
+ ResourceGroup testGroup1 = SessionTestHelper.createNewMixedGroupForRole(em, testRole1, "testGroup1", false);
+ Resource resource1 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource1");
+ Resource resource2 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource2");
+ Resource resource3 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource3");
+
+ Role testRole2 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole2");
+ ResourceGroup testGroup2 = SessionTestHelper.createNewMixedGroupForRole(em, testRole2, "testGroup2", false);
+
+ testGroup2.addRole(testRole1);
+ testRole1.getResourceGroups().add(testGroup2);
+
+ testGroup1.addRole(testRole2);
+ testRole2.getResourceGroups().add(testGroup1);
+
+ testGroup2.addExplicitResource(resource1);
+ resource1.getExplicitGroups().add(testGroup2);
+
+ /*
+ * Single resource implies the implicit resource list should mirror the explicit one
+ */
+ testGroup2.addImplicitResource(resource1);
+ resource1.getImplicitGroups().add(testGroup2);
+
+ em.merge(testGroup1);
+ em.merge(testGroup2);
+ em.merge(testRole1);
+ em.merge(testRole2);
+ em.merge(resource1);
+ em.flush();
+
+ /* setup permissions */
+ Set<Permission> somePermissions = EnumSet.of(Permission.CONFIGURE_WRITE, Permission.CONTROL,
+ Permission.MANAGE_INVENTORY);
+ Set<Permission> otherPermissions = EnumSet.of(Permission.CONTROL, Permission.MANAGE_SECURITY,
+ Permission.MANAGE_INVENTORY);
+ testRole1.getPermissions().addAll(somePermissions);
+ testRole2.getPermissions().addAll(otherPermissions);
+ em.merge(testRole1);
+ em.merge(testRole2);
+ em.flush();
+
+ /* setup shared object for result testing */
+ Set<Permission> allPermissions = EnumSet.noneOf(Permission.class);
+ allPermissions.addAll(somePermissions);
+ allPermissions.addAll(otherPermissions);
+
+ /* verify getResourcePermissions test */
+ Set<Permission> allPermissionsResults = authorizationManager.getExplicitResourcePermissions(testSubject,
+ resource1.getId());
+ assert SessionTestHelper.samePermissions(allPermissions, allPermissionsResults) : "Failed to get all 2-role crossed 2-group, 1-resource distinct permissions";
+
+ /* verify hasResourcePermission test */
+ for (Permission permission : allPermissions) {
+ assert (authorizationManager.hasResourcePermission(testSubject, permission, resource1.getId())) : "Failed to get single 2-role crossed 2-group, 1-resource distinct permission";
+ }
+
+ /* verify hasResourcePermission(collection) test */
+ Collection<Integer> allResources = SessionTestHelper.getResourceList(resource1, resource2, resource3);
+ for (Permission permission : allPermissions) {
+ assert (authorizationManager.hasResourcePermission(testSubject, permission, allResources)) : "Failed to get every positive 2-role crossed 2-group, resource-list permission";
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ /*
+ * p | subject -- role -- group -- resource \ \- role -- group -- resource
+ * | p
+ */
+ getTransactionManager().begin();
+ em = getEntityManager();
+ try {
+ /* bootstrap */
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole1 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole1");
+ Role testRole2 = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole2");
+ ResourceGroup testGroup1 = SessionTestHelper.createNewMixedGroupForRole(em, testRole1, "testGroup1", false);
+ ResourceGroup testGroup2 = SessionTestHelper.createNewMixedGroupForRole(em, testRole2, "testGroup2", false);
+ Resource resource1 = SessionTestHelper.createNewResourceForGroup(em, testGroup1, "testResource1");
+ Resource resource2 = SessionTestHelper.createNewResourceForGroup(em, testGroup2, "testResource2");
+
+ /* setup permissions */
+ Set<Permission> somePermissions = EnumSet.of(Permission.MANAGE_ALERTS, Permission.MANAGE_SETTINGS);
+ Set<Permission> otherPermissions = EnumSet.of(Permission.MANAGE_ALERTS, Permission.MANAGE_CONTENT);
+ testRole1.getPermissions().addAll(somePermissions);
+ testRole2.getPermissions().addAll(otherPermissions);
+ em.merge(testRole1);
+ em.merge(testRole2);
+ em.flush();
+
+ /* setup shared object for result testing */
+ Set<Permission> intersection = EnumSet.copyOf(somePermissions);
+ intersection.retainAll(otherPermissions);
+
+ Set<Permission> symmetricDifference = EnumSet.copyOf(somePermissions);
+ symmetricDifference.addAll(otherPermissions);
+ symmetricDifference.removeAll(intersection);
+
+ Collection<Integer> allResources = SessionTestHelper.getResourceList(resource1, resource2);
+
+ /* verify hasResourcePermission(collection) test */
+ for (Permission permission : intersection) {
+ assert (authorizationManager.hasResourcePermission(testSubject, permission, allResources)) : "Failed to get every positive 2-role independent 2-group, resource-list permission";
+ }
+
+ for (Permission permission : symmetricDifference) {
+ assert (!authorizationManager.hasResourcePermission(testSubject, permission, allResources)) : "Failed to get every negative 2-role independent 2-group, resource-list permission";
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test(groups = "integration.session")
+ public void testSetPermission() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole");
+
+ // moved setPerm to the role manager - leave this test here, just use that manager instead
+ RoleManagerLocal roleManager = LookupUtil.getRoleManager();
+ Subject superuser = LookupUtil.getSubjectManager().getOverlord();
+
+ /* verify role got all global permissions */
+ Set<Permission> globalPermissions = SessionTestHelper.getAllGlobalPerms();
+ roleManager.setPermissions(superuser, testRole.getId(), globalPermissions);
+ em.refresh(testRole);
+ assert SessionTestHelper.samePermissions(testRole.getPermissions(), globalPermissions) : "Failed to set global permissions";
+
+ /* verify role still has global and got all resource permissions */
+ Set<Permission> resourcePermissions = SessionTestHelper.getAllResourcePerms();
+ roleManager.setPermissions(superuser, testRole.getId(), resourcePermissions);
+ em.refresh(testRole);
+ assert SessionTestHelper.samePermissions(testRole.getPermissions(), resourcePermissions) : "Failed to set resource permissions";
+
+ /* verify role still has global and got all resource permissions */
+ Set<Permission> noPermissions = EnumSet.noneOf(Permission.class);
+ roleManager.setPermissions(superuser, testRole.getId(), noPermissions);
+ em.refresh(testRole);
+ assert SessionTestHelper.samePermissions(testRole.getPermissions(), noPermissions) : "Failed to set empty list of permissions";
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/authz/test/RoleManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/authz/test/RoleManagerBeanTest.java
new file mode 100644
index 0000000..c316462
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/authz/test/RoleManagerBeanTest.java
@@ -0,0 +1,286 @@
+/*
+ * 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.enterprise.server.authz.test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.authz.Role;
+import org.rhq.core.domain.resource.group.LdapGroup;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.authz.PermissionException;
+import org.rhq.enterprise.server.authz.RoleManagerLocal;
+import org.rhq.enterprise.server.resource.group.LdapGroupManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Tests the role manager.
+ */
+@Test
+public class RoleManagerBeanTest extends AbstractEJB3Test {
+ private SubjectManagerLocal subjectManager;
+ private RoleManagerLocal roleManager;
+ private LdapGroupManagerLocal ldapManager;
+
+ /**
+ * Prepares things for the entire test class.
+ */
+ @BeforeClass
+ public void beforeClass() {
+ roleManager = LookupUtil.getRoleManager();
+ subjectManager = LookupUtil.getSubjectManager();
+ ldapManager = LookupUtil.getLdapGroupManager();
+ }
+
+ /**
+ * Tests getting all roles.
+ */
+ public void testGetAllRoles() {
+ assert roleManager.findRoles(PageControl.getUnlimitedInstance()).size() > 0;
+ }
+
+ /**
+ * Tests getting all roles for a user.
+ *
+ * @throws Exception
+ */
+ public void testGetSubjectRoles() throws Exception {
+ getTransactionManager().begin();
+
+ try {
+ PageList<Role> roles = roleManager.findRolesBySubject(subjectManager.getOverlord().getId(), PageControl
+ .getUnlimitedInstance());
+ assert roles.size() == 1;
+
+ Role role = roles.get(0);
+ assert role.getName().equals("Super User Role") : "Superuser should have only the super user role: " + role;
+ assert role.getPermissions().contains(Permission.MANAGE_SECURITY);
+ assert role.getPermissions().contains(Permission.MANAGE_INVENTORY);
+ assert role.getPermissions().contains(Permission.MANAGE_SETTINGS);
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ /**
+ * Tests getting all subjects for a particular role.
+ *
+ * @throws Exception
+ */
+ public void testGetRoleSubjects() throws Exception {
+ getTransactionManager().begin();
+
+ try {
+ PageList<Role> roles = roleManager.findRolesBySubject(subjectManager.getOverlord().getId(), PageControl
+ .getUnlimitedInstance());
+
+ for (Role role : roles) {
+ PageList<Subject> subjects = roleManager.findSubjectsByRole(role.getId(), PageControl
+ .getUnlimitedInstance());
+ if (role.getName().equals("Super User Role")) {
+ assert subjects.size() >= 1 : "At least rhqadmin must have super user role: " + subjects;
+
+ for (Subject s : subjects) {
+ if ((s.getId() == 1) || s.getName().equals("admin")) {
+ assert false : "getRoleSubjects() is not supposed to return the superuser" + s;
+ }
+ }
+ }
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ /**
+ * Tests getting roles by their IDs.
+ *
+ * @throws Exception
+ */
+ public void testGetRolesByIds() throws Exception {
+ getTransactionManager().begin();
+ try {
+ PageList<Role> all_roles = roleManager.findRoles(PageControl.getUnlimitedInstance());
+ List<Integer> role_id_list = new ArrayList<Integer>(all_roles.size());
+ for (Role role : all_roles) {
+ role_id_list.add(role.getId());
+ }
+
+ PageList<Role> roles = roleManager.findRolesByIds(role_id_list.toArray(new Integer[0]), PageControl
+ .getUnlimitedInstance());
+ assert roles.size() == all_roles.size();
+ assert roles.containsAll(all_roles);
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ /**
+ * Tests getting roles that are not already assigned to a subject and not part of an exclusion list of roles.
+ *
+ * @throws Exception
+ */
+ public void testGetAvailableRolesForSubject() throws Exception {
+ getTransactionManager().begin();
+ try {
+ Subject superuser = subjectManager.getOverlord();
+ superuser = createSession(superuser);
+
+ Subject subject = new Subject();
+ subject.setName("dummy-subject");
+ subject = subjectManager.createSubject(superuser, subject);
+ subject = createSession(subject);
+
+ Role new_role = new Role("dummy-role");
+ Role new_role2 = new Role("dummy-role2");
+ new_role = roleManager.createRole(superuser, new_role);
+ new_role2 = roleManager.createRole(superuser, new_role2);
+
+ PageList<Role> all_roles = roleManager.findRoles(PageControl.getUnlimitedInstance());
+ assert all_roles.size() >= 3 : "There should at least be the two dummy roles and the super user role";
+
+ PageList<Role> roles;
+
+ roles = roleManager.findAvailableRolesForSubject(superuser, subject.getId(), new Integer[0], PageControl
+ .getUnlimitedInstance());
+
+ assert roles.size() == all_roles.size() : "All roles should be available for this subject";
+ assert roles.containsAll(all_roles);
+
+ roles = roleManager.findAvailableRolesForSubject(superuser, subject.getId(), new Integer[] { new_role
+ .getId() }, PageControl.getUnlimitedInstance());
+ assert (roles.size() + 1) == all_roles.size() : "All roles but one should be available for this subject";
+ assert !roles.contains(new_role);
+
+ roles = roleManager.findAvailableRolesForSubject(superuser, subject.getId(), new Integer[] {
+ new_role.getId(), new_role2.getId() }, PageControl.getUnlimitedInstance());
+ assert (roles.size() + 2) == all_roles.size() : "All roles but two should be available for this subject";
+ assert !roles.contains(new_role);
+ assert !roles.contains(new_role2);
+
+ roleManager.addRolesToSubject(superuser, subject.getId(), new int[] { new_role.getId() });
+ roles = roleManager.findAvailableRolesForSubject(superuser, subject.getId(), new Integer[0], PageControl
+ .getUnlimitedInstance());
+ assert (roles.size() + 1) == all_roles.size() : "All but one role should be available for this subject";
+ assert !roles.contains(new_role) : "We already assigned this new role to the subject - it isn't available";
+
+ roles = roleManager.findAvailableRolesForSubject(superuser, subject.getId(), new Integer[] { new_role2
+ .getId() }, PageControl.getUnlimitedInstance());
+ assert (roles.size() + 2) == all_roles.size() : "One is already assigned and one is excluded so all but two roles should be available for this subject";
+ assert !roles.contains(new_role) : "We already assigned this new role to the subject - it isn't available";
+ assert !roles.contains(new_role2) : "We excluded this new role - it isn't available";
+
+ try {
+ // dummy user doesn't have the permission for this
+ roles = roleManager.findAvailableRolesForSubject(subject, subject.getId(), new Integer[0], PageControl
+ .getUnlimitedInstance());
+ } catch (PermissionException s) {
+ // to be expected, this rolls the transaction back for us
+ }
+ } finally {
+ try {
+ getTransactionManager().rollback();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ /**
+ * Test creating, assigning, removing and deleting roles.
+ *
+ * @throws Exception
+ */
+ public void testRoles() throws Exception {
+ getTransactionManager().begin();
+
+ try {
+ Subject newSubject1 = new Subject();
+ newSubject1.setName("role-manager-subject");
+ newSubject1.setFsystem(false);
+
+ Subject newSubject2 = new Subject();
+ newSubject2.setName("secondary-role-manager");
+ newSubject2.setFsystem(false);
+
+ Role role = new Role("role-manager-role");
+ role.setFsystem(false);
+ role.addSubject(newSubject1);
+
+ Subject superuser = subjectManager.getOverlord();
+ subjectManager.createSubject(superuser, newSubject1);
+ newSubject1 = createSession(newSubject1);
+
+ subjectManager.createSubject(superuser, newSubject2);
+ newSubject2 = createSession(newSubject2);
+
+ assertEquals("Role should not be created or assigned yet", 0, roleManager.findRolesBySubject(
+ newSubject1.getId(), PageControl.getUnlimitedInstance()).size());
+
+ role = roleManager.createRole(superuser, role);
+ assertEquals("Role should be assigned at the time the role is created", 1, roleManager.findRolesBySubject(
+ newSubject1.getId(), PageControl.getUnlimitedInstance()).size());
+
+ roleManager.addRolesToSubject(superuser, newSubject2.getId(), new int[] { role.getId() });
+ assertEquals("Role should be assigned", 1, roleManager.findRolesBySubject(newSubject2.getId(),
+ PageControl.getUnlimitedInstance()).size());
+
+ roleManager.removeRolesFromSubject(superuser, newSubject1.getId(), new int[] { role.getId() });
+ assertEquals("Role should have been unassigned", 0, roleManager.findRolesBySubject(newSubject1.getId(),
+ PageControl.getUnlimitedInstance()).size());
+
+ roleManager.deleteRoles(superuser, new int[] { role.getId() });
+ assertFalse("Roles should have been deleted", roleManager.findRoles(PageControl.getUnlimitedInstance())
+ .contains(role));
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ /**
+ * Test creating, assigning, removing and deleting roles.
+ *
+ * @throws Exception
+ */
+ public void testLdapGroups() throws Exception {
+ getTransactionManager().begin();
+
+ try {
+ Subject superuser = subjectManager.getOverlord();
+ superuser = createSession(superuser);
+
+ Role role = new Role("role-manager-role");
+ role.setFsystem(false);
+ role = roleManager.createRole(superuser, role);
+ LdapGroup group = new LdapGroup();
+ group.setName("Foo");
+ role.addLdapGroup(group);
+ assert ldapManager.findLdapGroupsByRole(role.getId(), PageControl.getUnlimitedInstance()).size() == 1 : "Ldap Group Foo Should be assigned";
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java
new file mode 100644
index 0000000..1621dac
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java
@@ -0,0 +1,1195 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.bundle;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import javax.transaction.TransactionManager;
+
+import org.hibernate.LazyInitializationException;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.bundle.Bundle;
+import org.rhq.core.domain.bundle.BundleDeployment;
+import org.rhq.core.domain.bundle.BundleDeploymentStatus;
+import org.rhq.core.domain.bundle.BundleDestination;
+import org.rhq.core.domain.bundle.BundleFile;
+import org.rhq.core.domain.bundle.BundleResourceDeployment;
+import org.rhq.core.domain.bundle.BundleResourceDeploymentHistory;
+import org.rhq.core.domain.bundle.BundleType;
+import org.rhq.core.domain.bundle.BundleVersion;
+import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration;
+import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory;
+import org.rhq.core.domain.bundle.composite.BundleWithLatestVersionComposite;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.configuration.definition.PropertySimpleType;
+import org.rhq.core.domain.content.Architecture;
+import org.rhq.core.domain.content.Package;
+import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.criteria.BundleCriteria;
+import org.rhq.core.domain.criteria.BundleDeploymentCriteria;
+import org.rhq.core.domain.criteria.BundleFileCriteria;
+import org.rhq.core.domain.criteria.BundleResourceDeploymentCriteria;
+import org.rhq.core.domain.criteria.BundleVersionCriteria;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.InventoryStatus;
+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.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
+import org.rhq.core.util.file.FileUtil;
+import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.core.util.updater.DeploymentProperties;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestAgentClient;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.ResourceTreeHelper;
+
+/**
+ * @author John Mazzitelli
+ * @author Jay Shaughnessy
+ */
+@SuppressWarnings({ "unused" })
+@Test
+public class BundleManagerBeanTest extends AbstractEJB3Test {
+
+ private static final boolean TESTS_ENABLED = true;
+
+ private static final String TEST_PREFIX = "bundletest";
+ private static final String TEST_BUNDLE_DESTBASEDIR_PROP = TEST_PREFIX + ".destBaseDirProp";
+ private static final String TEST_BUNDLE_DESTBASEDIR_PROP_VALUE = TEST_PREFIX + "/destBaseDir";
+ private static final String TEST_DESTBASEDIR_NAME = TEST_PREFIX + ".destBaseDirName";
+
+ private BundleManagerLocal bundleManager;
+ private ResourceManagerLocal resourceManager;
+ private static final boolean ENABLED = true;
+ private static final boolean DISABLED = false;
+
+ private TestBundleServerPluginService ps;
+ private MasterServerPluginContainer pc;
+ private Subject overlord;
+ TestServerCommunicationsService agentServiceContainer;
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ agentServiceContainer = prepareForTestAgents();
+ agentServiceContainer.bundleService = new TestAgentClient(null, agentServiceContainer);
+
+ this.ps = new TestBundleServerPluginService();
+ prepareCustomServerPluginService(this.ps);
+ bundleManager = LookupUtil.getBundleManager();
+ resourceManager = LookupUtil.getResourceManager();
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+ this.ps.startMasterPluginContainer();
+
+ // try and clean up any junk that may be lying around from a failed run
+ cleanupDatabase();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ unprepareForTestAgents();
+
+ try {
+ this.ps = null;
+ cleanupDatabase();
+ } finally {
+ unprepareServerPluginService();
+ }
+ }
+
+ private void cleanupDatabase() {
+ EntityManager em = null;
+
+ try {
+ getTransactionManager().begin();
+ em = getEntityManager();
+
+ Query q;
+ List<?> doomed;
+
+ // clean up any tests that don't already clean up after themselves
+
+ // remove bundleversions which cascade remove bundlefiles and bundledeployments
+ // bundlefiles cascaderemove packageversions
+ // bundledeployments cascade remove bundleresourcedeployments
+ // bundleresourcedeployments cascade remove bundleresourcedeploymenthistory
+ q = em.createQuery("SELECT bv FROM BundleVersion bv WHERE bv.name LIKE '" + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(BundleVersion.class, ((BundleVersion) removeMe).getId()));
+ }
+ em.flush();
+ // remove any orphaned bfs
+ q = em.createQuery("SELECT bf FROM BundleFile bf WHERE bf.packageVersion.generalPackage.name LIKE '"
+ + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(BundleFile.class, ((BundleFile) removeMe).getId()));
+ }
+ // remove any orphaned deployment history
+ q = em
+ .createQuery("SELECT brdh FROM BundleResourceDeploymentHistory brdh WHERE brdh.resourceDeployment.bundleDeployment.name LIKE '"
+ + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(BundleResourceDeploymentHistory.class,
+ ((BundleResourceDeploymentHistory) removeMe).getId()));
+ }
+ // remove any orphaned brds
+ q = em.createQuery("SELECT brd FROM BundleResourceDeployment brd WHERE brd.bundleDeployment.name LIKE '"
+ + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(BundleResourceDeployment.class, ((BundleResourceDeployment) removeMe).getId()));
+ }
+ // remove any orphaned bds
+ q = em.createQuery("SELECT bd FROM BundleDeployment bd WHERE bd.description LIKE '" + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(BundleDeployment.class, ((BundleDeployment) removeMe).getId()));
+ }
+
+ // remove bundles which cascade remove packageTypes and destinations
+ // packagetypes cascade remove packages
+ // package cascade remove packageversions
+ q = em.createQuery("SELECT b FROM Bundle b WHERE b.name LIKE '" + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(Bundle.class, ((Bundle) removeMe).getId()));
+ }
+ em.flush();
+ // remove any orphaned pvs
+ q = em.createQuery("SELECT pv FROM PackageVersion pv WHERE pv.generalPackage.name LIKE '" + TEST_PREFIX
+ + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(PackageVersion.class, ((PackageVersion) removeMe).getId()));
+ }
+ // remove any oprphaned packages
+ q = em.createQuery("SELECT p FROM Package p WHERE p.name LIKE '" + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(Package.class, ((Package) removeMe).getId()));
+ }
+ // remove any orphaned packagetypes
+ q = em.createQuery("SELECT pt FROM PackageType pt WHERE pt.name LIKE '" + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(PackageType.class, ((PackageType) removeMe).getId()));
+ }
+ // remove any orphaned destinations
+ q = em.createQuery("SELECT bd FROM BundleDestination bd WHERE bd.name LIKE '" + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(BundleDestination.class, ((BundleDestination) removeMe).getId()));
+ }
+
+ // remove repos no longer referenced by bundles
+ q = em.createQuery("SELECT r FROM Repo r WHERE r.name LIKE '" + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(Repo.class, ((Repo) removeMe).getId()));
+ }
+
+ // remove Resource Groups left over from test deployments freeing up test resources
+ q = em.createQuery("SELECT rg FROM ResourceGroup rg WHERE rg.name LIKE '" + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(ResourceGroup.class, ((ResourceGroup) removeMe).getId()));
+ }
+
+ // remove Resources in test groups
+ q = em.createQuery("SELECT r FROM Resource r WHERE r.name LIKE '" + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ ResourceTreeHelper.deleteResource(em, em.getReference(Resource.class, ((Resource) removeMe).getId()));
+ }
+
+ // remove ResourceTypes which cascade remove BundleTypes
+ q = em.createQuery("SELECT rt FROM ResourceType rt WHERE rt.deleted = false and rt.name LIKE '"
+ + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(ResourceType.class, ((ResourceType) removeMe).getId()));
+ }
+ em.flush();
+ // remove any orphaned BundleTypes
+ q = em.createQuery("SELECT bt FROM BundleType bt WHERE bt.name LIKE '" + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(BundleType.class, ((BundleType) removeMe).getId()));
+ }
+
+ // remove Agents left over from test resources
+ q = em.createQuery("SELECT a FROM Agent a WHERE a.name LIKE '" + TEST_PREFIX + "%'");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ em.remove(em.getReference(Agent.class, ((Agent) removeMe).getId()));
+ }
+
+ getTransactionManager().commit();
+ em.close();
+ em = null;
+ } catch (Exception e) {
+ try {
+ System.out.println("CANNOT CLEAN UP TEST: Cause: " + e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+ } finally {
+ if (null != em) {
+ em.close();
+ }
+ }
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testCreateBundleVersionFromDistributionFile() throws Exception {
+
+ File tmpDir = FileUtil.createTempDirectory("createBundleFromDistro", ".dir", null);
+ try {
+ String bundleFile1 = TEST_PREFIX + "_subdir1/bundle-file-1.txt";
+ String bundleFile2 = TEST_PREFIX + "_subdir2/bundle-file-2.txt";
+ String bundleFile3 = TEST_PREFIX + "_bundle-file-3.txt";
+ writeFile(new File(tmpDir, bundleFile1), "first bundle file found inside bundle distro");
+ writeFile(new File(tmpDir, bundleFile2), "second bundle file found inside bundle distro");
+ writeFile(new File(tmpDir, bundleFile3), "third bundle file found inside bundle distro");
+
+ String bundleName = TEST_PREFIX + "-create-from-distro";
+ String bundleVersion = "1.2.3";
+ String bundleDescription = "test bundle desc";
+ DeploymentProperties bundleMetadata = new DeploymentProperties(0, bundleName, bundleVersion,
+ bundleDescription);
+
+ ConfigurationDefinition configDef = new ConfigurationDefinition("foo", null);
+ int propDefaultValue1 = 998877;
+ String propDefaultValue4 = "this.is.the.default";
+ String propName1 = "prop1requiredWithDefault";
+ String propName2 = "prop2";
+ String propName3 = "prop3requiredWithNoDefault";
+ String propName4 = "prop4notRequiredWithDefault";
+ String propDesc1 = "prop1desc";
+ String propDesc2 = "prop2desc";
+ String propDesc3 = "prop3desc";
+ String propDesc4 = "prop4desc";
+ PropertyDefinitionSimple propdef1requiredWithDefault = new PropertyDefinitionSimple(propName1, propDesc1,
+ true, PropertySimpleType.INTEGER);
+ PropertyDefinitionSimple propdef2 = new PropertyDefinitionSimple(propName2, propDesc2, false,
+ PropertySimpleType.STRING);
+ PropertyDefinitionSimple propdef3requiredWithNoDefault = new PropertyDefinitionSimple(propName3, propDesc3,
+ true, PropertySimpleType.STRING);
+ PropertyDefinitionSimple propdef4notRequiredWithDefault = new PropertyDefinitionSimple(propName4,
+ propDesc4, false, PropertySimpleType.STRING);
+ propdef1requiredWithDefault.setDefaultValue(String.valueOf(propDefaultValue1));
+ propdef4notRequiredWithDefault.setDefaultValue(propDefaultValue4);
+ configDef.put(propdef1requiredWithDefault);
+ configDef.put(propdef2);
+ configDef.put(propdef3requiredWithNoDefault);
+ configDef.put(propdef4notRequiredWithDefault);
+
+ Map<String, File> bundleFiles = new HashMap<String, File>(3);
+ bundleFiles.put(bundleFile1, new File(tmpDir, bundleFile1));
+ bundleFiles.put(bundleFile2, new File(tmpDir, bundleFile2));
+ bundleFiles.put(bundleFile3, new File(tmpDir, bundleFile3));
+
+ File bundleDistroFile = tmpDir; // not a real distro zip, but its just a simulation anyway - SLSB will pass this to our mock PC
+ String recipe = "mock recipe";
+ BundleType bt1 = createBundleType("one");
+
+ // prepare our mock bundle PC
+ ps.parseRecipe_returnValue = new RecipeParseResults(bundleMetadata, configDef, new HashSet<String>(
+ bundleFiles.keySet()));
+ ps.processBundleDistributionFile_returnValue = new BundleDistributionInfo(recipe,
+ ps.parseRecipe_returnValue, bundleFiles);
+ ps.processBundleDistributionFile_returnValue.setBundleTypeName(bt1.getName());
+
+ // now ask the SLSB to persist our bundle data given our mock distribution
+ BundleVersion bv1 = bundleManager.createBundleVersionViaURL(overlord, bundleDistroFile.toURI().toURL()
+ .toString());
+
+ // to a db lookup to make sure our bundle version is queryable
+ BundleVersionCriteria criteria = new BundleVersionCriteria();
+ criteria.addFilterId(bv1.getId());
+ criteria.fetchBundle(true);
+ criteria.fetchConfigurationDefinition(true);
+ criteria.fetchBundleFiles(true);
+ criteria.fetchTags(true);
+ BundleVersion bv2 = bundleManager.findBundleVersionsByCriteria(overlord, criteria).get(0);
+ List<BundleFile> bv2BundleFiles = bv2.getBundleFiles();
+ BundleFileCriteria bfCriteria = new BundleFileCriteria();
+ bfCriteria.addFilterBundleVersionId(bv2.getId());
+ bfCriteria.fetchPackageVersion(true);
+ PageList<BundleFile> bfs = bundleManager.findBundleFilesByCriteria(overlord, bfCriteria);
+ bv2BundleFiles.clear();
+ bv2BundleFiles.addAll(bfs);
+ bv2.setBundleDeployments(new ArrayList<BundleDeployment>());
+
+ // test that the PC's return value and our own DB lookup match the bundle version we expect to be in the DB
+ BundleVersion[] bvs = new BundleVersion[] { bv1, bv2 };
+ for (BundleVersion bv : bvs) {
+ assert bv.getId() > 0 : bv;
+ assert bv.getBundle().getName().equals(bundleName) : bv;
+ assert bv.getBundle().getDescription().equals(bundleDescription) : bv;
+ assert bv.getDescription().equals(bundleDescription) : "the bundle version desc should be the same as the bundle desc";
+ assert bv.getVersion().equals(bundleVersion) : bv;
+ assert bv.getBundleFiles().size() == 3 : bv;
+ ArrayList<String> bundleFileNames = new ArrayList<String>(3);
+ for (BundleFile bf : bv.getBundleFiles()) {
+ bundleFileNames.add(bf.getPackageVersion().getFileName());
+ }
+ assert bundleFileNames.contains(bundleFile1) : bv;
+ assert bundleFileNames.contains(bundleFile2) : bv;
+ assert bundleFileNames.contains(bundleFile3) : bv;
+ assert bv.getBundleDeployments().isEmpty() : bv;
+ assert bv.getConfigurationDefinition().getPropertyDefinitions().size() == 4;
+ assert bv.getConfigurationDefinition().get(propName1) != null;
+ assert bv.getConfigurationDefinition().get(propName1).getDescription().equals(propDesc1);
+ assert bv.getConfigurationDefinition().get(propName1).isRequired() == true;
+ assert bv.getConfigurationDefinition().getPropertyDefinitionSimple(propName1).getType() == PropertySimpleType.INTEGER;
+ assert bv.getConfigurationDefinition().get(propName2) != null;
+ assert bv.getConfigurationDefinition().get(propName2).getDescription().equals(propDesc2);
+ assert bv.getConfigurationDefinition().get(propName2).isRequired() == false;
+ assert bv.getConfigurationDefinition().getPropertyDefinitionSimple(propName2).getType() == PropertySimpleType.STRING;
+ assert bv.getConfigurationDefinition().get(propName3) != null;
+ assert bv.getConfigurationDefinition().get(propName3).getDescription().equals(propDesc3);
+ assert bv.getConfigurationDefinition().get(propName3).isRequired() == true;
+ assert bv.getConfigurationDefinition().getPropertyDefinitionSimple(propName3).getType() == PropertySimpleType.STRING;
+ assert bv.getConfigurationDefinition().get(propName4) != null;
+ assert bv.getConfigurationDefinition().get(propName4).getDescription().equals(propDesc4);
+ assert bv.getConfigurationDefinition().get(propName4).isRequired() == false;
+ assert bv.getConfigurationDefinition().getPropertyDefinitionSimple(propName4).getType() == PropertySimpleType.STRING;
+ assert bv.getRecipe().equals(recipe);
+
+ // make sure the default template is correct
+ ConfigurationTemplate defaultTemplate = bv.getConfigurationDefinition().getDefaultTemplate();
+ Configuration defaultConfig = defaultTemplate.getConfiguration();
+ assert defaultConfig.getProperties().size() == 3; // prop2 is not required and has no default, thus is missing
+ PropertySimple prop1 = defaultConfig.getSimple(propName1);
+ PropertySimple prop2 = defaultConfig.getSimple(propName2);
+ PropertySimple prop3 = defaultConfig.getSimple(propName3);
+ PropertySimple prop4 = defaultConfig.getSimple(propName4);
+ assert prop1 != null;
+ assert prop2 == null : "prop2 was not required and has no default, it should not be in the default template config";
+ assert prop3 != null;
+ assert prop4 != null;
+ assert prop1.getIntegerValue() != null;
+ assert prop1.getIntegerValue().intValue() == propDefaultValue1;
+ assert prop3.getStringValue() == null : "prop3 was required but had no default, its template value should have been null";
+ assert prop4.getStringValue().equals(propDefaultValue4);
+ }
+ } finally {
+ FileUtil.purge(tmpDir, true);
+ }
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testGetBundleTypes() throws Exception {
+ BundleType bt1 = createBundleType("one");
+ BundleType bt2 = createBundleType("two");
+ List<BundleType> bts = bundleManager.getAllBundleTypes(overlord);
+ assert bts.size() >= 2 : "should have at least 2 bundle types";
+
+ List<String> btNames = new ArrayList<String>();
+ for (BundleType bundleType : bts) {
+ btNames.add(bundleType.getName());
+ }
+
+ assert btNames.contains(bt1.getName());
+ assert btNames.contains(bt2.getName());
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testCreateBundle() throws Exception {
+ Bundle b1 = createBundle("one");
+ assertNotNull(b1);
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testCreateBundleVersion() throws Exception {
+ Bundle b1 = createBundle("one");
+ assertNotNull(b1);
+ BundleVersion bv1 = createBundleVersion(b1.getName() + "-1", null, b1);
+ assertNotNull(bv1);
+ assertEquals("1.0", bv1.getVersion());
+ assert 0 == bv1.getVersionOrder();
+ BundleVersion bv2 = createBundleVersion(b1.getName() + "-2", null, b1);
+ assertNotNull(bv2);
+ assertEquals("1.1", bv2.getVersion());
+ assert 1 == bv2.getVersionOrder();
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testDeleteBundle() throws Exception {
+ Bundle b1 = createBundle("one");
+ assertNotNull(b1);
+ BundleVersion bv1 = createBundleVersion(b1.getName() + "-1", null, b1);
+ assertNotNull(bv1);
+ assertEquals("1.0", bv1.getVersion());
+ BundleVersion bv2 = createBundleVersion(b1.getName() + "-2", null, b1);
+ assertNotNull(bv2);
+ assertEquals("1.1", bv2.getVersion());
+
+ // let's add a bundle file so we can ensure our deletion will also delete the file too
+ bundleManager.addBundleFileViaByteArray(overlord, bv2.getId(), "testDeleteBundle", "1.0", new Architecture(
+ "noarch"), "content".getBytes());
+ BundleFileCriteria bfCriteria = new BundleFileCriteria();
+ bfCriteria.addFilterBundleVersionId(bv2.getId());
+ bfCriteria.fetchPackageVersion(true);
+ PageList<BundleFile> files = bundleManager.findBundleFilesByCriteria(overlord, bfCriteria);
+ assert files.size() == 1 : files;
+ assert files.get(0).getPackageVersion().getGeneralPackage().getName().equals("testDeleteBundle") : files;
+
+ bundleManager.deleteBundle(overlord, b1.getId());
+
+ BundleCriteria bCriteria = new BundleCriteria();
+ bCriteria.addFilterId(b1.getId());
+ PageList<Bundle> bResults = bundleManager.findBundlesByCriteria(overlord, bCriteria);
+ assert bResults.size() == 0;
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testDeleteBundleVersion() throws Exception {
+ Bundle b1 = createBundle("one");
+ assertNotNull(b1);
+ BundleVersion bv1 = createBundleVersion(b1.getName() + "-1", null, b1);
+ assertNotNull(bv1);
+ assertEquals("1.0", bv1.getVersion());
+ BundleVersion bv2 = createBundleVersion(b1.getName() + "-2", null, b1);
+ assertNotNull(bv2);
+ assertEquals("1.1", bv2.getVersion());
+
+ // let's add a bundle file so we can ensure our deletion will also delete the file too
+ bundleManager.addBundleFileViaByteArray(overlord, bv2.getId(), "testDeleteBundleVersion", "1.0",
+ new Architecture("noarch"), "content".getBytes());
+ BundleFileCriteria bfCriteria = new BundleFileCriteria();
+ bfCriteria.addFilterBundleVersionId(bv2.getId());
+ bfCriteria.fetchPackageVersion(true);
+ PageList<BundleFile> files = bundleManager.findBundleFilesByCriteria(overlord, bfCriteria);
+ assert files.size() == 1 : files;
+ assert files.get(0).getPackageVersion().getGeneralPackage().getName().equals("testDeleteBundleVersion") : files;
+
+ BundleVersionCriteria bvCriteria = new BundleVersionCriteria();
+ BundleCriteria bCriteria = new BundleCriteria();
+
+ // delete the first one - this deletes the BV but the bundle should remain intact
+ bundleManager.deleteBundleVersion(overlord, bv2.getId(), true);
+ bvCriteria.addFilterId(bv2.getId());
+ PageList<BundleVersion> bvResults = bundleManager.findBundleVersionsByCriteria(overlord, bvCriteria);
+ assert bvResults.size() == 0;
+ bCriteria.addFilterId(b1.getId());
+ PageList<Bundle> bResults = bundleManager.findBundlesByCriteria(overlord, bCriteria);
+ assert bResults.size() == 1 : "Should not have deleted bundle yet, 1 version still exists";
+
+ // delete the second one - this deletes last BV thus the bundle should also get deleted
+ bundleManager.deleteBundleVersion(overlord, bv1.getId(), true);
+ bvCriteria.addFilterId(bv1.getId());
+ bvResults = bundleManager.findBundleVersionsByCriteria(overlord, bvCriteria);
+ assert bvResults.size() == 0;
+ bCriteria.addFilterId(b1.getId());
+ bResults = bundleManager.findBundlesByCriteria(overlord, bCriteria);
+ assert bResults.size() == 0 : "Should have deleted bundle since no versions exists anymore";
+
+ // make sure our composite query is OK and can show us 0 bundles, too
+ PageList<BundleWithLatestVersionComposite> composites;
+ bCriteria = new BundleCriteria();
+ composites = bundleManager.findBundlesWithLatestVersionCompositesByCriteria(overlord, bCriteria);
+ assert composites.size() == 0;
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testCreateBundleVersionOrdering() throws Exception {
+ Bundle b1 = createBundle("one");
+ assertNotNull(b1);
+
+ BundleCriteria criteria = new BundleCriteria();
+ criteria.addSortName(PageOrdering.ASC);
+ PageList<BundleWithLatestVersionComposite> results;
+
+ // verify there are no bundle versions yet
+ results = bundleManager.findBundlesWithLatestVersionCompositesByCriteria(overlord, criteria);
+ assert results.get(0).getBundleId().equals(b1.getId());
+ assert results.get(0).getBundleName().equals(b1.getName());
+ assert results.get(0).getBundleDescription().equals(b1.getDescription());
+ assert results.get(0).getLatestVersion() == null;
+ assert results.get(0).getVersionsCount().longValue() == 0L;
+
+ BundleVersion bv1 = createBundleVersion(b1.getName() + "-1", "1.0", b1);
+ assertNotNull(bv1);
+ assertEquals("1.0", bv1.getVersion());
+ assert 0 == bv1.getVersionOrder();
+ results = bundleManager.findBundlesWithLatestVersionCompositesByCriteria(overlord, criteria);
+ assert results.get(0).getBundleId().equals(b1.getId());
+ assert results.get(0).getBundleName().equals(b1.getName());
+ assert results.get(0).getBundleDescription().equals(b1.getDescription());
+ assert results.get(0).getLatestVersion().equals("1.0");
+ assert results.get(0).getVersionsCount().longValue() == 1L;
+
+ BundleVersion bv2 = createBundleVersion(b1.getName() + "-2", "2.0", b1);
+ assertNotNull(bv2);
+ assertEquals("2.0", bv2.getVersion());
+ assert 1 == bv2.getVersionOrder();
+ results = bundleManager.findBundlesWithLatestVersionCompositesByCriteria(overlord, criteria);
+ assert results.get(0).getBundleId().equals(b1.getId());
+ assert results.get(0).getBundleName().equals(b1.getName());
+ assert results.get(0).getBundleDescription().equals(b1.getDescription());
+ assert results.get(0).getLatestVersion().equals("2.0");
+ assert results.get(0).getVersionsCount().longValue() == 2L;
+
+ BundleVersion bv3 = createBundleVersion(b1.getName() + "-3", "1.5", b1);
+ assertNotNull(bv3);
+ assertEquals("1.5", bv3.getVersion());
+ assert 1 == bv3.getVersionOrder();
+ results = bundleManager.findBundlesWithLatestVersionCompositesByCriteria(overlord, criteria);
+ assert results.get(0).getBundleId().equals(b1.getId());
+ assert results.get(0).getBundleName().equals(b1.getName());
+ assert results.get(0).getBundleDescription().equals(b1.getDescription());
+ assert results.get(0).getLatestVersion().equals("2.0");
+ assert results.get(0).getVersionsCount().longValue() == 3L;
+
+ BundleVersionCriteria c = new BundleVersionCriteria();
+ PageList<BundleVersion> bvs = null;
+
+ c.addFilterId(bv1.getId()); // 1.0
+ bvs = bundleManager.findBundleVersionsByCriteria(overlord, c);
+ assertNotNull(bvs);
+ assertEquals(1, bvs.size());
+ assert bvs.get(0).getVersionOrder() == 0; // 1st is the 1.0 version
+
+ c.addFilterId(bv2.getId()); // 2.0
+ bvs = bundleManager.findBundleVersionsByCriteria(overlord, c);
+ assertNotNull(bvs);
+ assertEquals(1, bvs.size());
+ assert bvs.get(0).getVersionOrder() == 2; // 3rd is the 2.0 version
+
+ c.addFilterId(bv3.getId()); // 1.5
+ bvs = bundleManager.findBundleVersionsByCriteria(overlord, c);
+ assertNotNull(bvs);
+ assertEquals(1, bvs.size());
+ assert bvs.get(0).getVersionOrder() == 1; // 2nd is the 1.5 version
+
+ // see that we can create a really old bundle and versionOrder gets updated properly
+ BundleVersion bv4 = createBundleVersion(b1.getName() + "-4", "0.5", b1);
+ assertNotNull(bv4);
+ assertEquals("0.5", bv4.getVersion());
+
+ c.addFilterId(bv4.getId()); //0.5
+ bvs = bundleManager.findBundleVersionsByCriteria(overlord, c);
+ assertNotNull(bvs);
+ assertEquals(1, bvs.size());
+ assert bvs.get(0).getVersionOrder() == 0; // 1st is the 0.5 version
+
+ c.addFilterId(bv1.getId()); // 1.0
+ bvs = bundleManager.findBundleVersionsByCriteria(overlord, c);
+ assertNotNull(bvs);
+ assertEquals(1, bvs.size());
+ assert bvs.get(0).getVersionOrder() == 1; // 2nd is the 1.0 version
+
+ c.addFilterId(bv3.getId()); // 1.5
+ bvs = bundleManager.findBundleVersionsByCriteria(overlord, c);
+ assertNotNull(bvs);
+ assertEquals(1, bvs.size());
+ assert bvs.get(0).getVersionOrder() == 2; // 3nd is the 1.5 version
+
+ c.addFilterId(bv2.getId()); // 2.0
+ bvs = bundleManager.findBundleVersionsByCriteria(overlord, c);
+ assertNotNull(bvs);
+ assertEquals(1, bvs.size());
+ assert bvs.get(0).getVersionOrder() == 3; // 4th is the 2.0 version
+
+ // verify our composite criteria query can return more than one item
+ Bundle b2 = createBundle("two");
+ assertNotNull(b2);
+ results = bundleManager.findBundlesWithLatestVersionCompositesByCriteria(overlord, criteria);
+ assert results.size() == 2 : results;
+ assert results.get(0).getBundleId().equals(b1.getId());
+ assert results.get(0).getBundleName().equals(b1.getName());
+ assert results.get(0).getBundleDescription().equals(b1.getDescription());
+ assert results.get(0).getLatestVersion().equals("2.0");
+ assert results.get(0).getVersionsCount().longValue() == 4L;
+ assert results.get(1).getBundleId().equals(b2.getId());
+ assert results.get(1).getBundleName().equals(b2.getName());
+ assert results.get(1).getBundleDescription().equals(b2.getDescription());
+ assert results.get(1).getLatestVersion() == null;
+ assert results.get(1).getVersionsCount().longValue() == 0L;
+
+ BundleVersion b2_bv1 = createBundleVersion(b2.getName() + "-5", "9.1", b2);
+ assertNotNull(b2_bv1);
+ assertEquals("9.1", b2_bv1.getVersion());
+
+ results = bundleManager.findBundlesWithLatestVersionCompositesByCriteria(overlord, criteria);
+ assert results.size() == 2 : results;
+ assert results.get(0).getBundleId().equals(b1.getId());
+ assert results.get(0).getBundleName().equals(b1.getName());
+ assert results.get(0).getBundleDescription().equals(b1.getDescription());
+ assert results.get(0).getLatestVersion().equals("2.0");
+ assert results.get(0).getVersionsCount().longValue() == 4L;
+ assert results.get(1).getBundleId().equals(b2.getId());
+ assert results.get(1).getBundleName().equals(b2.getName());
+ assert results.get(1).getBundleDescription().equals(b2.getDescription());
+ assert results.get(1).getLatestVersion().equals("9.1");
+ assert results.get(1).getVersionsCount().longValue() == 1L;
+
+ // test sorting of the BundleWithLastestVersionComposite
+ criteria.addSortName(PageOrdering.DESC);
+ results = bundleManager.findBundlesWithLatestVersionCompositesByCriteria(overlord, criteria);
+ assert results.size() == 2 : results;
+ assert results.get(1).getBundleId().equals(b1.getId());
+ assert results.get(1).getBundleName().equals(b1.getName());
+ assert results.get(1).getBundleDescription().equals(b1.getDescription());
+ assert results.get(1).getLatestVersion().equals("2.0");
+ assert results.get(1).getVersionsCount().longValue() == 4L;
+ assert results.get(0).getBundleId().equals(b2.getId());
+ assert results.get(0).getBundleName().equals(b2.getName());
+ assert results.get(0).getBundleDescription().equals(b2.getDescription());
+ assert results.get(0).getLatestVersion().equals("9.1");
+ assert results.get(0).getVersionsCount().longValue() == 1L;
+
+ criteria.addSortName(PageOrdering.ASC);
+ results = bundleManager.findBundlesWithLatestVersionCompositesByCriteria(overlord, criteria);
+ assert results.size() == 2 : results;
+ assert results.get(0).getBundleId().equals(b1.getId());
+ assert results.get(0).getBundleName().equals(b1.getName());
+ assert results.get(0).getBundleDescription().equals(b1.getDescription());
+ assert results.get(0).getLatestVersion().equals("2.0");
+ assert results.get(0).getVersionsCount().longValue() == 4L;
+ assert results.get(1).getBundleId().equals(b2.getId());
+ assert results.get(1).getBundleName().equals(b2.getName());
+ assert results.get(1).getBundleDescription().equals(b2.getDescription());
+ assert results.get(1).getLatestVersion().equals("9.1");
+ assert results.get(1).getVersionsCount().longValue() == 1L;
+
+ // now delete one of the older bundle versions and make sure the ordering remains intact
+ bundleManager.deleteBundleVersion(overlord, bv1.getId(), true);
+ results = bundleManager.findBundlesWithLatestVersionCompositesByCriteria(overlord, criteria);
+ assert results.size() == 2 : results;
+ assert results.get(0).getBundleId().equals(b1.getId());
+ assert results.get(0).getBundleName().equals(b1.getName());
+ assert results.get(0).getBundleDescription().equals(b1.getDescription());
+ assert results.get(0).getLatestVersion().equals("2.0");
+ assert results.get(0).getVersionsCount().longValue() == 3L;
+ assert results.get(1).getBundleId().equals(b2.getId());
+ assert results.get(1).getBundleName().equals(b2.getName());
+ assert results.get(1).getBundleDescription().equals(b2.getDescription());
+ assert results.get(1).getLatestVersion().equals("9.1");
+ assert results.get(1).getVersionsCount().longValue() == 1L;
+
+ // now add another bundle version and make sure the ordering is updated properly [BZ 828905]
+ BundleVersion bv5 = createBundleVersion(b1.getName() + "-5", "5.0", b1);
+ assertNotNull(bv5);
+ assertEquals("5.0", bv5.getVersion());
+ assert 3 == bv5.getVersionOrder();
+ results = bundleManager.findBundlesWithLatestVersionCompositesByCriteria(overlord, criteria);
+ assert results.get(0).getBundleId().equals(b1.getId());
+ assert results.get(0).getBundleName().equals(b1.getName());
+ assert results.get(0).getBundleDescription().equals(b1.getDescription());
+ assert results.get(0).getLatestVersion().equals("5.0");
+ assert results.get(0).getVersionsCount().longValue() == 4L;
+
+ // delete the latest bundle version and make sure we didn't screw up the order
+ bundleManager.deleteBundleVersion(overlord, bv5.getId(), true);
+ results = bundleManager.findBundlesWithLatestVersionCompositesByCriteria(overlord, criteria);
+ assert results.get(0).getBundleId().equals(b1.getId());
+ assert results.get(0).getBundleName().equals(b1.getName());
+ assert results.get(0).getBundleDescription().equals(b1.getDescription());
+ assert results.get(0).getLatestVersion().equals("2.0");
+ assert results.get(0).getVersionsCount().longValue() == 3L;
+
+ // delete the oldest bundle version and make sure we didn't screw up the order
+ bundleManager.deleteBundleVersion(overlord, bv4.getId(), true); // deleting version 0.5
+ results = bundleManager.findBundlesWithLatestVersionCompositesByCriteria(overlord, criteria);
+ assert results.get(0).getBundleId().equals(b1.getId());
+ assert results.get(0).getBundleName().equals(b1.getName());
+ assert results.get(0).getBundleDescription().equals(b1.getDescription());
+ assert results.get(0).getLatestVersion().equals("2.0");
+ assert results.get(0).getVersionsCount().longValue() == 2L;
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testAddBundleFiles() throws Exception {
+ Bundle b1 = createBundle("one");
+ assertNotNull(b1);
+ BundleVersion bv1 = createBundleVersion(b1.getName(), "1.0", b1);
+ assertNotNull(bv1);
+ BundleFile bf1 = bundleManager.addBundleFileViaByteArray(overlord, bv1.getId(), TEST_PREFIX + "-bundlefile-1",
+ "1.0", null, "Test Bundle File # 1".getBytes());
+ BundleFile bf2 = bundleManager.addBundleFileViaByteArray(overlord, bv1.getId(), TEST_PREFIX + "-bundlefile-2",
+ "1.0", null, "Test Bundle File # 2".getBytes());
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testAddBundleFilesToDifferentBundles() throws Exception {
+ // create a bundle type to use for both bundles.
+ BundleType bt = createBundleType("one");
+ Bundle b1 = createBundle("one", bt);
+ assertNotNull(b1);
+ BundleVersion bv1 = createBundleVersion(b1.getName(), "1.0", b1);
+ assertNotNull(bv1);
+ BundleFile b1f1 = bundleManager.addBundleFileViaByteArray(overlord, bv1.getId(), TEST_PREFIX + "-file1", "1.0",
+ null, "Bundle #1 File # 1".getBytes());
+
+ // create a second bundle but create file of the same name as above
+ Bundle b2 = createBundle("two", bt);
+ assertNotNull(b2);
+ BundleVersion bv2 = createBundleVersion(b2.getName(), "1.0", b2);
+ assertNotNull(bv2);
+ BundleFile b2f1 = bundleManager.addBundleFileViaByteArray(overlord, bv2.getId(), TEST_PREFIX + "-file1", "1.0",
+ null, "Bundle #2 File # 1".getBytes());
+
+ BundleFileCriteria bfc = new BundleFileCriteria();
+ bfc.addFilterBundleVersionId(bv1.getId());
+ PageList<BundleFile> bundleFiles = bundleManager.findBundleFilesByCriteria(overlord, bfc);
+ assert bundleFiles.size() == 1 : bundleFiles;
+ assert bundleFiles.get(0).getId() == b1f1.getId() : bundleFiles;
+
+ bfc = new BundleFileCriteria();
+ bfc.addFilterBundleVersionId(bv2.getId());
+ bundleFiles = bundleManager.findBundleFilesByCriteria(overlord, bfc);
+ assert bundleFiles.size() == 1 : bundleFiles;
+ assert bundleFiles.get(0).getId() == b2f1.getId() : bundleFiles;
+
+ assert b1f1.getId() != b2f1.getId() : "should have been different bundle files";
+ assert b1f1.getPackageVersion().getId() != b2f1.getPackageVersion().getId() : "should be different PV";
+ assert b1f1.getPackageVersion().getGeneralPackage().getId() != b2f1.getPackageVersion().getGeneralPackage()
+ .getId() : "package IDs should be different";
+ assert !b1f1.getPackageVersion().getGeneralPackage().equals(b2f1.getPackageVersion().getGeneralPackage()) : "should be different packages";
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testCreateBundleDeployment() throws Exception {
+ Bundle b1 = createBundle("one");
+ assertNotNull(b1);
+ BundleVersion bv1 = createBundleVersion(b1.getName() + "-1", null, b1);
+ assertNotNull(bv1);
+ ResourceGroup platformResourceGroup = createTestResourceGroup();
+ assertNotNull(platformResourceGroup);
+ BundleDestination dest1 = createDestination(b1, "one", "/test", platformResourceGroup);
+ assertNotNull(dest1);
+ Configuration config = new Configuration();
+ BundleDeployment bd1;
+ try {
+ bd1 = createDeployment("one", bv1, dest1, config);
+ fail("Bad config was accepted");
+ } catch (Exception e) {
+ // expected due to bad config
+ }
+ config.put(new PropertySimple("bundletest.property", "bundletest.property value"));
+ bd1 = createDeployment("one", bv1, dest1, config);
+ assertNotNull(bd1);
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testDeployBundle() throws Exception {
+ Bundle b1 = createBundle("one");
+ assertNotNull(b1);
+ BundleVersion bv1 = createBundleVersion(b1.getName() + "-1", null, b1);
+ assertNotNull(bv1);
+ Configuration config = new Configuration();
+ config.put(new PropertySimple("bundletest.property", "bundletest.property value"));
+ ResourceGroup platformResourceGroup = createTestResourceGroup();
+ assertNotNull(platformResourceGroup);
+ BundleDestination dest1 = createDestination(b1, "one", "/test", platformResourceGroup);
+ assertNotNull(dest1);
+ BundleDeployment bd1 = createDeployment("one", bv1, dest1, config);
+ assertNotNull(bd1);
+ assertEquals(BundleDeploymentStatus.PENDING, bd1.getStatus());
+
+ BundleDeployment bd1d = bundleManager.scheduleBundleDeployment(overlord, bd1.getId(), false);
+ assertNotNull(bd1d);
+ assertEquals(bd1.getId(), bd1d.getId());
+
+ BundleDeploymentCriteria bdc = new BundleDeploymentCriteria();
+ bdc.addFilterId(bd1d.getId());
+ bdc.fetchBundleVersion(true);
+ bdc.fetchDestination(true);
+ bdc.fetchResourceDeployments(true);
+ bdc.fetchTags(true);
+ List<BundleDeployment> bds = bundleManager.findBundleDeploymentsByCriteria(overlord, bdc);
+ assertEquals(1, bds.size());
+ bd1d = bds.get(0);
+
+ assertEquals(platformResourceGroup, bd1d.getDestination().getGroup());
+ assertEquals(dest1.getId(), bd1d.getDestination().getId());
+
+ BundleResourceDeploymentCriteria c = new BundleResourceDeploymentCriteria();
+ c.addFilterBundleDeploymentId(bd1d.getId());
+ c.fetchBundleDeployment(true);
+ c.fetchHistories(true);
+ c.fetchResource(true);
+ List<BundleResourceDeployment> brds = bundleManager.findBundleResourceDeploymentsByCriteria(overlord, c);
+ assertEquals(1, brds.size());
+ assertEquals(1, bd1d.getResourceDeployments().size());
+ assertEquals(bd1d.getResourceDeployments().get(0).getId(), brds.get(0).getId());
+ BundleResourceDeployment brd = brds.get(0);
+
+ assertNotNull(brd.getBundleResourceDeploymentHistories());
+ int size = brd.getBundleResourceDeploymentHistories().size();
+ assertTrue(size > 0);
+ String auditMessage = "BundleTest-Message";
+ bundleManager.addBundleResourceDeploymentHistory(overlord, brd.getId(), new BundleResourceDeploymentHistory(
+ overlord.getName(), auditMessage, auditMessage, BundleResourceDeploymentHistory.Category.DEPLOY_STEP,
+ BundleResourceDeploymentHistory.Status.SUCCESS, auditMessage, auditMessage));
+
+ brds = bundleManager.findBundleResourceDeploymentsByCriteria(overlord, c);
+ assertEquals(1, brds.size());
+ assertEquals(brd.getId(), brds.get(0).getId());
+ brd = brds.get(0);
+ assertNotNull(brd.getBundleResourceDeploymentHistories());
+ assertTrue((size + 1) == brd.getBundleResourceDeploymentHistories().size());
+ BundleResourceDeploymentHistory newHistory = null;
+ for (BundleResourceDeploymentHistory h : brd.getBundleResourceDeploymentHistories()) {
+ if (auditMessage.equals(h.getMessage())) {
+ newHistory = h;
+ break;
+ }
+ }
+ assertNotNull(newHistory);
+ assertEquals(auditMessage, newHistory.getAction());
+ assertEquals(BundleResourceDeploymentHistory.Status.SUCCESS, newHistory.getStatus());
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testGetBundleFilenames() throws Exception {
+ Bundle b1 = createBundle("one");
+ assertNotNull(b1);
+ BundleVersion bv1 = createBundleVersion(b1.getName(), "1.0", b1);
+ assertNotNull(bv1);
+ Set<String> filenames = bundleManager.getBundleVersionFilenames(overlord, bv1.getId(), true);
+ assertNotNull(filenames);
+ assertEquals(2, filenames.size());
+ BundleFile bf1 = bundleManager.addBundleFileViaByteArray(overlord, bv1.getId(), TEST_PREFIX + "-bundlefile-1",
+ "1.0", null, "Test Bundle File # 1".getBytes());
+ filenames = bundleManager.getBundleVersionFilenames(overlord, bv1.getId(), true);
+ assertNotNull(filenames);
+ assertEquals(1, filenames.size());
+ BundleFile bf2 = bundleManager.addBundleFileViaByteArray(overlord, bv1.getId(), TEST_PREFIX + "-bundlefile-2",
+ "1.0", null, "Test Bundle File # 2".getBytes());
+ filenames = bundleManager.getBundleVersionFilenames(overlord, bv1.getId(), true);
+ assertNotNull(filenames);
+ assertEquals(0, filenames.size());
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testFindBundlesByCriteria() throws Exception {
+ Bundle b1 = createBundle("one");
+ Bundle b2 = createBundle("two");
+ BundleVersion bv1 = createBundleVersion(b1.getName(), "1.0", b1);
+ BundleVersion bv2 = createBundleVersion(b2.getName(), "1.0", b2);
+ BundleCriteria c = new BundleCriteria();
+ PageList<Bundle> bundles = null;
+ Bundle b = null;
+ String name = null;
+
+ // return all with no optional data
+ c.addFilterName(TEST_PREFIX);
+ bundles = bundleManager.findBundlesByCriteria(overlord, c);
+ assertNotNull(bundles);
+ assertEquals(2, bundles.size());
+ b = bundles.get(0);
+ name = "one";
+ assertNotNull(b);
+ assertTrue(b.getBundleType().getName(), b.getName().contains(name));
+ assertTrue(b.getBundleType().getName(), b.getBundleType().getName().contains(name));
+ try {
+ b.getBundleVersions().isEmpty();
+ fail("Should have thrown LazyInitializationException");
+ } catch (LazyInitializationException e) {
+ // expected
+ } catch (Exception e) {
+ fail("Should have thrown LazyInitializationException");
+ }
+
+ b = bundles.get(1);
+ name = "two";
+ assertNotNull(b);
+ assertTrue(b.getBundleType().getName(), b.getName().contains(name));
+ assertTrue(b.getBundleType().getName(), b.getBundleType().getName().contains(name));
+
+ // return bundle "two" using all criteria and with all optional data
+ c.addFilterId(b.getId());
+ c.addFilterName(b.getName());
+ c.addFilterBundleTypeName(b.getBundleType().getName());
+ c.fetchBundleVersions(true);
+ c.fetchRepo(true);
+ bundles = bundleManager.findBundlesByCriteria(overlord, c);
+ assertNotNull(bundles);
+ assertEquals(1, bundles.size());
+ b = bundles.get(0);
+ assertTrue(b.getBundleType().getName(), b.getName().contains(name));
+ assertTrue(b.getBundleType().getName(), b.getBundleType().getName().contains(name));
+ assertNotNull(b.getBundleVersions());
+ assertEquals(1, b.getBundleVersions().size());
+ BundleVersion bv = b.getBundleVersions().get(0);
+ assertEquals(bv2, bv);
+ assertEquals(b, bv.getBundle());
+ Repo r = b.getRepo();
+ assertNotNull(r);
+ assertEquals(b.getName(), r.getName());
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testFindBundleVersionsByCriteria() throws Exception {
+ Bundle b1 = createBundle("one");
+ BundleVersion bv1 = createBundleVersion(b1.getName(), "1.0", b1);
+ BundleVersion bv2 = createBundleVersion(b1.getName(), "2.0", b1);
+ BundleVersion bv3 = createBundleVersion(b1.getName(), "2.1", b1);
+ BundleVersionCriteria c = new BundleVersionCriteria();
+ PageList<BundleVersion> bvs = null;
+ BundleVersion bvOut = null;
+
+ // return all with no optional data
+ c.addFilterName(TEST_PREFIX);
+ bvs = bundleManager.findBundleVersionsByCriteria(overlord, c);
+ assertNotNull(bvs);
+ assertEquals(3, bvs.size());
+ assertFalse(bvs.get(0).equals(bvs.get(1)));
+ assertFalse(bvs.get(0).equals(bvs.get(2)));
+ assertFalse(bvs.get(1).equals(bvs.get(2)));
+ assertTrue(bvs.get(0).equals(bvs.get(0)));
+ assertTrue(bvs.get(0).equals(bv2) || bvs.get(1).equals(bv2) || bvs.get(2).equals(bv2));
+
+ // return bundle version using all criteria and with all optional data
+ BundleVersion bvIn = bvs.get(1);
+ c.addFilterId(bvIn.getId());
+ c.addFilterName(bvIn.getName());
+ c.addFilterBundleName("one");
+ c.addFilterVersion(bvIn.getVersion());
+ c.fetchBundle(true);
+ c.fetchBundleDeployments(true);
+ bvs = bundleManager.findBundleVersionsByCriteria(overlord, c);
+ assertNotNull(bvs);
+ assertEquals(1, bvs.size());
+ bvOut = bvs.get(0);
+ assertEquals(bvIn, bvOut);
+ assertEquals(bvOut.getBundle(), b1);
+ assertNotNull(bvOut.getBundleDeployments());
+ assertTrue(bvOut.getBundleDeployments().isEmpty());
+ }
+
+ private BundleType createBundleType(String name) throws Exception {
+ final String fullName = TEST_PREFIX + "-type-" + name;
+ ResourceType rt = createResourceTypeForBundleType(name);
+ BundleType bt = bundleManager.createBundleType(overlord, fullName, rt.getId());
+
+ assert bt.getId() > 0;
+ assert bt.getName().endsWith(fullName);
+ return bt;
+ }
+
+ private Bundle createBundle(String name) throws Exception {
+ BundleType bt = createBundleType(name);
+ return createBundle(name, bt);
+ }
+
+ private Bundle createBundle(String name, BundleType bt) throws Exception {
+ final String fullName = TEST_PREFIX + "-bundle-" + name;
+ Bundle b = bundleManager.createBundle(overlord, fullName, fullName + "-desc", bt.getId());
+
+ assert b.getId() > 0;
+ assert b.getName().endsWith(fullName);
+ return b;
+ }
+
+ private BundleVersion createBundleVersion(String name, String version, Bundle bundle) throws Exception {
+ final String fullName = TEST_PREFIX + "-bundleversion-" + version + "-" + name;
+ final String recipe = "deploy -f " + TEST_PREFIX + ".zip -d @@ test.path @@";
+ BundleVersion bv = bundleManager.createBundleVersion(overlord, bundle.getId(), fullName, fullName + "-desc",
+ version, recipe);
+
+ assert bv.getId() > 0;
+ assert bv.getName().endsWith(fullName);
+ return bv;
+ }
+
+ private BundleDestination createDestination(Bundle bundle, String name, String deployDir, ResourceGroup group)
+ throws Exception {
+ final String fullName = TEST_PREFIX + "-bundledestination-" + name;
+ BundleDestination bd = bundleManager.createBundleDestination(overlord, bundle.getId(), fullName, fullName,
+ TEST_DESTBASEDIR_NAME, deployDir, group.getId());
+
+ assert bd.getId() > 0;
+ assert bd.getName().endsWith(fullName);
+ assert bd.getDestinationBaseDirectoryName().equals(TEST_DESTBASEDIR_NAME);
+ return bd;
+ }
+
+ private BundleDeployment createDeployment(String name, BundleVersion bv, BundleDestination dest,
+ Configuration config) throws Exception {
+ final String fullName = TEST_PREFIX + "-bundledeployment-" + name;
+ BundleDeployment bd = bundleManager
+ .createBundleDeployment(overlord, bv.getId(), dest.getId(), fullName, config);
+
+ assert bd.getId() > 0;
+ assert bd.getDescription().endsWith(fullName);
+ return bd;
+ }
+
+ private ResourceType createResourceTypeForBundleType(String name) throws Exception {
+ final String fullName = TEST_PREFIX + "-resourcetype-" + name;
+ ResourceType rt = new ResourceType(fullName, "BundleManagerBeanTest", ResourceCategory.PLATFORM, null);
+
+ TransactionManager txMgr = getTransactionManager();
+ txMgr.begin();
+ EntityManager em = getEntityManager();
+ em.persist(rt);
+ em.close();
+ txMgr.commit();
+ return rt;
+ }
+
+ // lifted from ResourceManagerBeanTest, with the addition of adding bundle config to the type
+ private ResourceGroup createTestResourceGroup() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ ResourceGroup resourceGroup = null;
+ Resource resource = null;
+
+ try {
+ // Naming this with TEST_PREFIX allows cleanupDatabase to blow away these test resources along
+ // with the bundle resource type
+ ResourceType resourceType = new ResourceType(TEST_PREFIX + "-platform-" + System.currentTimeMillis(),
+ "test", ResourceCategory.PLATFORM, null);
+
+ // we need to make this test type bundle targetable
+ ConfigurationDefinition pcDef = new ConfigurationDefinition(TEST_PREFIX + "-testdef", "bundle test");
+ PropertyDefinitionSimple propDef = new PropertyDefinitionSimple(TEST_BUNDLE_DESTBASEDIR_PROP, "", true,
+ PropertySimpleType.STRING);
+ propDef.setDisplayName(TEST_BUNDLE_DESTBASEDIR_PROP);
+ pcDef.put(propDef);
+ em.persist(pcDef);
+
+ ResourceTypeBundleConfiguration rtbc = new ResourceTypeBundleConfiguration(new Configuration());
+ rtbc.addBundleDestinationBaseDirectory(TEST_DESTBASEDIR_NAME,
+ ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory.Context.pluginConfiguration.name(),
+ TEST_BUNDLE_DESTBASEDIR_PROP, null);
+ resourceType.setResourceTypeBundleConfiguration(rtbc);
+ resourceType.setPluginConfigurationDefinition(pcDef);
+
+ em.persist(resourceType);
+
+ // make sure the bundle config is ok
+ rtbc = resourceType.getResourceTypeBundleConfiguration();
+ assert rtbc != null;
+ assert rtbc.getBundleDestinationBaseDirectories().size() == 1;
+ BundleDestinationBaseDirectory bdbd = rtbc.getBundleDestinationBaseDirectories().iterator().next();
+ assert bdbd.getName().equals(TEST_DESTBASEDIR_NAME);
+ assert bdbd.getValueContext() == ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory.Context.pluginConfiguration;
+ assert bdbd.getValueName().equals(TEST_BUNDLE_DESTBASEDIR_PROP);
+
+ Agent agent = new Agent(TEST_PREFIX + "-testagent", "testaddress", 1, "", "testtoken");
+ em.persist(agent);
+ em.flush();
+
+ Configuration rc = new Configuration();
+ rc.put(new PropertySimple(TEST_BUNDLE_DESTBASEDIR_PROP, TEST_BUNDLE_DESTBASEDIR_PROP_VALUE));
+ em.persist(rc);
+
+ resource = new Resource("reskey" + System.currentTimeMillis(), TEST_PREFIX + "-resname", resourceType);
+ resource.setUuid("" + System.currentTimeMillis());
+ resource.setInventoryStatus(InventoryStatus.COMMITTED);
+ resource.setAgent(agent);
+ resource.setResourceConfiguration(rc);
+ em.persist(resource);
+
+ resourceGroup = new ResourceGroup(TEST_PREFIX + "-group-" + System.currentTimeMillis());
+ resourceGroup.addExplicitResource(resource);
+ resourceGroup.setResourceType(resourceType); // need to tell the group the type it is
+ em.persist(resourceGroup);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ System.out.println("CANNOT PREPARE TEST: Cause: " + e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ //
+ }
+ } finally {
+ em.close();
+ }
+
+ return resourceGroup;
+ }
+
+ private String readFile(File file) throws Exception {
+ return new String(StreamUtil.slurp(new FileInputStream(file)));
+ }
+
+ private void writeFile(File file, String content) throws Exception {
+ file.getParentFile().mkdirs();
+ StreamUtil.copy(new ByteArrayInputStream(content.getBytes()), new FileOutputStream(file));
+ }
+
+ private File createZip(File destDir, String zipName, String[] entryNames, String[] contents) 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);
+
+ assert contents.length == entryNames.length;
+ for (int i = 0; i < contents.length; i++) {
+ ZipEntry zipAdd = new ZipEntry(entryNames[i]);
+ zipAdd.setTime(System.currentTimeMillis());
+ out.putNextEntry(zipAdd);
+ out.write(contents[i].getBytes());
+ }
+ return zipFile;
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/TestBundleServerPluginService.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/TestBundleServerPluginService.java
new file mode 100644
index 0000000..61c53d3
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/TestBundleServerPluginService.java
@@ -0,0 +1,244 @@
+/*
+ * 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.enterprise.server.bundle;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.configuration.definition.PropertySimpleType;
+import org.rhq.core.domain.plugin.PluginKey;
+import org.rhq.core.domain.plugin.PluginStatusType;
+import org.rhq.core.domain.plugin.ServerPlugin;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.core.util.updater.DeploymentProperties;
+import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginManager;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
+import org.rhq.enterprise.server.plugin.pc.bundle.BundleServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.bundle.BundleServerPluginFacet;
+import org.rhq.enterprise.server.plugin.pc.bundle.BundleServerPluginManager;
+import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginManager;
+import org.rhq.enterprise.server.plugin.pc.content.PackageTypeServerPluginContainer;
+import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorMetadataParser;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
+
+/**
+ * Used as a mock service for the bundle server plugin container.
+ */
+public class TestBundleServerPluginService extends ServerPluginService implements TestBundleServerPluginServiceMBean {
+
+ // public so tests can directly set these
+ public TestMasterServerPluginContainer master;
+ public TestBundleServerPluginContainer bundlePC;
+ public MasterServerPluginContainerConfiguration masterConfig;
+
+ public RecipeParseResults parseRecipe_returnValue = null;
+ public BundleDistributionInfo processBundleDistributionFile_returnValue;
+
+ public TestBundleServerPluginService() {
+ // build the config at constructor time so tests have it even before the PC is initialized
+ File dir = new File(System.getProperty("java.io.tmpdir"), "test-server-plugins");
+ this.masterConfig = new MasterServerPluginContainerConfiguration(dir, dir, dir, null);
+ }
+
+ @Override
+ public MasterServerPluginContainer createMasterPluginContainer() {
+ this.master = new TestMasterServerPluginContainer();
+ this.master.initialize(this.masterConfig);
+ return this.master;
+ }
+
+ /**
+ * The test master PC
+ */
+ class TestMasterServerPluginContainer extends MasterServerPluginContainer {
+ @Override
+ protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
+ ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(1);
+ bundlePC = new TestBundleServerPluginContainer(this);
+ pcs.add(bundlePC);
+ pcs.add(new TestContentServerPluginContainer(this));
+
+ //needed internally by the server, so let's provide the standard impl.
+ pcs.add(new PackageTypeServerPluginContainer(this));
+ return pcs;
+ }
+
+ @Override
+ protected ClassLoader createRootServerPluginClassLoader() {
+ return this.getClass().getClassLoader();
+ }
+
+ @Override
+ protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
+ // if our test never setup any plugins, ignore it and just return an empty map
+ File pluginDir = getConfiguration().getPluginDirectory();
+ if (pluginDir == null || pluginDir.listFiles() == null || pluginDir.listFiles().length == 0) {
+ return new HashMap<URL, ServerPluginDescriptorType>();
+ } else {
+ return super.preloadAllPlugins();
+ }
+ }
+
+ @Override
+ protected List<PluginKey> getDisabledPluginKeys() {
+ // in the real world, the db is checked for enable flag, here we say all plugins are enabled
+ return new ArrayList<PluginKey>();
+ }
+ }
+
+ public class TestBundleServerPluginContainer extends BundleServerPluginContainer {
+ public TestBundleServerPluginContainer(MasterServerPluginContainer master) {
+ super(master);
+ }
+
+ @Override
+ protected ServerPluginManager createPluginManager() {
+ TestBundlePluginManager pm = new TestBundlePluginManager(this);
+ return pm;
+ }
+ }
+
+ public class TestContentServerPluginContainer extends ContentServerPluginContainer {
+ public TestContentServerPluginContainer(MasterServerPluginContainer master) {
+ super(master);
+ }
+
+ @Override
+ protected ServerPluginManager createPluginManager() {
+ ContentServerPluginManager pm = new ContentServerPluginManager(this);
+ return pm;
+ }
+ }
+
+ /**
+ * The test plugin manager.
+ */
+ class TestBundlePluginManager extends BundleServerPluginManager {
+ public final Map<String, ServerPluginComponent> components;
+
+ public TestBundlePluginManager(TestBundleServerPluginContainer pc) {
+ super(pc);
+ components = new HashMap<String, ServerPluginComponent>();
+ }
+
+ @Override
+ protected ServerPlugin getPlugin(ServerPluginEnvironment env) {
+
+ try {
+ Configuration pluginConfig = null;
+ Configuration scheduledJobsConfig = null;
+ ConfigurationDefinition configDef;
+
+ ServerPluginDescriptorType pluginDescriptor = env.getPluginDescriptor();
+
+ configDef = ServerPluginDescriptorMetadataParser.getPluginConfigurationDefinition(pluginDescriptor);
+ if (configDef != null) {
+ pluginConfig = configDef.getDefaultTemplate().createConfiguration();
+ }
+
+ configDef = ServerPluginDescriptorMetadataParser.getScheduledJobsDefinition(pluginDescriptor);
+ if (configDef != null) {
+ scheduledJobsConfig = configDef.getDefaultTemplate().createConfiguration();
+ }
+
+ File pluginFile = new File(env.getPluginUrl().toURI());
+ ServerPlugin plugin = new ServerPlugin(0, env.getPluginKey().getPluginName(), pluginFile.getName(),
+ pluginDescriptor.getDisplayName(), true, PluginStatusType.INSTALLED, pluginDescriptor
+ .getDescription(), "", MessageDigestGenerator.getDigestString(pluginFile), pluginDescriptor
+ .getVersion(), pluginDescriptor.getVersion(), pluginConfig, scheduledJobsConfig,
+ new ServerPluginType(pluginDescriptor).stringify(), System.currentTimeMillis(), System
+ .currentTimeMillis());
+ return plugin;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected ServerPluginComponent createServerPluginComponent(ServerPluginEnvironment environment)
+ throws Exception {
+ ServerPluginComponent component = super.createServerPluginComponent(environment);
+ components.put(environment.getPluginKey().getPluginName(), component);
+ return component;
+ }
+
+ @Override
+ public RecipeParseResults parseRecipe(String bundleTypeName, String recipe) throws Exception {
+ return new TestBundlePluginComponent().parseRecipe(recipe);
+ }
+
+ @Override
+ public BundleDistributionInfo processBundleDistributionFile(File distributionFile) throws Exception {
+ return new TestBundlePluginComponent().processBundleDistributionFile(distributionFile);
+ }
+ }
+
+ class TestBundlePluginComponent implements BundleServerPluginFacet {
+
+ public TestBundlePluginComponent() {
+ };
+
+ public RecipeParseResults parseRecipe(String recipe) throws Exception {
+
+ if (parseRecipe_returnValue != null) {
+ return parseRecipe_returnValue;
+ }
+
+ ConfigurationDefinition configDef;
+ Set<String> bundleFileNames;
+ DeploymentProperties metadata;
+
+ metadata = new DeploymentProperties(0, "bundletest", "1.0", "bundle test description");
+
+ configDef = new ConfigurationDefinition("bundletest-configdef", "Test Config Def for testing BundleVersion");
+ configDef.put(new PropertyDefinitionSimple("bundletest.property",
+ "Test property for BundleVersion Config Def testing", true, PropertySimpleType.STRING));
+
+ bundleFileNames = new HashSet<String>();
+ bundleFileNames.add("bundletest-bundlefile-1");
+ bundleFileNames.add("bundletest-bundlefile-2");
+
+ return new RecipeParseResults(metadata, configDef, bundleFileNames);
+ }
+
+ public BundleDistributionInfo processBundleDistributionFile(File uberBundleFile) throws Exception {
+ if (processBundleDistributionFile_returnValue != null) {
+ return processBundleDistributionFile_returnValue;
+ }
+
+ throw new UnsupportedOperationException("this mock object cannot do this");
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/TestBundleServerPluginServiceMBean.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/TestBundleServerPluginServiceMBean.java
new file mode 100644
index 0000000..9af2a47
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/TestBundleServerPluginServiceMBean.java
@@ -0,0 +1,24 @@
+/*
+ * 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.enterprise.server.bundle;
+
+import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceMBean;
+
+public interface TestBundleServerPluginServiceMBean extends ServerPluginServiceMBean {
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java
new file mode 100644
index 0000000..ac07e18
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java
@@ -0,0 +1,606 @@
+/*
+ * 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.enterprise.server.cloud;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+
+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.auth.Subject;
+import org.rhq.core.domain.cloud.AffinityGroup;
+import org.rhq.core.domain.cloud.PartitionEvent;
+import org.rhq.core.domain.cloud.PartitionEventType;
+import org.rhq.core.domain.cloud.Server;
+import org.rhq.core.domain.cloud.composite.FailoverListComposite;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.core.AgentManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Tests the configuration manager.
+ *
+ * NOTE: These tests only work if there are no servers registered in the db. The tests will clean up themselves for
+ * NOTE: multiple runs but will fail (typically the getForSingleAgent tests) if run against a db that has been
+ * NOTE: used against an active server.
+ */
+@Test
+public class FailoverListManagerBeanTest extends AbstractEJB3Test {
+
+ private static final boolean ENABLE_TESTS = true;
+
+ private FailoverListManagerLocal failoverListManager;
+ private AgentManagerLocal agentManager;
+ private PartitionEventManagerLocal partitionEventManager;
+ private CloudManagerLocal cloudManager;
+ private AffinityGroupManagerLocal affinityGroupManager;
+ private Subject overlord;
+
+ private List<Server> servers;
+ private List<Agent> agents;
+ private AffinityGroup ag;
+ private PartitionEvent partitionEvent;
+ private List<Agent> newAgents;
+
+ /**
+ * Prepares things for the entire test class.
+ */
+ @BeforeClass
+ public void beforeClass() {
+ agentManager = LookupUtil.getAgentManager();
+ failoverListManager = LookupUtil.getFailoverListManager();
+ partitionEventManager = LookupUtil.getPartitionEventManager();
+ cloudManager = LookupUtil.getCloudManager();
+ affinityGroupManager = LookupUtil.getAffinityGroupManager();
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ servers = new ArrayList<Server>();
+ agents = new ArrayList<Agent>();
+ newAgents = new ArrayList<Agent>();
+ }
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ servers.clear();
+ agents.clear();
+ newAgents.clear();
+
+ prepareForTestAgents();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ try {
+ getTransactionManager().begin();
+
+ partitionEventManager.deletePartitionEvents(overlord, new Integer[] { partitionEvent.getId() });
+
+ try {
+ for (Server server : servers) {
+ // must set to down to allow for a delete
+ cloudManager.updateServerMode(new Integer[] { server.getId() }, Server.OperationMode.DOWN);
+ cloudManager.deleteServer(server.getId());
+ }
+
+ for (Agent agent : agents) {
+ agentManager.deleteAgent(agent);
+ }
+
+ affinityGroupManager.delete(overlord, new Integer[] { ag.getId() });
+
+ if (null != newAgents) {
+ for (Agent agent : newAgents) {
+ agentManager.deleteAgent(agent);
+ }
+ }
+
+ // Delete any remaining partition events generated by the test and the test cleanup
+ PageList<PartitionEvent> events = partitionEventManager.getPartitionEvents(overlord, null, null, "flm",
+ PageControl.getUnlimitedInstance());
+ Integer[] eventIds = new Integer[events.size()];
+ for (int i = 0, size = events.size(); (i < size); ++i) {
+ eventIds[i] = events.get(i).getId();
+ }
+ partitionEventManager.deletePartitionEvents(overlord, eventIds);
+
+ } catch (Exception e) {
+ System.out.println(e);
+ throw e;
+ }
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ System.out.println(e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+
+ throw e;
+ } finally {
+ this.unprepareForTestAgents();
+ }
+ }
+
+ private void setupTest(int numServers, int numAgents) throws Exception {
+ Server server = new Server();
+ Agent agent;
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ for (int i = 0; (i < numServers); ++i) {
+ server = new Server();
+ server.setName("Server-flm-" + i);
+ server.setAddress("" + i);
+ server.setPort(i);
+ server.setSecurePort(i);
+ server.setOperationMode(Server.OperationMode.NORMAL);
+ em.persist(server);
+ servers.add(server);
+ }
+
+ for (int i = 0; (i < numAgents); ++i) {
+ agent = new Agent("Agent-flm-" + i, "" + i, 1, "endpoint", "token" + i);
+ em.persist(agent);
+ agents.add(agent);
+ }
+
+ ag = new AffinityGroup("AG-flm-1");
+ em.persist(ag);
+
+ partitionEvent = new PartitionEvent("FLM-TEST", PartitionEventType.SYSTEM_INITIATED_PARTITION,
+ "Test-flm-detail", PartitionEvent.ExecutionStatus.IMMEDIATE);
+ em.persist(partitionEvent);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ System.out.println(e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+
+ throw e;
+ } finally {
+ em.close();
+ }
+ }
+
+ private void setupNewAgents(int numNewAgents) throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ for (int i = 0; (i < numNewAgents); ++i) {
+
+ Agent agent = new Agent("Agent-flm-NEW" + i, "NEW-" + i, 1, "endpoint", "token-NEW-" + i);
+ em.persist(agent);
+ newAgents.add(agent);
+ }
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ System.out.println(e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+
+ throw e;
+ } finally {
+ em.close();
+ }
+ }
+
+ private boolean validateBalance(Map<Agent, FailoverListComposite> result, int numServers, int numAgents) {
+
+ validateBasic(result, numServers, numAgents);
+
+ // validate balance level by level
+ for (int level = 0; (level < numServers); ++level) {
+ Map<String, Integer> distributionMap = new HashMap<String, Integer>(numServers);
+ for (Agent agent : result.keySet()) {
+ FailoverListComposite flc = result.get(agent);
+ // for debugging
+ //if (i == 1) {
+ // System.out.println(agent + " : " + flc);
+ //}
+ FailoverListComposite.ServerEntry server = flc.get(level);
+ Integer count = distributionMap.get(server.address);
+ distributionMap.put(server.address, (null == count) ? 1 : ++count);
+ }
+ for (Integer agentsOnServer : distributionMap.values()) {
+ double div = (double) numAgents / (double) numServers;
+ int ceil = (int) Math.ceil(div);
+ int floor = (int) Math.floor(div);
+ // as we get deeper be more lenient. We haven't come up with any sort of genius algorithm, it's
+ // just ok, if it balances well for the primary and secondary that's good. Allow a skew of 1 for
+ // level 3-5 and a skew of 2 for levels past that
+ if (level > 2) {
+ ++ceil;
+ --floor;
+ }
+ if (level > 5) {
+ ++ceil;
+ --floor;
+ }
+ assert agentsOnServer <= ceil : "AgentsOnServer [" + agentsOnServer + "] > ceiling [" + ceil
+ + "] (level " + level + ")";
+ assert agentsOnServer >= floor : "AgentsOnServer [" + agentsOnServer + "] < floor [" + floor
+ + "] (level " + level + ")";
+ }
+ }
+
+ return true;
+ }
+
+ private void validateAffinity(Map<Agent, FailoverListComposite> result, int numServers, int numAgents,
+ int numAffinityServers, int numAffinityAgents) {
+
+ double div;
+
+ validateBasic(result, numServers, numAgents);
+
+ // validate level by level
+ for (int level = 0; (level < numServers); ++level) {
+ Map<Integer, Integer> distributionMap = new HashMap<Integer, Integer>(numServers);
+ for (Agent agent : result.keySet()) {
+ FailoverListComposite flc = result.get(agent);
+ FailoverListComposite.ServerEntry server = flc.get(level);
+ Integer agentId = Integer.valueOf(agent.getAddress());
+ Integer serverId = Integer.valueOf(server.address);
+ if ((level < numAffinityServers) && (agentId < numAffinityAgents))
+ assert (serverId < numAffinityServers) : "serverId [" + serverId + "] >= numAffinityServers ["
+ + numAffinityServers + "]";
+ Integer count = distributionMap.get(serverId);
+ distributionMap.put(serverId, (null == count) ? 1 : ++count);
+ }
+ for (Integer serverId : distributionMap.keySet()) {
+ Integer agentsOnServer = distributionMap.get(serverId);
+ if (level >= numAffinityServers) {
+ if (serverId < numAffinityServers) {
+ div = (numAgents - numAffinityAgents) / (double) numAffinityServers;
+ } else {
+ div = numAffinityAgents / (double) (numServers - numAffinityServers);
+ }
+ int ceil = (int) Math.ceil(div);
+ int floor = (int) Math.floor(div);
+ assert agentsOnServer <= ceil : "AgentsOnServer [" + agentsOnServer + "] > ceiling [" + ceil + "]";
+ assert agentsOnServer >= floor : "AgentsOnServer [" + agentsOnServer + "] < floor [" + floor + "]";
+ }
+ }
+ }
+ }
+
+ private void validateBasic(Map<Agent, FailoverListComposite> result, int numServers, int numAgents) {
+ // validate server list length
+ for (Agent agent : result.keySet()) {
+ assert result.get(agent).size() == numServers;
+ }
+
+ // validate no duplicates in server list
+ for (Agent agent : result.keySet()) {
+ Set<String> names = new HashSet<String>(numServers);
+ FailoverListComposite flc = result.get(agent);
+ for (int i = 0; (i < numServers); ++i) {
+ FailoverListComposite.ServerEntry server = flc.get(i);
+ assert names.add(server.address);
+ }
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents1_0() throws Exception {
+ setupTest(1, 0);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ assert validateBalance(result, 1, 0);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents1_1() throws Exception {
+ setupTest(1, 1);
+ long start = System.currentTimeMillis();
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ System.out.println("Elapsed 1/0 = " + (System.currentTimeMillis() - start) + "ms");
+ assert null != result;
+ assert validateBalance(result, 1, 1);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents1_2() throws Exception {
+ setupTest(1, 2);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ assert validateBalance(result, 1, 2);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents1_5() throws Exception {
+ setupTest(1, 5);
+ long start = System.currentTimeMillis();
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ System.out.println("Elapsed 1/5 = " + (System.currentTimeMillis() - start) + "ms");
+ assert null != result;
+ assert validateBalance(result, 1, 5);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents2_0() throws Exception {
+ setupTest(2, 0);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ assert validateBalance(result, 2, 0);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents2_1() throws Exception {
+ setupTest(2, 1);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ assert validateBalance(result, 2, 1);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents2_2() throws Exception {
+ setupTest(2, 2);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ assert validateBalance(result, 2, 2);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents2_3() throws Exception {
+ setupTest(2, 3);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ assert validateBalance(result, 2, 3);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents2_9() throws Exception {
+ setupTest(2, 9);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ assert validateBalance(result, 2, 9);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents2_10() throws Exception {
+ setupTest(2, 10);
+ long start = System.currentTimeMillis();
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ System.out.println("Elapsed 2/10 = " + (System.currentTimeMillis() - start) + "ms");
+ assert null != result;
+ assert validateBalance(result, 2, 10);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents2_15() throws Exception {
+ setupTest(2, 15);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ assert validateBalance(result, 2, 15);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents3_2() throws Exception {
+ setupTest(3, 2);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ assert validateBalance(result, 3, 2);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents3_3() throws Exception {
+ setupTest(3, 3);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ assert validateBalance(result, 3, 3);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents3_4() throws Exception {
+ setupTest(3, 4);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ assert validateBalance(result, 3, 4);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents5_10() throws Exception {
+ setupTest(5, 10);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ assert validateBalance(result, 5, 10);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents5_25() throws Exception {
+ setupTest(5, 25);
+ long start = System.currentTimeMillis();
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ System.out.println("Elapsed 2/10 = " + (System.currentTimeMillis() - start) + "ms");
+ assert null != result;
+ assert validateBalance(result, 5, 25);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents5_42() throws Exception {
+ setupTest(5, 42);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ assert validateBalance(result, 5, 42);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents20_1000() throws Exception {
+ setupTest(20, 1000);
+ long start = System.currentTimeMillis();
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ System.out.println("Elapsed 20/1000 = " + (System.currentTimeMillis() - start) + "ms");
+ assert null != result;
+ assert validateBalance(result, 20, 1000);
+
+ start = System.currentTimeMillis();
+ setupNewAgents(1);
+ failoverListManager.getForSingleAgent(partitionEvent, newAgents.get(0).getName());
+ System.out.println("Elapsed 1 NEW 20/1000 = " + (System.currentTimeMillis() - start) + "ms");
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents2_10_affinity_1_10() throws Exception {
+ setupTest(2, 10);
+ // set up affinity such that all agents go to a server-1
+ servers.get(0).setAffinityGroup(ag);
+ for (Agent agent : agents) {
+ agent.setAffinityGroup(ag);
+ }
+
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ validateAffinity(result, 2, 10, 1, 10);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents4_20_affinity_2_10() throws Exception {
+ setupTest(4, 20);
+ // set up affinity such that all agents go to a server-1
+ servers.get(0).setAffinityGroup(ag);
+ servers.get(1).setAffinityGroup(ag);
+ for (int i = 0; (i < 10); ++i) {
+ agents.get(i).setAffinityGroup(ag);
+ }
+
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ validateAffinity(result, 4, 20, 2, 10);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents3_20_affinity_2_10() throws Exception {
+ setupTest(3, 20);
+ // set up affinity such that all agents go to a server-1
+ servers.get(0).setAffinityGroup(ag);
+ servers.get(1).setAffinityGroup(ag);
+ for (int i = 0; (i < 10); ++i) {
+ agents.get(i).setAffinityGroup(ag);
+ }
+
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ validateAffinity(result, 3, 20, 2, 10);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForAllAgents3_20_preferred_20() throws Exception {
+ setupTest(3, 20);
+ for (int i = 0; (i < 10); ++i) {
+ agents.get(i).setServer(servers.get(0));
+ }
+ for (int i = 10; (i < 20); ++i) {
+ agents.get(i).setServer(servers.get(1));
+ }
+
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ validateBalance(result, 3, 20);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForSingleAgent_existing() throws Exception {
+ setupTest(2, 4);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+ for (Agent agent : result.keySet()) {
+ FailoverListComposite flc1 = result.get(agent);
+ FailoverListComposite flc2 = failoverListManager.getForSingleAgent(partitionEvent, agent.getName());
+ assert flc1.size() == flc2.size();
+ for (int i = 0, size = flc1.size(); (i < size); ++i) {
+ assert flc1.get(i).equals(flc2.get(i));
+ }
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForSingleAgent_new_1() throws Exception {
+ setupTest(2, 4);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+
+ setupNewAgents(3);
+ List<FailoverListComposite> serverLists = new ArrayList<FailoverListComposite>(3);
+ for (int i = 0; i < 3; ++i) {
+ serverLists.add(failoverListManager.getForSingleAgent(partitionEvent, newAgents.get(i).getName()));
+ assert null != serverLists.get(i);
+ assert serverLists.get(i).size() == servers.size();
+ }
+ assert !serverLists.get(0).equals(serverLists.get(1));
+ assert serverLists.get(0).equals(serverLists.get(2));
+ assert !serverLists.get(1).equals(serverLists.get(2));
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForSingleAgent_new_2() throws Exception {
+ setupTest(3, 6);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+
+ setupNewAgents(3);
+ List<FailoverListComposite> serverLists = new ArrayList<FailoverListComposite>(3);
+ for (int i = 0; i < 3; ++i) {
+ serverLists.add(failoverListManager.getForSingleAgent(partitionEvent, newAgents.get(i).getName()));
+ assert null != serverLists.get(i);
+ assert serverLists.get(i).size() == servers.size();
+ }
+ assert !serverLists.get(0).equals(serverLists.get(1));
+ assert !serverLists.get(0).equals(serverLists.get(2)) : serverLists.toString();
+ assert !serverLists.get(1).equals(serverLists.get(2));
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetForSingleAgent_new_3() throws Exception {
+ setupTest(1, 0);
+ Map<Agent, FailoverListComposite> result = failoverListManager.refresh(partitionEvent, servers, agents);
+ assert null != result;
+
+ setupNewAgents(3);
+ List<FailoverListComposite> serverLists = new ArrayList<FailoverListComposite>(3);
+ for (int i = 0; i < 3; ++i) {
+ serverLists.add(failoverListManager.getForSingleAgent(partitionEvent, newAgents.get(i).getName()));
+ assert null != serverLists.get(i);
+ assert serverLists.get(i).size() == servers.size();
+ }
+ assert serverLists.get(0).equals(serverLists.get(1));
+ assert serverLists.get(0).equals(serverLists.get(2));
+ assert serverLists.get(1).equals(serverLists.get(2));
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBeanTest.java
new file mode 100644
index 0000000..c666e34
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBeanTest.java
@@ -0,0 +1,1121 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.configuration;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
+
+import org.jetbrains.annotations.NotNull;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.agent.PluginContainerException;
+import org.rhq.core.clientapi.agent.configuration.ConfigurationAgentService;
+import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
+import org.rhq.core.clientapi.agent.discovery.DiscoveryAgentService;
+import org.rhq.core.clientapi.agent.discovery.InvalidPluginConfigurationClientException;
+import org.rhq.core.clientapi.server.configuration.ConfigurationUpdateResponse;
+import org.rhq.core.clientapi.server.discovery.InventoryReport;
+import org.rhq.core.communications.command.annotation.Asynchronous;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
+import org.rhq.core.domain.configuration.PluginConfigurationUpdate;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.configuration.ResourceConfigurationUpdate;
+import org.rhq.core.domain.configuration.group.GroupPluginConfigurationUpdate;
+import org.rhq.core.domain.criteria.ResourceConfigurationUpdateCriteria;
+import org.rhq.core.domain.discovery.AvailabilityReport;
+import org.rhq.core.domain.discovery.MergeResourceResponse;
+import org.rhq.core.domain.discovery.ResourceSyncInfo;
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageOrdering;
+import org.rhq.core.util.exception.ThrowableUtil;
+import org.rhq.enterprise.server.authz.PermissionException;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.SessionTestHelper;
+
+/**
+ * Tests the configuration manager.
+ */
+@Test
+@SuppressWarnings("all")
+public class ConfigurationManagerBeanTest extends AbstractEJB3Test {
+ private static final boolean ENABLE_TESTS = true;
+
+ private ConfigurationManagerLocal configurationManager;
+ private ResourceManagerLocal resourceManager;
+ private Resource newResource1;
+ private Resource newResource2;
+ private ResourceGroup compatibleGroup;
+ private PageControl configUpdatesPageControl;
+ private Agent agent;
+ private Subject overlord;
+
+ /**
+ * Prepares things for the entire test class.
+ */
+ @BeforeClass
+ public void beforeClass() {
+ // Make sure page control sorts so the latest config update is last (the default is for the latest to be first).
+ configUpdatesPageControl = PageControl.getUnlimitedInstance();
+ // (ips, 04/01/10): Use createdTime, rather than id, to order by, since the id's are not guaranteed to be
+ // ordered sequentially (this is because, dbsetup configures our sequences to pre-create
+ // and cache sequence values 10 at a time.
+ configUpdatesPageControl.addDefaultOrderingField("cu.createdTime", PageOrdering.ASC);
+
+ configurationManager = LookupUtil.getConfigurationManager();
+ resourceManager = LookupUtil.getResourceManager();
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+ }
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ prepareScheduler();
+
+ TestServerCommunicationsService agentServiceContainer = prepareForTestAgents();
+ TestServices testServices = new TestServices();
+ agentServiceContainer.configurationService = testServices;
+ agentServiceContainer.discoveryService = testServices;
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ compatibleGroup = SessionTestHelper.createNewCompatibleGroupForRole(em, null, // no role necessary here
+ "compat");
+
+ newResource1 = SessionTestHelper.createNewResourceForGroup(em, compatibleGroup,
+ "res" + System.currentTimeMillis());
+ newResource2 = SessionTestHelper.createNewResourceForGroup(em, compatibleGroup,
+ "res" + System.currentTimeMillis());
+
+ // set one resource as the child of another, so that they don't both look like platforms under the agent
+ newResource1.addChildResource(newResource2);
+
+ agent = SessionTestHelper.createNewAgent(em, "agent-" + getClass().getSimpleName());
+ newResource1.setAgent(agent);
+ newResource2.setAgent(agent);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ System.out.println(e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+
+ throw e;
+ } finally {
+ em.close();
+ }
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ try {
+ // perform in-band and out-of-band work in quick succession
+ // only need to delete newResource1, which will delete his child newResource2 as well as the agent
+ List<Integer> deletedIds = resourceManager.uninventoryResource(overlord, newResource1.getId());
+ for (Integer deletedResourceId : deletedIds) {
+ resourceManager.uninventoryResourceAsyncWork(overlord, deletedResourceId);
+ }
+ } catch (Exception e) {
+ System.out.println(e);
+ throw e;
+ }
+
+ try {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ ResourceGroup group = em.find(ResourceGroup.class, compatibleGroup.getId());
+ em.remove(group);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ System.out.println(e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+
+ throw e;
+ } finally {
+ em.close();
+ }
+
+ getTransactionManager().begin();
+ em = getEntityManager();
+ try {
+ ResourceType type = em.find(ResourceType.class, newResource1.getResourceType().getId());
+
+ em.remove(type);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ System.out.println(e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+
+ throw e;
+ } finally {
+ em.close();
+ }
+
+ } finally {
+ unprepareScheduler();
+ unprepareForTestAgents();
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testLatestConfiguration() throws Exception {
+ int resourceId = newResource1.getId();
+
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ // create a config, then another that spends some time in INPROGRESS before succeeding
+ Configuration configuration1 = new Configuration();
+ configuration1.put(new PropertySimple("myboolean", "true"));
+
+ Configuration configuration2 = new Configuration();
+ configuration2.put(new PropertySimple("myboolean", "false"));
+ configuration2.put(new PropertySimple("mysleep", "7000"));
+
+ configurationManager.updateResourceConfiguration(overlord, resourceId, configuration1);
+ Thread.sleep(2000); // wait for the test agent to complete the request
+
+ ResourceConfigurationUpdate history1;
+ history1 = configurationManager.getLatestResourceConfigurationUpdate(overlord, resourceId);
+ assert history1 != null;
+ PropertySimple myprop = history1.getConfiguration().getSimple("myboolean");
+ assert myprop != null;
+ assert "true".equals(myprop.getStringValue());
+
+ // now update to that second config - the "agent" will sleep for a bit before it completes
+ // so we will have an INPROGRESS configuration for a few seconds before it goes to SUCCESS
+ ResourceConfigurationUpdate history2 = null;
+ boolean inProgress = false;
+ boolean inProgressTested = false;
+
+ configurationManager.updateResourceConfiguration(overlord, resourceId, configuration2);
+
+ do {
+ history2 = configurationManager.getLatestResourceConfigurationUpdate(overlord, resourceId);
+ inProgress = configurationManager.isResourceConfigurationUpdateInProgress(overlord, resourceId);
+
+ if (inProgress) {
+ // history2 should be history1 since the update is not complete
+ assert history2 != null;
+ assert history2.getId() == history1.getId();
+ myprop = history2.getConfiguration().getSimple("myboolean");
+ assert myprop != null;
+ assert "true".equals(myprop.getStringValue());
+ myprop = history2.getConfiguration().getSimple("mysleep"); // this wasn't in the first config
+ assert myprop == null;
+ // record that this test case ran, we expect it will if the agent delay is there
+ inProgressTested = true;
+ } else {
+ // update is complete, history 2 should be different
+ history2 = configurationManager.getLatestResourceConfigurationUpdate(overlord, resourceId);
+ assert history2 != null;
+ assert history2.getId() != history1.getId();
+ myprop = history2.getConfiguration().getSimple("myboolean");
+ assert myprop != null;
+ assert "false".equals(myprop.getStringValue());
+ myprop = history2.getConfiguration().getSimple("mysleep");
+ assert myprop.getLongValue() != null;
+ assert myprop.getLongValue().longValue() == 7000L;
+ }
+ } while (inProgress);
+
+ assertTrue(inProgressTested);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testDeleteType() throws Exception {
+ // the purpose of this little test is to test an error condition I'm getting when attempting to delete
+ // a resource type - just forces a run with before/afterMethod
+ return;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testPluginConfigurationUpdateCallbackSuccess() throws Exception {
+ Resource resource = newResource1;
+
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ Configuration configuration1 = new Configuration();
+ configuration1.put(new PropertySimple("foo", "1"));
+
+ Configuration configuration2 = new Configuration();
+ configuration2.put(new PropertySimple("bar", "2"));
+
+ Configuration current;
+
+ current = configurationManager.getPluginConfiguration(overlord, resource.getId());
+ assert current != null;
+ assert current.getProperties().size() == 0 : current; // there is no plugin config settings yet
+
+ configurationManager.updatePluginConfiguration(overlord, resource.getId(), configuration1);
+ current = configurationManager.getPluginConfiguration(overlord, resource.getId());
+ assert current != null;
+ assert current.getProperties().size() == 1 : current;
+ assert current.getSimple("foo").getIntegerValue() == 1 : current;
+
+ configurationManager.updatePluginConfiguration(overlord, resource.getId(), configuration2);
+ current = configurationManager.getPluginConfiguration(overlord, resource.getId());
+ assert current != null;
+ assert current.getProperties().size() == 1 : current;
+ assert current.getSimple("bar").getIntegerValue() == 2 : current;
+ assert current.getSimple("foo") == null : current; // this is gone now, we overrode it
+
+ assert current.remove("foo") == null : current; // secondary test - just exercise the remove method
+ assert current.remove("bar") != null : current; // again just test the remove method
+ current.put(new PropertySimple("hello", "3"));
+ configurationManager.updatePluginConfiguration(overlord, resource.getId(), current);
+ current = configurationManager.getPluginConfiguration(overlord, resource.getId());
+ assert current != null;
+ assert current.getProperties().size() == 1 : current;
+ assert current.getSimple("hello").getIntegerValue() == 3 : current;
+ assert current.getSimple("foo") == null : current; // this is gone now
+ assert current.getSimple("bar") == null : current; // this is gone now
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testPluginConfigurationUpdateCallbackFailure() throws Exception {
+ Resource resource = newResource1;
+
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ Configuration configuration1 = new Configuration();
+ configuration1.put(new PropertySimple("foo", "1"));
+ configuration1.put(new PropertySimple("fail", "true"));
+
+ Configuration current;
+
+ current = configurationManager.getPluginConfiguration(overlord, resource.getId());
+ assert current != null;
+ assert current.getProperties().size() == 0 : current; // there is no plugin config settings yet
+
+ PluginConfigurationUpdate update = configurationManager.updatePluginConfiguration(overlord, resource.getId(),
+ configuration1);
+ assert update.getErrorMessage() != null : "We should have simulated a failure, "
+ + "but instead received no error.";
+
+ // Even if a plugin container exception occurs, the plugin configuration should still be updated.
+ current = configurationManager.getPluginConfiguration(overlord, resource.getId());
+ assert current != null;
+ assert current.getProperties().size() != 0 : current.toString();
+ }
+
+ @Test(enabled = false)
+ public void testGroupPluginConfigurationUpdateWorkflowSuccess() throws Exception {
+ // TODO (joseph): Fix and then re-enable this test.
+ //testGroupPluginConfigurationUpdateWorkflowHelper(false);
+ }
+
+ @Test(enabled = false)
+ public void testGroupPluginConfigurationUpdateWorkflowFailure() throws Exception {
+ // TODO (joseph): Fix and then re-enable this test.
+ //testGroupPluginConfigurationUpdateWorkflowHelper(true);
+ }
+
+ @Test(enabled = false)
+ public void testGroupPluginConfigurationUpdateMergeAlgorithmPerformance() throws Exception {
+ Configuration configuration = new Configuration();
+ configuration.put(new PropertySimple("foo1", "1"));
+ configuration.put(new PropertySimple("foo2", "2"));
+ configuration.put(new PropertySimple("foo3", "3"));
+ configuration.put(new PropertySimple("foo4", "4"));
+ configuration.put(new PropertySimple("foo5", "5"));
+
+ /*
+ * for a configuration object that has 5 simple properties, baseline for groupSize of 100K was 165ms (Dec 6,
+ * 2007);
+ *
+ * that means it took 0.000165ms per merge into the group configuration;
+ */
+ final int TEST_SIZE = 100000;
+ final double BASELINE = 0.00165;
+ final double TOLERANCE = 3.0; // a number, representing percentage
+ final long EXPECTED = (long) (BASELINE * TEST_SIZE * (1 + TOLERANCE));
+
+ List<Configuration> timingSet = new ArrayList<Configuration>();
+ for (int i = 0; i < TEST_SIZE; i++) {
+ timingSet.add(configuration);
+ }
+
+ /*
+ * getGroupConfiguration is the most expensive part of the algorithm that helps to render a ResourceGroup's
+ * inventory tab
+ *
+ * so let's run timings on uber groups to make sure it's speedy
+ */
+ long before = System.currentTimeMillis();
+ //GroupPluginConfigurationUpdate.getGroupConfiguration(timingSet);
+ long after = System.currentTimeMillis();
+
+ long millisTaken = after - before;
+
+ if (millisTaken < EXPECTED) {
+ if ((millisTaken + 5000) < EXPECTED) {
+ assert false : "Merging GroupPluginConfigurationUpdates is too slow: " + "It took " + millisTaken
+ + " millis for " + TEST_SIZE + " resources; " + "We wanted less than " + EXPECTED + "ms";
+ } else {
+ System.out.println("Merging GroupPluginConfigurationUpdates is a bit slow: " + "It took " + millisTaken
+ + " millis for " + TEST_SIZE + " resources; " + "We wanted less than " + EXPECTED + "ms");
+ }
+ }
+ }
+
+ private void testGroupPluginConfigurationUpdateWorkflowHelper(boolean failOnChildUpdates) throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ Resource resource1 = newResource1;
+ Resource resource2 = newResource2;
+
+ try {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ Configuration configuration1 = new Configuration();
+ configuration1.put(new PropertySimple("foo", "1"));
+ configuration1.put(new PropertySimple("fail", "false"));
+
+ Configuration configuration2 = new Configuration();
+ configuration2.put(new PropertySimple("foo", "2"));
+ configuration2.put(new PropertySimple("fail", "false"));
+
+ /* begin simple checks */
+ PluginConfigurationUpdate update1 = configurationManager.updatePluginConfiguration(overlord,
+ resource1.getId(), configuration1);
+ assert update1.getErrorMessage() == null : "We weren't expecting a failure here";
+
+ PluginConfigurationUpdate update2 = configurationManager.updatePluginConfiguration(overlord,
+ resource2.getId(), configuration2);
+ assert update2.getErrorMessage() == null : "We weren't expecting a failure here";
+
+ Configuration updatedConfiguration1 = configurationManager.getPluginConfiguration(overlord,
+ resource1.getId());
+ Configuration updatedConfiguration2 = configurationManager.getPluginConfiguration(overlord,
+ resource2.getId());
+
+ assert updatedConfiguration1.equals(configuration1) : "configuration1 was: " + updatedConfiguration1 + ", "
+ + "expected was: " + configuration1;
+
+ assert updatedConfiguration2.equals(configuration2) : "configuration2 was: " + updatedConfiguration2 + ", "
+ + "expected was: " + configuration2;
+ /* end simple checks */
+
+ /* begin group configuration creation checks */
+ Configuration expectedGroupConfiguration = new Configuration();
+ expectedGroupConfiguration
+ .put(new PropertySimple("foo", GroupPluginConfigurationUpdate.MIXED_VALUES_MARKER));
+ expectedGroupConfiguration.put(new PropertySimple("fail", "false"));
+
+ List<Configuration> updatedConfigurations = Arrays.asList(new Configuration[] { updatedConfiguration1,
+ updatedConfiguration2 });
+
+ Configuration groupConfiguration = null;
+ /*
+ Configuration groupConfiguration = GroupPluginConfigurationUpdate
+ .getGroupConfiguration(updatedConfigurations);
+ */
+
+ assert groupConfiguration.equals(expectedGroupConfiguration) : "group configuration was: "
+ + groupConfiguration + ", " + "expected was: " + expectedGroupConfiguration;
+ /* end group configuration creation checks */
+
+ /* begin group modification */
+ Configuration groupConfigurationOverride = new Configuration();
+ PropertySimple propertySimple1 = new PropertySimple("foo", "3");
+ PropertySimple propertySimple2 = new PropertySimple("fail", "true");
+ groupConfigurationOverride.put(propertySimple1);
+ groupConfigurationOverride.put(propertySimple2);
+
+ // regardless of failures, semantics dictate that the new configuration should be persisted to the resource
+ Configuration expectedGroupConfigurationResults = new Configuration();
+ expectedGroupConfigurationResults.put(new PropertySimple("foo", "3")); // from groupConfigurationOverride
+ propertySimple1.setOverride(Boolean.TRUE);
+
+ if (failOnChildUpdates) {
+ expectedGroupConfigurationResults.put(new PropertySimple("fail", "true")); // from groupConfigurationOverride
+ propertySimple2.setOverride(Boolean.TRUE); // will make TestServices fail
+ } else {
+ expectedGroupConfigurationResults.put(new PropertySimple("fail", "false")); // from both resource's current configuration
+ propertySimple2.setOverride(Boolean.FALSE); // false is default, but setting explicitly for test clarity
+ }
+
+ Map<Integer, Configuration> memberConfigs = new HashMap<Integer, Configuration>();
+ memberConfigs.put(resource1.getId(), configuration1);
+ memberConfigs.put(resource2.getId(), configuration2);
+ int groupUpdateId = configurationManager.scheduleGroupPluginConfigurationUpdate(overlord,
+ compatibleGroup.getId(), memberConfigs);
+
+ // instead of sleeping, let's directly execute what would normally be scheduled
+ //configurationManager.completeGroupPluginConfigurationUpdate(groupUpdateId);
+
+ GroupPluginConfigurationUpdate update = configurationManager.getGroupPluginConfigurationById(groupUpdateId);
+
+ assert update != null : "Group plugin configuration update should not have been null";
+
+ int i = 0;
+ for (PluginConfigurationUpdate childUpdate : update.getConfigurationUpdates()) {
+ Configuration childUpdateConfiguration = childUpdate.getConfiguration();
+ assert childUpdateConfiguration.equals(expectedGroupConfigurationResults) : "new updateChildConfig["
+ + i + "] was: " + childUpdateConfiguration + ", " + "expected was: "
+ + expectedGroupConfigurationResults;
+ i++;
+ }
+
+ Configuration configurationAfterGroupUpdate1 = configurationManager.getPluginConfiguration(overlord,
+ resource1.getId());
+ Configuration configurationAfterGroupUpdate2 = configurationManager.getPluginConfiguration(overlord,
+ resource2.getId());
+
+ ConfigurationUpdateStatus expectedResultStatus = null;
+
+ if (failOnChildUpdates) {
+ expectedResultStatus = ConfigurationUpdateStatus.FAILURE;
+ } else {
+ expectedResultStatus = ConfigurationUpdateStatus.SUCCESS;
+ }
+
+ assert configurationAfterGroupUpdate1.equals(expectedGroupConfigurationResults) : "new config1 was: "
+ + configurationAfterGroupUpdate1 + ", " + "expected was: " + expectedGroupConfigurationResults;
+
+ assert configurationAfterGroupUpdate2.equals(expectedGroupConfigurationResults) : "new config2 was: "
+ + configurationAfterGroupUpdate2 + ", " + "expected was: " + expectedGroupConfigurationResults;
+
+ assert update.getStatus() == expectedResultStatus : "Group plugin configuration update "
+ + "should have been marked as " + expectedResultStatus + ": " + update;
+
+ /* end group modification */
+ } catch (Exception e) {
+ e.printStackTrace();
+ assert false : "Failed test with this exception: " + e;
+ } finally {
+ getTransactionManager().rollback();
+ try {
+ em.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testResourceConfigurationUpdateCallbackFailure() throws Exception {
+ Resource resource = newResource1;
+
+ try {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ // this is simulating what the UI would be doing, build the config and call the server-side API
+ // we'll pretend the user is the overlord - another test will check a real user to see permission errors
+ Configuration configuration = new Configuration();
+ configuration.put(new PropertySimple("myboolean", "invalid-bool"));
+
+ ResourceConfigurationUpdate history = new ResourceConfigurationUpdate(resource, configuration, "dummyuser");
+
+ assert history.getStatus().equals(ConfigurationUpdateStatus.INPROGRESS);
+
+ configurationManager.updateResourceConfiguration(overlord, resource.getId(), configuration);
+
+ Thread.sleep(2000); // wait for the test agent to complete the request
+
+ // our test service pretends the agent got an error - it will set some errors and the call to
+ // completedConfigurationUpdate is made inline (in the real code, this would be asynchronous)
+ // at this point in time, the round trip messaging is done and we have the agent response
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ resource = em.find(Resource.class, resource.getId());
+
+ history = resource.getResourceConfigurationUpdates().get(0);
+
+ assert history.getStatus().equals(ConfigurationUpdateStatus.FAILURE) : "Status was "
+ + history.getStatus();
+ assert history.getErrorMessage() != null;
+ assert history.getErrorMessage().indexOf("This simulates a failed update") > 0;
+ assert history.getConfiguration() != null;
+ PropertySimple mybool = history.getConfiguration().getSimple("myboolean");
+ assert mybool != null;
+ assert mybool.getStringValue().equals("invalid-bool");
+ assert mybool.getErrorMessage().indexOf("Not a valid boolean") > 0;
+ } finally {
+ getTransactionManager().rollback();
+ try {
+ em.close();
+ } catch (Exception e) {
+ }
+ }
+
+ assert configurationManager.getLatestResourceConfigurationUpdate(overlord, resource.getId()) != null : "Resource wasn't configured yet - but we should have populated it with live values";
+
+ // purging a non-existing request is a no-op
+ configurationManager.purgeResourceConfigurationUpdate(overlord, Integer.MIN_VALUE, false);
+
+ // delete the request now
+ configurationManager.purgeResourceConfigurationUpdate(overlord, history.getId(), false);
+
+ getTransactionManager().begin();
+ em = getEntityManager();
+ try {
+ resource = em.find(Resource.class, resource.getId());
+ assert resource.getResourceConfigurationUpdates().size() == 1; // the initial built for us for free with the live config
+ } finally {
+ getTransactionManager().rollback();
+ try {
+ em.close();
+ } catch (Exception e) {
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ assert false : "Failed test with this exception: " + e;
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testResourceConfigurationUpdateCallbackSuccess() throws Exception {
+ Resource resource = newResource1;
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ // this is simulating what the UI would be doing, build the config and call the server-side API
+ // we'll pretend the user is the overlord - another test will check a real user to see permission errors
+ Configuration configuration = new Configuration();
+ configuration.put(new PropertySimple("myboolean", "true"));
+
+ ResourceConfigurationUpdate request = new ResourceConfigurationUpdate(resource, configuration, "dummyuser");
+
+ assert request.getStatus().equals(ConfigurationUpdateStatus.INPROGRESS);
+
+ configurationManager.updateResourceConfiguration(overlord, resource.getId(), configuration);
+
+ Thread.sleep(2000); // wait for the test agent to complete the request
+
+ // at this point in time, the round trip messaging is done and we have the agent response
+ ResourceConfigurationUpdateCriteria criteria = new ResourceConfigurationUpdateCriteria();
+ criteria.addFilterResourceIds(resource.getId());
+ criteria.fetchConfiguration(true);
+ criteria.addSortCreatedTime(PageOrdering.ASC);
+
+ List<ResourceConfigurationUpdate> requests;
+
+ requests = configurationManager.findResourceConfigurationUpdatesByCriteria(overlord, criteria);
+
+ assert requests.size() == 1;
+ assert requests.get(0) != null;
+
+ request = requests.get(0);
+
+ assert request.getStatus().equals(ConfigurationUpdateStatus.SUCCESS);
+ assert request.getErrorMessage() == null;
+ assert request.getConfiguration() != null;
+ PropertySimple mybool = request.getConfiguration().getSimple("myboolean");
+ assert mybool != null;
+ assert mybool.getStringValue().equals("true");
+ assert mybool.getErrorMessage() == null;
+
+ ResourceConfigurationUpdate current;
+ current = configurationManager.getLatestResourceConfigurationUpdate(overlord, resource.getId());
+
+ assert current != null;
+ assert current.getId() == request.getId();
+ assert current.getResource().equals(resource);
+ assert current.getStatus().equals(request.getStatus());
+ assert current.getSubjectName().equals(request.getSubjectName());
+ assert current.getCreatedTime() == request.getCreatedTime();
+ assert current.getModifiedTime() == request.getModifiedTime();
+ assert current.getConfiguration().getId() == request.getConfiguration().getId();
+
+ Configuration live = configurationManager.getLiveResourceConfiguration(overlord, resource.getId(), false);
+ assert live != null;
+ mybool = live.getSimple("myboolean");
+ assert mybool != null;
+ assert "true".equals(mybool.getStringValue());
+ assert mybool.getErrorMessage() == null;
+
+ // purging a non-existing request is a no-op
+ configurationManager.purgeResourceConfigurationUpdate(overlord, Integer.MIN_VALUE, false);
+
+ // delete the request now
+ System.out.println("REQUEST WAS: " + request.toString());
+ configurationManager.purgeResourceConfigurationUpdate(overlord, request.getId(), false);
+
+ requests = configurationManager.findResourceConfigurationUpdates(overlord, resource.getId(), null, null, false,
+ configUpdatesPageControl);
+
+ assert requests.size() == 1; // it will create one for us from the "live" configuration
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testConfigurationRollback() throws Exception {
+ Resource resource = newResource1;
+
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ // create a few configs in history
+ Configuration configuration1 = new Configuration();
+ configuration1.put(new PropertySimple("myboolean", "true"));
+ configurationManager.updateResourceConfiguration(overlord, resource.getId(), configuration1);
+ Thread.sleep(3000); // wait for the test agent to complete the request
+
+ Configuration configuration2 = new Configuration();
+ configuration2.put(new PropertySimple("myboolean", "false"));
+ configurationManager.updateResourceConfiguration(overlord, resource.getId(), configuration2);
+ Thread.sleep(3000); // wait for the test agent to complete the request
+
+ Configuration configuration3 = new Configuration();
+ configuration3.put(new PropertySimple("myboolean", "TRUE"));
+ configurationManager.updateResourceConfiguration(overlord, resource.getId(), configuration3);
+ Thread.sleep(3000); // wait for the test agent to complete the request
+
+ ResourceConfigurationUpdateCriteria criteria = new ResourceConfigurationUpdateCriteria();
+ criteria.addFilterResourceIds(resource.getId());
+ criteria.fetchConfiguration(true);
+ criteria.addSortCreatedTime(PageOrdering.ASC);
+ List<ResourceConfigurationUpdate> history = configurationManager.findResourceConfigurationUpdatesByCriteria(
+ overlord, criteria);
+ assert history != null;
+ assert history.size() == 3;
+
+ Configuration currentConfiguration = history.get(2).getConfiguration();
+ PropertySimple mybool = currentConfiguration.getSimple("myboolean");
+ assert mybool != null;
+ assertEquals("TRUE", mybool.getStringValue());
+
+ // now grab one of the earlier configurations and rollback to it
+ Configuration rollbackToHere = history.get(1).getConfiguration(); // the "false" one
+ mybool = rollbackToHere.getSimple("myboolean");
+ assert mybool != null;
+ assertEquals("false", mybool.getStringValue());
+
+ configurationManager.updateResourceConfiguration(overlord, resource.getId(), rollbackToHere);
+ Thread.sleep(3000); // wait for the test agent to complete the request
+
+ criteria = new ResourceConfigurationUpdateCriteria();
+ criteria.addFilterResourceIds(resource.getId());
+ criteria.fetchConfiguration(true);
+ criteria.addSortCreatedTime(PageOrdering.ASC);
+
+ history = configurationManager.findResourceConfigurationUpdatesByCriteria(overlord, criteria);
+ assert history != null;
+ assert history.size() == 4;
+ ResourceConfigurationUpdate newConfigUpdate = history.get(3); // the last one is the new one
+ Configuration newConfiguration = newConfigUpdate.getConfiguration();
+ assert newConfiguration.getId() != rollbackToHere.getId();
+ mybool = newConfiguration.getSimple("myboolean");
+ assert mybool != null;
+ assertEquals("false", mybool.getStringValue());
+ assert mybool.getErrorMessage() == null;
+
+ ResourceConfigurationUpdate current = configurationManager.getLatestResourceConfigurationUpdate(overlord,
+ resource.getId());
+ assert current != null;
+ assert current.getId() == newConfigUpdate.getId();
+ assert current.getResource().equals(resource);
+ assert current.getStatus().equals(newConfigUpdate.getStatus());
+ assert current.getSubjectName().equals(newConfigUpdate.getSubjectName());
+ assert current.getCreatedTime() == newConfigUpdate.getCreatedTime();
+ assert current.getModifiedTime() == newConfigUpdate.getModifiedTime();
+ assert current.getConfiguration().getId() == newConfigUpdate.getConfiguration().getId();
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testPurgeConfigurationHistorySame() throws Exception {
+ Resource resource = newResource1;
+
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ // create a couple configs in history
+ Configuration configuration1 = new Configuration();
+ configuration1.put(new PropertySimple("myboolean", "true"));
+
+ Configuration configuration2 = new Configuration();
+ configuration2.put(new PropertySimple("myboolean", "true"));
+
+ configurationManager.updateResourceConfiguration(overlord, resource.getId(), configuration1);
+ Thread.sleep(6000); // wait for the test agent to complete the request
+ configurationManager.updateResourceConfiguration(overlord, resource.getId(), configuration2);
+ Thread.sleep(6000); // wait for the test agent to complete the request
+
+ // at this point in time, the round trip messaging is done and we have the agent response
+ List<ResourceConfigurationUpdate> requests;
+
+ requests = configurationManager.findResourceConfigurationUpdates(overlord, resource.getId(), null, null, false,
+ configUpdatesPageControl);
+
+ assert requests != null;
+ assert requests.size() == 1 : "Got " + requests.size() + " config update requests - expected 1.";
+ }
+
+ @Test(enabled = true)
+ public void testPurgeConfigurationHistoryDifferent() throws Exception {
+ Resource resource = newResource1;
+
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ // create a couple configs in history
+ Configuration configuration1 = new Configuration();
+ configuration1.put(new PropertySimple("myboolean", "true"));
+
+ Configuration configuration2 = new Configuration();
+ configuration2.put(new PropertySimple("myboolean", "false"));
+
+ ResourceConfigurationUpdate up;
+ up = configurationManager.updateResourceConfiguration(overlord, resource.getId(), configuration1);
+ Thread.sleep(2000); // wait for the test agent to complete the request
+ assert configuration1.equals(configurationManager.getResourceConfiguration(resource.getId()));
+ up = configurationManager.updateResourceConfiguration(overlord, resource.getId(), configuration2);
+ Thread.sleep(2000); // wait for the test agent to complete the request
+ assert configuration2.equals(configurationManager.getResourceConfiguration(resource.getId()));
+
+ // at this point in time, the round trip messaging is done and we have the agent response
+ List<ResourceConfigurationUpdate> requests;
+
+ requests = configurationManager.findResourceConfigurationUpdates(overlord, resource.getId(), null, null, false,
+ configUpdatesPageControl);
+
+ assert requests != null;
+ assert requests.size() == 2 : "Got " + requests.size() + " config update requests - expected 2.";
+
+ // delete the first one
+ ResourceConfigurationUpdate doomedRequest = requests.get(0);
+ ResourceConfigurationUpdate savedRequest = requests.get(1);
+
+ configurationManager.purgeResourceConfigurationUpdates(overlord, new int[] { doomedRequest.getId() }, false);
+
+ // now get the current configs/requests and
+ // make sure we deleted just the one configuration, leaving one left
+ requests = configurationManager.findResourceConfigurationUpdates(overlord, resource.getId(), null, null, false,
+ configUpdatesPageControl);
+
+ assert requests.size() == 1;
+ assert requests.get(0).getId() == savedRequest.getId();
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testPurgeConfigurationHistoryWithFailedUpdateRequest() throws Exception {
+ Resource resource = newResource1;
+
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ // create a couple update/requests in history - one request will fail, so only a single config in history will be there
+ Configuration configuration1 = new Configuration();
+ configuration1.put(new PropertySimple("myboolean", "invalid-boolean"));
+
+ Configuration configuration2 = new Configuration();
+ configuration2.put(new PropertySimple("myboolean", "true"));
+
+ Configuration activeConfigurationBefore = configurationManager.getResourceConfiguration(resource.getId());
+
+ configurationManager.updateResourceConfiguration(overlord, resource.getId(), configuration1);
+ Thread.sleep(2000); // wait for the test agent to complete the request
+
+ Configuration activeConfigurationAfter = configurationManager.getResourceConfiguration(resource.getId());
+ assert activeConfigurationBefore.equals(activeConfigurationAfter) : "ActiveResourceConfiguration was not supposed to change for a failed update -- old was: "
+ + activeConfigurationBefore + ", new was: " + activeConfigurationAfter;
+
+ configurationManager.updateResourceConfiguration(overlord, resource.getId(), configuration2);
+ Thread.sleep(2000); // wait for the test agent to complete the request
+
+ Configuration activeConfiguration = configurationManager.getResourceConfiguration(resource.getId());
+ assert activeConfiguration != null : "ActiveResourceConfiguration was not updated with configuration2";
+ Map<String, PropertySimple> activeProperties = activeConfiguration.getSimpleProperties();
+ assert activeProperties.size() == 1;
+ assert activeProperties.containsKey("myboolean");
+ PropertySimple activeProperty = activeProperties.get("myboolean");
+ assert activeProperty.getName().equals("myboolean");
+ assert "true".equals(activeProperty.getStringValue());
+
+ // at this point in time, the round trip messaging is done and we have the agent response
+ List<ResourceConfigurationUpdate> requests;
+
+ requests = configurationManager.findResourceConfigurationUpdates(overlord, resource.getId(), null, null, false,
+ configUpdatesPageControl);
+
+ assert requests != null;
+ assert requests.size() == 2; // one succeeded and one failed
+
+ assert requests.get(0).getStatus() == ConfigurationUpdateStatus.FAILURE : "actual: "
+ + requests.get(0).getStatus();
+ assert requests.get(1).getStatus() == ConfigurationUpdateStatus.SUCCESS : "actual: "
+ + requests.get(1).getStatus();
+
+ ResourceConfigurationUpdate savedRequest = requests.get(0); // this is the one that failed
+ ResourceConfigurationUpdate doomedRequest = requests.get(1); // this is the one that succeeded
+
+ configurationManager.purgeResourceConfigurationUpdate(overlord, doomedRequest.getId(), false);
+
+ // now get the current configs/requests and
+ // make sure we deleted the only one configuration that succeeded, leaving one update record
+ ResourceConfigurationUpdateCriteria criteria = new ResourceConfigurationUpdateCriteria();
+ criteria.addFilterResourceIds(resource.getId());
+ criteria.fetchConfiguration(true);
+ criteria.addSortCreatedTime(PageOrdering.ASC);
+
+ requests = configurationManager.findResourceConfigurationUpdatesByCriteria(overlord, criteria);
+
+ assert requests.size() == 1;
+
+ ResourceConfigurationUpdate request = requests.get(0);
+ assert request.getId() == savedRequest.getId();
+ assert request.getStatus().equals(ConfigurationUpdateStatus.FAILURE);
+ assert request.getErrorMessage() != null;
+ assert request.getErrorMessage().indexOf("This simulates a failed update") > 0;
+ assert request.getConfiguration() != null;
+ PropertySimple mybool = request.getConfiguration().getSimple("myboolean");
+ assert mybool != null;
+ assert mybool.getStringValue().equals("invalid-boolean");
+ assert mybool.getErrorMessage().indexOf("Not a valid boolean") > 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testNoPermissionCallback() throws Exception {
+ Subject superuser = LookupUtil.getSubjectManager().getOverlord();
+ Subject noPermSubject = new Subject("userWithNoPermissions", true, false);
+ Resource resource = newResource1;
+
+ try {
+ noPermSubject = LookupUtil.getSubjectManager().createSubject(superuser, noPermSubject);
+ noPermSubject = createSession(noPermSubject);
+
+ try {
+ configurationManager.updateResourceConfiguration(noPermSubject, resource.getId(), new Configuration());
+ assert false : "Should not have been updated - user didn't have permissions";
+ } catch (PermissionException expected) {
+ System.out.println("This was expected and OK:\n" + expected);
+ }
+
+ try {
+ configurationManager.updatePluginConfiguration(noPermSubject, resource.getId(), new Configuration());
+ assert false : "Should not have been updated - user didn't have permissions";
+ } catch (PermissionException expected) {
+ System.out.println("This was expected and OK:\n" + expected);
+ expected.printStackTrace();
+ }
+ } finally {
+ LookupUtil.getSubjectManager().deleteUsers(LookupUtil.getSubjectManager().getOverlord(),
+ new int[] { noPermSubject.getId() });
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testInvalidUpdateCallback() throws Exception {
+ ConfigurationUpdateResponse response = new ConfigurationUpdateResponse(Integer.MAX_VALUE, new Configuration(),
+ ConfigurationUpdateStatus.SUCCESS, null);
+
+ try {
+ configurationManager.completeResourceConfigurationUpdate(response);
+ assert false : "Should not have been able to process an unknown request - we didn't persist it yet";
+ } catch (Exception expected) {
+ System.out.println("This was expected and OK:\n" + expected);
+ }
+ }
+
+ void persist(Object entity) throws Exception {
+ EntityManager entityMgr = getEntityManager();
+ getEntityManager().persist(entity);
+ entityMgr.flush();
+ entityMgr.clear();
+ }
+
+ void delete(Configuration configuration) {
+ EntityManager entityMgr = getEntityManager();
+ Configuration managedConfig = entityMgr.find(Configuration.class, configuration.getId());
+ entityMgr.remove(managedConfig);
+ }
+
+ private class TestServices implements ConfigurationAgentService, DiscoveryAgentService {
+ private Configuration savedConfiguration = null;
+
+ public ConfigurationUpdateResponse executeUpdateResourceConfigurationImmediately(
+ ConfigurationUpdateRequest request) throws PluginContainerException {
+ return null;
+ }
+
+ public AvailabilityReport executeAvailabilityScanImmediately(boolean changedOnlyReport) {
+ return null;
+ }
+
+ public void updateResourceConfiguration(final ConfigurationUpdateRequest request) {
+ Thread thread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ PropertySimple mysleep = request.getConfiguration().getSimple("mysleep");
+ PropertySimple mybool = request.getConfiguration().getSimple("myboolean");
+ assert mybool != null;
+
+ ConfigurationUpdateResponse response;
+
+ if (mybool.getStringValue().equalsIgnoreCase("true")) {
+ savedConfiguration = request.getConfiguration();
+
+ // tests need us to sleep AFTER we save the config
+ if (mysleep != null) {
+ Thread.sleep(mysleep.getLongValue());
+ }
+
+ response = new ConfigurationUpdateResponse(request.getConfigurationUpdateId(), null,
+ ConfigurationUpdateStatus.SUCCESS, null);
+ } else if (mybool.getStringValue().equalsIgnoreCase("false")) {
+ savedConfiguration = request.getConfiguration();
+
+ // tests need us to sleep AFTER we save the config
+ if (mysleep != null) {
+ Thread.sleep(mysleep.getLongValue());
+ }
+
+ response = new ConfigurationUpdateResponse(request.getConfigurationUpdateId(), null,
+ ConfigurationUpdateStatus.SUCCESS, null);
+ } else {
+ mybool.setErrorMessage(ThrowableUtil.getStackAsString(new IllegalArgumentException(
+ "Not a valid boolean")));
+ response = new ConfigurationUpdateResponse(request.getConfigurationUpdateId(),
+ request.getConfiguration(), new NullPointerException("This simulates a failed update"));
+ }
+
+ LookupUtil.getConfigurationManager().completeResourceConfigurationUpdate(response);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+ };
+
+ thread.start();
+ }
+
+ public void updatePluginConfiguration(int resourceId, Configuration newPluginConfiguration)
+ throws InvalidPluginConfigurationClientException, PluginContainerException {
+ PropertySimple mybool = newPluginConfiguration.getSimple("fail");
+ if ((mybool != null) && mybool.getBooleanValue()) {
+ throw new PluginContainerException("Simulates a failure to update plugin config");
+ }
+
+ return;
+ }
+
+ public ResourceConfigurationUpdate createResource(Resource parent, ResourceType resourceType,
+ ResourceConfigurationUpdate configuration) throws PluginContainerException {
+ return null;
+ }
+
+ public void deleteResource(Resource resource) throws PluginContainerException {
+ }
+
+ public Configuration loadResourceConfiguration(int resourceId) throws PluginContainerException {
+ return savedConfiguration;
+ }
+
+ public Configuration loadResourceConfiguration(int resourceId, boolean fromStructured)
+ throws PluginContainerException {
+ return savedConfiguration;
+ }
+
+ public Configuration merge(Configuration configuration, int resourceId, boolean fromStructured)
+ throws PluginContainerException {
+ return null;
+ }
+
+ public void disableServiceScans(int serverResourceId) {
+ }
+
+ public void enableServiceScans(int serverResourceId, Configuration config) {
+ }
+
+ @NotNull
+ public InventoryReport executeServerScanImmediately() throws PluginContainerException {
+ return null;
+ }
+
+ @NotNull
+ public InventoryReport executeServiceScanImmediately() throws PluginContainerException {
+ return null;
+ }
+
+ public void executeServiceScanDeferred() {
+ return;
+ }
+
+ public Availability getCurrentAvailability(Resource resource) {
+ return null;
+ }
+
+ public MergeResourceResponse manuallyAddResource(ResourceType resourceType, int parentResourceId,
+ Configuration pluginConfiguration, int ownerSubjectId) throws InvalidPluginConfigurationClientException,
+ PluginContainerException {
+ return null;
+ }
+
+ public Resource getPlatform() {
+ return null;
+ }
+
+ public InventoryReport getPlatformScanResults(long jobId) {
+ return null;
+ }
+
+ public long startPlatformScan(Configuration config) {
+ return 0;
+ }
+
+ public boolean stopPlatformScan(long jobId) {
+ return false;
+ }
+
+ public void uninventoryResource(int resourceId) {
+ }
+
+ @Asynchronous(guaranteedDelivery = true)
+ public void synchronizeInventory(ResourceSyncInfo syncInfo) {
+ }
+
+ public Configuration validate(Configuration configuration, int resourceId, boolean isStructured)
+ throws PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public void requestFullAvailabilityReport() {
+ return;
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBeanUnitTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBeanUnitTest.java
new file mode 100644
index 0000000..d51798d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBeanUnitTest.java
@@ -0,0 +1,575 @@
+/*
+ * 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, 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.enterprise.server.configuration;
+
+import static org.rhq.core.domain.authz.Permission.CONFIGURE_READ;
+import static org.rhq.core.domain.authz.Permission.CONFIGURE_WRITE;
+import static org.rhq.test.AssertUtils.*;
+import static org.rhq.core.domain.configuration.ConfigurationUpdateStatus.*;
+import static org.testng.Assert.*;
+
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.util.exception.ThrowableUtil;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.test.JMockTest;
+import org.rhq.test.jmock.PropertyMatcher;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.ResourceConfigurationUpdate;
+import org.rhq.core.domain.configuration.RawConfiguration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.ConfigurationFormat;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.clientapi.agent.configuration.ConfigurationAgentService;
+import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
+import org.rhq.enterprise.server.core.AgentManagerLocal;
+import org.rhq.enterprise.server.agentclient.AgentClient;
+import org.rhq.enterprise.server.authz.AuthorizationManagerLocal;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeMethod;
+import org.jmock.Expectations;
+import org.jmock.Sequence;
+import org.hamcrest.Matcher;
+
+import javax.persistence.EntityManager;
+import java.lang.reflect.Field;
+
+public class ConfigurationManagerBeanUnitTest extends JMockTest {
+
+ static final boolean FROM_STRUCTURED = true;
+ static final boolean FROM_RAW = false;
+ static final Subject OVERLORD = new Subject("overlord", true, true);
+
+ ConfigurationManagerLocal configurationMgrLocal;
+
+ ResourceManagerLocal resourceMgr;
+
+ SubjectManagerLocal subjectMgr;
+
+ AgentManagerLocal agentMgr;
+
+ AuthorizationManagerLocal authorizationMgr;
+
+ EntityManager entityMgr;
+
+ ConfigurationManagerBean configurationMgr;
+
+ @BeforeMethod
+ public void setup() throws Exception {
+ configurationMgr = new ConfigurationManagerBean();
+
+ configurationMgrLocal = context.mock(ConfigurationManagerLocal.class);
+ setField(configurationMgr, "configurationManager", configurationMgrLocal);
+
+ agentMgr = context.mock(AgentManagerLocal.class);
+ setField(configurationMgr, "agentManager", agentMgr);
+
+ authorizationMgr = context.mock(AuthorizationManagerLocal.class);
+ setField(configurationMgr, "authorizationManager", authorizationMgr);
+
+ entityMgr = context.mock(EntityManager.class);
+ setField(configurationMgr, "entityManager", entityMgr);
+
+ resourceMgr = context.mock(ResourceManagerLocal.class);
+ setField(configurationMgr, "resourceManager", resourceMgr);
+
+ subjectMgr = context.mock(SubjectManagerLocal.class);
+ setField(configurationMgr, "subjectManager", subjectMgr);
+ }
+
+ static void setField(Object src, String fieldName, Object value) {
+ try {
+ Field field = src.getClass().getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(src, value);
+ }
+ catch (SecurityException e) {
+ throw new RuntimeException(e);
+ }
+ catch (IllegalArgumentException e) {
+ throw new RuntimeException(e);
+ }
+ catch (NoSuchFieldException e) {
+ String msg = "The field <" + fieldName + "> does not exist for " +
+ src.getClass().getName();
+ throw new RuntimeException(e);
+ }
+ catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ @Test
+ public void updateStructuredResourceConfigShouldUpdateAuditTrailAndSendUpdateToAgent() throws Exception {
+ final ResourceConfigUpdateFixture fixture = newStructuredResourceConfigUpdateFixture();
+
+ final ResourceConfigurationUpdate expectedUpdate = new ResourceConfigurationUpdate(fixture.resource,
+ fixture.configuration, fixture.subject.getName());
+
+ final AgentClient agentClient = context.mock(AgentClient.class);
+ final ConfigurationAgentService configAgentService = context.mock(ConfigurationAgentService.class);
+
+ final ConfigurationUpdateRequest expectedUpdateRequest = new ConfigurationUpdateRequest(expectedUpdate.getId(),
+ expectedUpdate.getConfiguration(), expectedUpdate.getResource().getId());
+
+ context.checking(new Expectations() {{
+ allowing(subjectMgr).getOverlord(); will(returnValue(OVERLORD));
+
+ allowing(resourceMgr).getResource(OVERLORD, fixture.resourceId);
+ will(returnValue(fixture.resource));
+
+ oneOf(authorizationMgr).hasResourcePermission(fixture.subject, CONFIGURE_WRITE, fixture.resourceId);
+ will(returnValue(true));
+
+ allowing(entityMgr).find(Resource.class, fixture.resourceId); will(returnValue(fixture.resource));
+
+ oneOf(configurationMgrLocal).persistNewResourceConfigurationUpdateHistory(fixture.subject,
+ fixture.resourceId, fixture.configuration, INPROGRESS, fixture.subject.getName(),
+ fixture.isPartOfGroupUpdate);
+ will(returnValue(expectedUpdate));
+
+ allowing(agentMgr).getAgentClient(expectedUpdate.getResource().getAgent()); will(returnValue(agentClient));
+
+ allowing(agentClient).getConfigurationAgentService(); will(returnValue(configAgentService));
+
+ oneOf(configAgentService).updateResourceConfiguration(with(matchingUpdateRequest(expectedUpdateRequest)));
+ }});
+
+ ResourceConfigurationUpdate actualUpdate = configurationMgr.updateResourceConfiguration(fixture.subject,
+ fixture.resourceId, fixture.configuration);
+
+ assertSame(actualUpdate, expectedUpdate, "Expected to get back the persisted configuration update");
+ }
+
+ @Test
+ public void updateRawResourceConfigShouldUpdateAuditTrailAndSendUpdateToAgent() throws Exception {
+ final ResourceConfigUpdateFixture fixture = newRawResourceConfigUpdateFixture();
+
+ final ResourceConfigurationUpdate expectedUpdate = new ResourceConfigurationUpdate(fixture.resource,
+ fixture.configuration, fixture.subject.getName());
+
+ final AgentClient agentClient = context.mock(AgentClient.class);
+ final ConfigurationAgentService configAgentService = context.mock(ConfigurationAgentService.class);
+
+ final ConfigurationUpdateRequest expectedUpdateRequest = new ConfigurationUpdateRequest(expectedUpdate.getId(),
+ expectedUpdate.getConfiguration(), expectedUpdate.getResource().getId());
+
+ context.checking(new Expectations() {{
+ allowing(subjectMgr).getOverlord(); will(returnValue(OVERLORD));
+
+ allowing(resourceMgr).getResource(OVERLORD, fixture.resourceId);
+ will(returnValue(fixture.resource));
+
+ allowing(entityMgr).find(Resource.class, fixture.resourceId); will(returnValue(fixture.resource));
+
+ oneOf(authorizationMgr).hasResourcePermission(fixture.subject, CONFIGURE_WRITE, fixture.resourceId);
+ will(returnValue(true));
+
+ oneOf(configurationMgrLocal).persistNewResourceConfigurationUpdateHistory(fixture.subject,
+ fixture.resourceId, fixture.configuration, INPROGRESS, fixture.subject.getName(),
+ fixture.isPartOfGroupUpdate);
+ will(returnValue(expectedUpdate));
+
+ allowing(agentMgr).getAgentClient(expectedUpdate.getResource().getAgent()); will(returnValue(agentClient));
+
+ allowing(agentClient).getConfigurationAgentService(); will(returnValue(configAgentService));
+
+ oneOf(configAgentService).updateResourceConfiguration(with(matchingUpdateRequest(expectedUpdateRequest)));
+ }});
+
+ ResourceConfigurationUpdate actualUpdate = configurationMgr.updateResourceConfiguration(fixture.subject,
+ fixture.resourceId, fixture.configuration);
+
+ assertSame(actualUpdate, expectedUpdate, "Expected to get back the persisted configuration update");
+ }
+
+ @Test(expectedExceptions = ConfigurationUpdateNotSupportedException.class)
+ public void exceptionShouldBeThrownWhenCallingWrongMethodForConfigThatSupportsStructuredAndRaw() throws Exception {
+ final ResourceConfigUpdateFixture fixture = newStructuredAndRawResourceConfigUpdateFixture();
+
+ context.checking(new Expectations() {{
+ allowing(entityMgr).find(Resource.class, fixture.resourceId); will(returnValue(fixture.resource));
+ }});
+
+ configurationMgr.updateResourceConfiguration(fixture.subject, fixture.resourceId, fixture.configuration);
+ }
+
+ @Test
+ public void updateResourceConfigShouldNotTranslateStructuredWhenRawNotSupported() throws Exception {
+ final ResourceConfigUpdateFixture fixture = newStructuredResourceConfigUpdateFixture();
+
+ final ResourceConfigurationUpdate expectedUpdate = new ResourceConfigurationUpdate(fixture.resource,
+ fixture.configuration, fixture.subject.getName());
+ expectedUpdate.setId(-1);
+
+ final AgentClient agentClient = context.mock(AgentClient.class);
+ final ConfigurationAgentService configAgentService = context.mock(ConfigurationAgentService.class);
+
+ final ConfigurationUpdateRequest expectedUpdateRequest = new ConfigurationUpdateRequest(expectedUpdate.getId(),
+ expectedUpdate.getConfiguration(), expectedUpdate.getResource().getId());
+
+ final Sequence configUdpate = context.sequence("structured-config-update");
+
+ context.checking(new Expectations() {{
+ oneOf(authorizationMgr).canViewResource(fixture.subject, fixture.resourceId);
+ will(returnValue(true));
+
+ oneOf(authorizationMgr).hasResourcePermission(fixture.subject, CONFIGURE_WRITE, fixture.resourceId);
+ will(returnValue(true));
+
+ allowing(entityMgr).find(Resource.class, fixture.resourceId); will(returnValue(fixture.resource));
+
+ allowing(agentMgr).getAgentClient(expectedUpdate.getResource().getAgent()); will(returnValue(agentClient));
+
+ allowing(agentClient).getConfigurationAgentService(); will(returnValue(configAgentService));
+
+ oneOf(configAgentService).validate(fixture.configuration, fixture.resourceId, FROM_STRUCTURED);
+ inSequence(configUdpate);
+
+ oneOf(configurationMgrLocal).persistNewResourceConfigurationUpdateHistory(fixture.subject,
+ fixture.resourceId, fixture.configuration, INPROGRESS, fixture.subject.getName(),
+ fixture.isPartOfGroupUpdate);
+ will(returnValue(expectedUpdate));
+ inSequence(configUdpate);
+
+ oneOf(configAgentService).updateResourceConfiguration(with(matchingUpdateRequest(expectedUpdateRequest)));
+ inSequence(configUdpate);
+ }});
+
+ ResourceConfigurationUpdate actualUpdate = configurationMgr.updateStructuredOrRawConfiguration(fixture.subject,
+ fixture.resourceId, fixture.configuration, FROM_STRUCTURED);
+
+ assertSame(actualUpdate, expectedUpdate, "Expected to get back the persisted configuration update");
+ }
+
+ @Test
+ public void updateResourceConfigShouldTranslateRawWhenRawConfigHasEdits() throws Exception {
+ final ResourceConfigUpdateFixture fixture = newStructuredAndRawResourceConfigUpdateFixture();
+ fixture.configuration.addRawConfiguration(new RawConfiguration());
+
+ final Configuration translatedConfig = fixture.configuration.deepCopy();
+ translatedConfig.put(new PropertySimple("x", "y"));
+
+ final ResourceConfigurationUpdate expectedUpdate = new ResourceConfigurationUpdate(fixture.resource, translatedConfig,
+ fixture.subject.getName());
+ expectedUpdate.setId(-1);
+
+ final AgentClient agentClient = context.mock(AgentClient.class);
+ final ConfigurationAgentService configAgentService = context.mock(ConfigurationAgentService.class);
+
+ final ConfigurationUpdateRequest expectedUpdateRequest = new ConfigurationUpdateRequest(expectedUpdate.getId(),
+ expectedUpdate.getConfiguration(), expectedUpdate.getResource().getId());
+
+ final Sequence configUdpate = context.sequence("raw-config-update");
+
+ context.checking(new Expectations() {{
+ oneOf(authorizationMgr).hasResourcePermission(fixture.subject, CONFIGURE_READ, fixture.resourceId);
+ will(returnValue(true));
+
+ oneOf(authorizationMgr).hasResourcePermission(fixture.subject, CONFIGURE_WRITE, fixture.resourceId);
+ will(returnValue(true));
+
+ allowing(entityMgr).find(Resource.class, fixture.resourceId); will(returnValue(fixture.resource));
+
+ allowing(authorizationMgr).canViewResource(fixture.subject, fixture.resourceId); will(returnValue(true));
+
+ oneOf(configAgentService).merge(fixture.configuration, fixture.resourceId, FROM_RAW);
+ will(returnValue(translatedConfig)); inSequence(configUdpate);
+
+ oneOf(configurationMgrLocal).persistNewResourceConfigurationUpdateHistory(fixture.subject,
+ fixture.resourceId, translatedConfig, INPROGRESS, fixture.subject.getName(),
+ fixture.isPartOfGroupUpdate);
+ will(returnValue(expectedUpdate));
+ inSequence(configUdpate);
+
+ allowing(agentMgr).getAgentClient(expectedUpdate.getResource().getAgent()); will(returnValue(agentClient));
+
+ allowing(agentClient).getConfigurationAgentService(); will(returnValue(configAgentService));
+
+ oneOf(configAgentService).validate(fixture.configuration, fixture.resourceId, FROM_RAW);
+
+ oneOf(configAgentService).updateResourceConfiguration(with(matchingUpdateRequest(expectedUpdateRequest)));
+ inSequence(configUdpate);
+ }});
+
+ ResourceConfigurationUpdate actualUpdate = configurationMgr.updateStructuredOrRawConfiguration(fixture.subject,
+ fixture.resourceId, fixture.configuration, FROM_RAW);
+
+ assertSame(actualUpdate, expectedUpdate, "Expected to get back the persisted configuration update");
+ }
+
+ @Test
+ public void updateResourceConfigShouldMarkUpdateAsFailureWhenExceptionOccurs() throws Exception {
+ final ResourceConfigUpdateFixture fixture = newStructuredResourceConfigUpdateFixture();
+
+ final RuntimeException exception = new RuntimeException();
+
+ final ResourceConfigurationUpdate expectedUpdate = new ResourceConfigurationUpdate(fixture.resource,
+ fixture.configuration, fixture.subject.getName());
+ expectedUpdate.setId(-1);
+ expectedUpdate.setStatus(FAILURE);
+ expectedUpdate.setErrorMessage(ThrowableUtil.getStackAsString(exception));
+
+ context.checking(new Expectations() {{
+ allowing(subjectMgr).getOverlord(); will(returnValue(OVERLORD));
+
+ allowing(resourceMgr).getResource(OVERLORD, fixture.resourceId);
+ will(returnValue(fixture.resource));
+
+ allowing(entityMgr).find(Resource.class, fixture.resourceId); will(returnValue(fixture.resource));
+
+ allowing(entityMgr).find(ResourceConfigurationUpdate.class, expectedUpdate.getId());
+ will(returnValue(expectedUpdate));
+
+ oneOf(authorizationMgr).hasResourcePermission(fixture.subject, CONFIGURE_WRITE, fixture.resourceId);
+ will(returnValue(true));
+
+ oneOf(configurationMgrLocal).persistNewResourceConfigurationUpdateHistory(fixture.subject, fixture.resourceId,
+ fixture.configuration, INPROGRESS, fixture.subject.getName(), fixture.isPartOfGroupUpdate);
+ will(returnValue(expectedUpdate));
+
+ oneOf(configurationMgrLocal).mergeConfigurationUpdate(expectedUpdate);
+
+ allowing(agentMgr).getAgentClient(expectedUpdate.getResource().getAgent());
+ will(throwException(exception));
+ }});
+
+ ResourceConfigurationUpdate actualUpdate = configurationMgr.updateResourceConfiguration(fixture.subject,
+ fixture.resourceId, fixture.configuration);
+
+ assertPropertiesMatch(expectedUpdate, actualUpdate, "Expected to get back a failure update");
+ }
+
+ @Test
+ public void translatingFromStructuredToRawShouldReturnModifiedConfig() throws Exception {
+ final ConfigTranslationFixture fixture = newStructuredAndRawTranslationFixture();
+
+ final AgentClient agentClient = context.mock(AgentClient.class);
+ final ConfigurationAgentService configAgentService = context.mock(ConfigurationAgentService.class);
+
+ final Configuration expectedConfig = new Configuration();
+
+ context.checking(new Expectations() {{
+ allowing(entityMgr).find(Resource.class, fixture.resourceId); will(returnValue(fixture.resource));
+
+ allowing(agentMgr).getAgentClient(fixture.resource.getAgent()); will(returnValue(agentClient));
+
+ oneOf(authorizationMgr).hasResourcePermission(fixture.subject, CONFIGURE_READ, fixture.resourceId);
+ will(returnValue(true));
+
+ allowing(agentClient).getConfigurationAgentService(); will(returnValue(configAgentService));
+
+ oneOf(configAgentService).merge(fixture.configuration, fixture.resourceId, FROM_STRUCTURED);
+ will(returnValue(expectedConfig));
+ }});
+
+ Configuration translatedConfig = configurationMgr.translateResourceConfiguration(fixture.subject,
+ fixture.resourceId, fixture.configuration, FROM_STRUCTURED);
+
+ assertSame(
+ translatedConfig,
+ expectedConfig,
+ "Expected to get back the configuration translated by the " + ConfigurationAgentService.class.getSimpleName());
+ }
+
+ @Test
+ public void translatingFromRawToStructuredShouldReturnModifiedConfig() throws Exception {
+ final ConfigTranslationFixture fixture = newStructuredAndRawTranslationFixture();
+
+ final AgentClient agentClient = context.mock(AgentClient.class);
+ final ConfigurationAgentService configAgentService = context.mock(ConfigurationAgentService.class);
+
+ final Configuration expectedConfig = new Configuration();
+
+ context.checking(new Expectations() {{
+ allowing(entityMgr).find(Resource.class, fixture.resourceId); will(returnValue(fixture.resource));
+
+ oneOf(authorizationMgr).hasResourcePermission(fixture.subject, CONFIGURE_READ, fixture.resourceId);
+ will(returnValue(true));
+
+ allowing(agentMgr).getAgentClient(fixture.resource.getAgent()); will(returnValue(agentClient));
+
+ allowing(agentClient).getConfigurationAgentService(); will(returnValue(configAgentService));
+
+ oneOf(configAgentService).merge(fixture.configuration, fixture.resourceId, FROM_RAW);
+ will(returnValue(expectedConfig));
+ }});
+
+ Configuration translatedConfig = configurationMgr.translateResourceConfiguration(fixture.subject,
+ fixture.resourceId, fixture.configuration, FROM_RAW);
+
+ assertSame(
+ translatedConfig,
+ expectedConfig,
+ "Expected to get back the configuration translated by the " + ConfigurationAgentService.class.getSimpleName());
+ }
+
+ @Test(expectedExceptions = TranslationNotSupportedException.class)
+ public void exceptionShouldBeThrownWhenTryingToTranslateStructuredOnlyConfig() throws Exception {
+ final ConfigTranslationFixture fixture = newStructuredTranslationFixture();
+
+ context.checking(new Expectations() {{
+ allowing(entityMgr).find(Resource.class, fixture.resourceId); will(returnValue(fixture.resource));
+ }});
+
+ configurationMgr.translateResourceConfiguration(fixture.subject, fixture.resourceId, fixture.configuration,
+ FROM_STRUCTURED);
+ }
+
+ @Test(expectedExceptions = TranslationNotSupportedException.class)
+ public void exceptionShouldBeThrownWhenTryingToTranslateRawOnlyConfig() throws Exception {
+ final ConfigTranslationFixture fixture = newRawTranslationFixture();
+
+ context.checking(new Expectations() {{
+ allowing(entityMgr).find(Resource.class, fixture.resourceId); will(returnValue(fixture.resource));
+ }});
+
+ configurationMgr.translateResourceConfiguration(fixture.subject, fixture.resourceId, fixture.configuration,
+ FROM_RAW);
+ }
+
+ public static Matcher<ConfigurationUpdateRequest> matchingUpdateRequest(ConfigurationUpdateRequest expected) {
+ return new PropertyMatcher<ConfigurationUpdateRequest>(expected);
+ }
+
+ ResourceConfigUpdateFixture newStructuredResourceConfigUpdateFixture() {
+ ResourceConfigUpdateFixture fixture = new ResourceConfigUpdateFixture();
+ fixture.resource = createResourceWithStructuredConfig(fixture.resourceId);
+
+ return fixture;
+ }
+
+ ResourceConfigUpdateFixture newRawResourceConfigUpdateFixture() {
+ ResourceConfigUpdateFixture fixture = new ResourceConfigUpdateFixture();
+ fixture.resource = createResourceWithRawConfig(fixture.resourceId);
+
+ return fixture;
+ }
+
+ ResourceConfigUpdateFixture newStructuredAndRawResourceConfigUpdateFixture() {
+ ResourceConfigUpdateFixture fixture = new ResourceConfigUpdateFixture();
+ fixture.resource = createResourceWithStructuredAndRawConfig(fixture.resourceId);
+
+ return fixture;
+ }
+
+ ConfigTranslationFixture newStructuredAndRawTranslationFixture() {
+ ConfigTranslationFixture fixture = new ConfigTranslationFixture();
+ fixture.resource = createResourceWithStructuredAndRawConfig(fixture.resourceId);
+
+ return fixture;
+ }
+
+ ConfigTranslationFixture newStructuredTranslationFixture() {
+ ConfigTranslationFixture fixture = new ConfigTranslationFixture();
+ fixture.resource = createResourceWithStructuredConfig(fixture.resourceId);
+
+ return fixture;
+ }
+
+ ConfigTranslationFixture newRawTranslationFixture() {
+ ConfigTranslationFixture fixture = new ConfigTranslationFixture();
+ fixture.resource = createResourceWithRawConfig(fixture.resourceId);
+
+ return fixture;
+ }
+
+ Resource createResource(int resourceId) {
+ Resource resource = new Resource(resourceId);
+ resource.setAgent(new Agent("test-agent", "localhost", 7080, null, null));
+ return resource;
+ }
+
+ Resource createResourceWithStructuredConfig(int resourceId) {
+ Resource resource = createResource(resourceId);
+ resource.setResourceType(createStructurerdOnlyResourceType());
+
+ return resource;
+ }
+
+ Resource createResourceWithStructuredAndRawConfig(int resourceId) {
+ Resource resource = createResource(resourceId);
+ resource.setResourceType(createStructuredAndRawResourceType());
+
+ return resource;
+ }
+
+ Resource createResourceWithRawConfig(int resourceId) {
+ Resource resource = createResource(resourceId);
+ resource.setResourceType(createRawResourceType());
+
+ return resource;
+ }
+
+ ResourceType createStructuredAndRawResourceType() {
+ ConfigurationDefinition configDef = new ConfigurationDefinition("structured-and-raw", "structured and raw");
+ configDef.setConfigurationFormat(ConfigurationFormat.STRUCTURED_AND_RAW);
+
+ ResourceType resourceType = new ResourceType();
+ resourceType.setResourceConfigurationDefinition(configDef);
+
+ return resourceType;
+ }
+
+ ResourceType createStructurerdOnlyResourceType() {
+ ConfigurationDefinition configDef = new ConfigurationDefinition("structred-config-def", "structured config def");
+ configDef.setConfigurationFormat(ConfigurationFormat.STRUCTURED);
+
+ ResourceType resourceType = new ResourceType();
+ resourceType.setResourceConfigurationDefinition(configDef);
+
+ return resourceType;
+ }
+
+ ResourceType createRawResourceType() {
+ ConfigurationDefinition configDef = new ConfigurationDefinition("raw-config-def", "raw config def");
+ configDef.setConfigurationFormat(ConfigurationFormat.RAW);
+
+ ResourceType resourceType = new ResourceType();
+ resourceType.setResourceConfigurationDefinition(configDef);
+
+ return resourceType;
+ }
+
+ static class ResourceConfigUpdateFixture {
+ Subject subject = new Subject("rhqadmin", true, true);
+ int resourceId = -1;
+ Configuration configuration = new Configuration();
+ boolean isPartOfGroupUpdate = false;
+ Resource resource;
+ }
+
+ static class ConfigTranslationFixture {
+ Subject subject = new Subject("rhqadmin", true, true);
+ int resourceId = -1;
+ Configuration configuration = new Configuration();
+ Resource resource;
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/DynamicConfigurationPropertyBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/DynamicConfigurationPropertyBeanTest.java
new file mode 100644
index 0000000..dba76ed
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/DynamicConfigurationPropertyBeanTest.java
@@ -0,0 +1,176 @@
+/*
+* RHQ Management Platform
+* Copyright (C) 2009 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.enterprise.server.configuration;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import javax.transaction.NotSupportedException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.TransactionManager;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.authz.Role;
+import org.rhq.core.domain.configuration.DynamicConfigurationPropertyValue;
+import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * @author Jason Dobies
+ */
+public class DynamicConfigurationPropertyBeanTest extends AbstractEJB3Test {
+
+ private static final boolean ENABLED = true;
+
+ private DynamicConfigurationPropertyLocal bean;
+
+ @BeforeMethod
+ public void setUp() {
+ bean = LookupUtil.getDynamicConfigurationProperty();
+ }
+
+ @Test(enabled = ENABLED)
+ public void invalidKey() throws Exception {
+ // Test
+ List<DynamicConfigurationPropertyValue> stringList = bean.lookupValues("foo");
+
+ //Verify
+ assert stringList != null;
+ assert stringList.size() == 0;
+ }
+
+ @Test(enabled = ENABLED)
+ public void user() throws Exception {
+ String queryString = "SELECT s FROM Subject s WHERE s.fsystem = false";
+
+ // Setup
+ int existingUserCount = countForQuery(queryString, false);
+
+ // Test
+ List<DynamicConfigurationPropertyValue> users = bean.lookupValues(PropertyExpressionEvaluator.KEY_USERS);
+
+ // Verify
+ outputList(users);
+ assert users.size() == existingUserCount : "Expected: " + existingUserCount + ", Found: " + users.size();
+ }
+
+ @Test(enabled = ENABLED)
+ public void roles() throws Exception {
+ // Setup
+ int existingRoleCount = countForQuery(Role.QUERY_FIND_ALL);
+
+ // Test
+ List<DynamicConfigurationPropertyValue> roles = bean.lookupValues(PropertyExpressionEvaluator.KEY_ROLES);
+
+ // Verify
+ outputList(roles);
+ assert roles.size() == existingRoleCount : "Expected: " + existingRoleCount + ", Found: " + roles.size();
+ }
+
+ @Test(enabled = ENABLED)
+ public void packageType() throws Exception {
+ // Setup
+ ResourceType resourceType = null;
+ PackageType packageType = null;
+
+ TransactionManager tx = getTransactionManager();
+ try {
+ tx.begin();
+ EntityManager entityManager = getEntityManager();
+
+ resourceType = new ResourceType("dynamicConfigPropBeanTestType", "foo", ResourceCategory.PLATFORM, null);
+ entityManager.persist(resourceType);
+
+ packageType = new PackageType("dynamicConfigPropBeanTestType", resourceType);
+ entityManager.persist(packageType);
+ tx.commit();
+ } catch (Exception e) {
+ if (tx.getStatus() == Status.STATUS_ACTIVE) {
+ tx.rollback();
+ }
+ }
+
+ int existingPackageTypes = countForQuery(PackageType.QUERY_FIND_ALL);
+ assert existingPackageTypes > 0 : "Package type created in setup was not written correctly";
+
+ // Test
+ List<DynamicConfigurationPropertyValue> types = bean
+ .lookupValues(PropertyExpressionEvaluator.KEY_PACKAGE_TYPES);
+
+ // Verify
+ assert types.size() == existingPackageTypes : "Expected: " + existingPackageTypes + ", Found: " + types.size();
+
+ // Clean up
+ tx = getTransactionManager();
+ try {
+ tx.begin();
+ EntityManager entityManager = getEntityManager();
+
+ resourceType = entityManager.find(ResourceType.class, resourceType.getId());
+ entityManager.remove(resourceType);
+
+ packageType = entityManager.find(PackageType.class, packageType.getId());
+ entityManager.remove(packageType);
+
+ tx.commit();
+ } catch (Exception e) {
+ if (tx.getStatus() == Status.STATUS_ACTIVE) {
+ tx.rollback();
+ }
+ }
+ }
+
+ private int countForQuery(String queryName) throws NotSupportedException, SystemException {
+ return countForQuery(queryName, true);
+ }
+
+ @SuppressWarnings("unchecked")
+ private int countForQuery(String queryString, boolean isName) throws NotSupportedException, SystemException {
+
+ getTransactionManager().begin();
+ EntityManager entityManager = getEntityManager();
+
+ Query query = (isName) ? entityManager.createNamedQuery(queryString) : entityManager.createQuery(queryString);
+ List existing = query.getResultList();
+
+ int count = existing.size();
+
+ getTransactionManager().rollback();
+
+ return count;
+ }
+
+ private void outputList(List<DynamicConfigurationPropertyValue> items) {
+ System.out.println("Items returned from lookupValues:");
+ for (DynamicConfigurationPropertyValue item : items) {
+ System.out.println(item);
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/LargeGroupPluginConfigurationTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/LargeGroupPluginConfigurationTest.java
new file mode 100644
index 0000000..2ad1547
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/LargeGroupPluginConfigurationTest.java
@@ -0,0 +1,243 @@
+/*
+ * 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.configuration;
+
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.jetbrains.annotations.NotNull;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.agent.PluginContainerException;
+import org.rhq.core.clientapi.agent.discovery.DiscoveryAgentService;
+import org.rhq.core.clientapi.agent.discovery.InvalidPluginConfigurationClientException;
+import org.rhq.core.clientapi.server.discovery.InventoryReport;
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
+import org.rhq.core.domain.discovery.AvailabilityReport;
+import org.rhq.core.domain.discovery.MergeResourceResponse;
+import org.rhq.core.domain.discovery.ResourceSyncInfo;
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.authz.PermissionException;
+import org.rhq.enterprise.server.test.LargeGroupTestBase;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.util.SessionTestHelper;
+
+@Test
+public class LargeGroupPluginConfigurationTest extends LargeGroupTestBase {
+
+ private LargeGroupEnvironment env;
+ private CountDownLatch latch;
+
+ @Override
+ protected void setupMockAgentServices(TestServerCommunicationsService agentServiceContainer) {
+ TestServices testServices = new TestServices();
+ agentServiceContainer.discoveryService = testServices;
+ }
+
+ /**
+ * Create a large group of 1000+ resources.
+ */
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ env = createLargeGroupWithNormalUserRoleAccess(1010, Permission.MODIFY_RESOURCE);
+ SessionTestHelper.simulateLogin(env.normalSubject);
+ }
+
+ /**
+ * Remove the group and all its members.
+ */
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ tearDownLargeGroupWithNormalUserRoleAccess(env);
+ SessionTestHelper.simulateLogout(env.normalSubject);
+ }
+
+ public void testGroupPluginConfigurationUpdate() throws Exception {
+ // all of our platform's children are members of the group we are testing with
+ int memberCount = env.platformResource.getChildResources().size();
+
+ // we don't have any updates yet, but when we created the resources, they had a default plugin config already set.
+ // let's see that we can obtain those plugin configs for all resources in the group
+ Map<Integer, Configuration> existingMap;
+ System.out.println("Getting plugin config for group [#members=" + memberCount + "]");
+ long start = System.currentTimeMillis();
+ existingMap = configurationManager.getPluginConfigurationsForCompatibleGroup(env.normalSubject,
+ env.compatibleGroup.getId());
+ long duration = System.currentTimeMillis() - start;
+ System.out.println("Took [" + duration + "]ms to get plugin config for group [#members=" + memberCount + "]");
+
+ assert existingMap.size() == memberCount : "did not get back the amount of configs [" + existingMap.size()
+ + "] we expected [" + memberCount + "]";
+
+ for (Map.Entry<Integer, Configuration> entry : existingMap.entrySet()) {
+ Integer resourceId = entry.getKey();
+ Configuration config = entry.getValue();
+ assert PC_PROP1_VALUE.equals(config.getSimpleValue(PC_PROP1_NAME, null)) : "bad plugin config for "
+ + resourceId + "=" + config.toString(true);
+ assert resourceId.toString().equals(config.getSimpleValue(PC_PROP2_NAME, null)) : "bad plugin config for "
+ + resourceId + "=" + config.toString(true);
+
+ // create new plugin configuration settings for this resource, we will update the group members to these new configs
+ config.getSimple(PC_PROP2_NAME).setStringValue("UPDATE" + resourceId);
+ }
+
+ // update our group with the new plugin configs
+ System.out.println("Scheduling a group plugin update.");
+ latch = new CountDownLatch(memberCount); // our TestService will count this down
+ int groupUpdateId = configurationManager.scheduleGroupPluginConfigurationUpdate(env.normalSubject,
+ env.compatibleGroup.getId(), existingMap);
+
+ // group plugin configuration update has been kicked off, wait for the mock agents to each complete their update
+ System.out.print("Waiting for mock agents");
+ assert latch.await(5, TimeUnit.MINUTES) : "agents should not have taken this long";
+ System.out.println(" Mock agents are done.");
+
+ // wait for group update to get out of the INPROGRESS state (it will eventually get to SUCCESS), but don't wait indefinitely
+ // this shouldn't take too long - just have to wait for the all the DB commits to complete
+ System.out.print("Waiting for group plugin config update to be finished...");
+ ConfigurationUpdateStatus status = getGroupPluginConfigurationStatus(env.compatibleGroup.getId());
+ boolean inprogress = (status == ConfigurationUpdateStatus.INPROGRESS);
+ for (int i = 0; i < 20 && inprogress; i++) {
+ Thread.sleep(3000);
+ status = getGroupPluginConfigurationStatus(env.compatibleGroup.getId());
+ inprogress = (status == ConfigurationUpdateStatus.INPROGRESS);
+ }
+ assert !inprogress : "group plugin configuration update is still inprogress - this is taking too long";
+ System.out.println(" Done. Status=" + ((status != null) ? status.name() : "????null????"));
+ assert status == ConfigurationUpdateStatus.SUCCESS : "should have finished in the success status";
+
+ // now see if our group plugin configuration update affected all of our resources by getting the group plugin config
+ System.out.println("Getting updated plugin config for group [#members=" + memberCount + "]");
+ start = System.currentTimeMillis();
+ existingMap = configurationManager.getPluginConfigurationsForCompatibleGroup(env.normalSubject,
+ env.compatibleGroup.getId());
+ duration = System.currentTimeMillis() - start;
+ System.out.println("Took [" + duration + "]ms to get updated plugin config for group [#members=" + memberCount
+ + "]");
+
+ assert existingMap.size() == memberCount : "did not get back the amount of configs [" + existingMap.size()
+ + "] we expected [" + memberCount + "]";
+
+ for (Map.Entry<Integer, Configuration> entry : existingMap.entrySet()) {
+ Integer resourceId = entry.getKey();
+ Configuration config = entry.getValue();
+ assert PC_PROP1_VALUE.equals(config.getSimpleValue(PC_PROP1_NAME, null)) : "bad plugin config for "
+ + resourceId + "=" + config.toString(true);
+ assert ("UPDATE" + resourceId.toString()).equals(config.getSimpleValue(PC_PROP2_NAME, null)) : "bad plugin config for "
+ + resourceId + "=" + config.toString(true);
+ }
+
+ // now test our authz - unauthorized user should bomb out
+ System.out.println("Attempting unauthz access");
+ SessionTestHelper.simulateLogin(env.unauthzSubject);
+ start = System.currentTimeMillis();
+ try {
+ configurationManager.getPluginConfigurationsForCompatibleGroup(env.unauthzSubject,
+ env.compatibleGroup.getId());
+ assert false : "should have failed - unauthz user not allowed to get plugin configuration";
+ } catch (PermissionException expected) {
+ } finally {
+ duration = System.currentTimeMillis() - start;
+ SessionTestHelper.simulateLogout(env.unauthzSubject);
+ }
+ System.out.println("Took [" + duration + "]ms to attempt unauthz access");
+ return;
+ }
+
+ /**
+ * This class mocks out the remote agent. It will receive calls to, for example,
+ * update plugin configurations.
+ */
+ private class TestServices implements DiscoveryAgentService {
+
+ @Override
+ public void updatePluginConfiguration(int resourceId, Configuration newPluginConfiguration)
+ throws InvalidPluginConfigurationClientException, PluginContainerException {
+ latch.countDown();
+ long latchCount = latch.getCount();
+ System.out.print(((latchCount % 100) != 0) ? "." : String.valueOf(latchCount));
+ }
+
+ @Override
+ public AvailabilityReport executeAvailabilityScanImmediately(boolean changedOnlyReport) {
+ return null;
+ }
+
+ @Override
+ public Availability getCurrentAvailability(Resource resource) {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public InventoryReport executeServerScanImmediately() throws PluginContainerException {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public InventoryReport executeServiceScanImmediately() throws PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public void executeServiceScanDeferred() {
+ }
+
+ @Override
+ public Resource getPlatform() {
+ return null;
+ }
+
+ @Override
+ public MergeResourceResponse manuallyAddResource(ResourceType resourceType, int parentResourceId,
+ Configuration pluginConfiguration, int creatorSubjectId) throws InvalidPluginConfigurationClientException,
+ PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public void synchronizeInventory(ResourceSyncInfo syncInfo) {
+ }
+
+ @Override
+ public void uninventoryResource(int resourceId) {
+ }
+
+ @Override
+ public void disableServiceScans(int serverResourceId) {
+ }
+
+ @Override
+ public void enableServiceScans(int serverResourceId, Configuration config) {
+ }
+
+ @Override
+ public void requestFullAvailabilityReport() {
+ return;
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/LargeGroupResourceConfigurationTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/LargeGroupResourceConfigurationTest.java
new file mode 100644
index 0000000..591c12f
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/LargeGroupResourceConfigurationTest.java
@@ -0,0 +1,227 @@
+/*
+ * 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.configuration;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.agent.PluginContainerException;
+import org.rhq.core.clientapi.agent.configuration.ConfigurationAgentService;
+import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
+import org.rhq.core.clientapi.server.configuration.ConfigurationServerService;
+import org.rhq.core.clientapi.server.configuration.ConfigurationUpdateResponse;
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.enterprise.server.authz.PermissionException;
+import org.rhq.enterprise.server.test.LargeGroupTestBase;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.util.SessionTestHelper;
+
+@Test
+public class LargeGroupResourceConfigurationTest extends LargeGroupTestBase {
+
+ private LargeGroupEnvironment env;
+ private CountDownLatch latch;
+
+ @Override
+ protected void setupMockAgentServices(TestServerCommunicationsService agentServiceContainer) {
+ TestServices testServices = new TestServices();
+ agentServiceContainer.configurationService = testServices;
+ }
+
+ /**
+ * Create a large group of 1000+ resources.
+ */
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ env = createLargeGroupWithNormalUserRoleAccess(1010, Permission.CONFIGURE_READ, Permission.CONFIGURE_WRITE);
+ SessionTestHelper.simulateLogin(env.normalSubject);
+ }
+
+ /**
+ * Remove the group and all its members.
+ */
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ tearDownLargeGroupWithNormalUserRoleAccess(env);
+ SessionTestHelper.simulateLogout(env.normalSubject);
+ }
+
+ public void testGroupResourceConfigurationUpdate() throws Exception {
+ // all of our platform's children are members of the group we are testing with
+ int memberCount = env.platformResource.getChildResources().size();
+
+ // we don't have any resource config
+ // let's see that we can obtain the current live configs for all resources in the group
+ // our mock agent will return the live configs
+ Map<Integer, Configuration> existingMap;
+ System.out.println("Getting resource config for group [#members=" + memberCount + "]");
+ long start = System.currentTimeMillis();
+ existingMap = configurationManager.getResourceConfigurationsForCompatibleGroup(env.normalSubject,
+ env.compatibleGroup.getId());
+ long duration = System.currentTimeMillis() - start;
+ System.out.println("Took [" + duration + "]ms to get resource config for group [#members=" + memberCount + "]");
+
+ assert existingMap.size() == memberCount : "did not get back the amount of configs [" + existingMap.size()
+ + "] we expected [" + memberCount + "]";
+
+ for (Map.Entry<Integer, Configuration> entry : existingMap.entrySet()) {
+ Integer resourceId = entry.getKey();
+ Configuration config = entry.getValue();
+ assert RC_PROP1_VALUE.equals(config.getSimpleValue(RC_PROP1_NAME, null)) : "bad resource config for "
+ + resourceId + "=" + config.toString(true);
+ assert resourceId.toString().equals(config.getSimpleValue(RC_PROP2_NAME, null)) : "bad resource config for "
+ + resourceId + "=" + config.toString(true);
+
+ // create new resource configuration settings for this resource, we will update the group members to these new configs
+ config.getSimple(RC_PROP2_NAME).setStringValue("UPDATE" + resourceId);
+ }
+
+ // update our group with the new resource configs
+ System.out.println("Scheduling a group resource config update.");
+ latch = new CountDownLatch(memberCount); // our TestService will count this down
+ int groupUpdateId = configurationManager.scheduleGroupResourceConfigurationUpdate(env.normalSubject,
+ env.compatibleGroup.getId(), existingMap);
+
+ // group resource configuration update has been kicked off, wait for the mock agents to each complete their update
+ System.out.print("Waiting for mock agents");
+ assert latch.await(5, TimeUnit.MINUTES) : "agents should not have taken this long";
+ System.out.println(" Mock agents are done.");
+
+ // wait for group update to get out of the INPROGRESS state (it will eventually get to SUCCESS), but don't wait indefinitely
+ // this shouldn't take too long - just have to wait for the all the DB commits to complete
+ System.out.print("Waiting for group resource config update to be finished...");
+ ConfigurationUpdateStatus status = getGroupResourceConfigurationStatus(env.compatibleGroup.getId());
+ boolean inprogress = (status == ConfigurationUpdateStatus.INPROGRESS);
+ for (int i = 0; i < 20 && inprogress; i++) {
+ Thread.sleep(3000);
+ status = getGroupResourceConfigurationStatus(env.compatibleGroup.getId());
+ inprogress = (status == ConfigurationUpdateStatus.INPROGRESS);
+ }
+ assert !inprogress : "group resource configuration update is still inprogress - this is taking too long";
+ System.out.println(" Done. Status=" + ((status != null) ? status.name() : "????null????"));
+ assert status == ConfigurationUpdateStatus.SUCCESS : "should have finished in the success status";
+
+ // now see if our group resource configuration update affected all of our resources by getting the group plugin config
+ System.out.println("Getting updated resource config for group [#members=" + memberCount + "]");
+ start = System.currentTimeMillis();
+ existingMap = configurationManager.getResourceConfigurationsForCompatibleGroup(env.normalSubject,
+ env.compatibleGroup.getId());
+ duration = System.currentTimeMillis() - start;
+ System.out.println("Took [" + duration + "]ms to get updated resource config for group [#members="
+ + memberCount + "]");
+
+ assert existingMap.size() == memberCount : "did not get back the amount of configs [" + existingMap.size()
+ + "] we expected [" + memberCount + "]";
+
+ for (Map.Entry<Integer, Configuration> entry : existingMap.entrySet()) {
+ Integer resourceId = entry.getKey();
+ Configuration config = entry.getValue();
+ assert RC_PROP1_VALUE.equals(config.getSimpleValue(RC_PROP1_NAME, null)) : "bad resource config for "
+ + resourceId + "=" + config.toString(true);
+ assert ("UPDATE" + resourceId.toString()).equals(config.getSimpleValue(RC_PROP2_NAME, null)) : "bad resource config for "
+ + resourceId + "=" + config.toString(true);
+ }
+
+ // now test our authz - unauthorized user should bomb out
+ System.out.println("Attempting unauthz access");
+ SessionTestHelper.simulateLogin(env.unauthzSubject);
+ start = System.currentTimeMillis();
+ try {
+ configurationManager.getResourceConfigurationsForCompatibleGroup(env.unauthzSubject,
+ env.compatibleGroup.getId());
+ assert false : "should have failed - unauthz user not allowed to get resource configuration";
+ } catch (PermissionException expected) {
+ } finally {
+ duration = System.currentTimeMillis() - start;
+ SessionTestHelper.simulateLogout(env.unauthzSubject);
+ }
+ System.out.println("Took [" + duration + "]ms to attempt unauthz access");
+ return;
+ }
+
+ /**
+ * This class mocks out the remote agent. It will receive calls to, for example,
+ * update configurations.
+ */
+ private class TestServices implements ConfigurationAgentService {
+
+ private HashMap<Integer, Configuration> configs = new HashMap<Integer, Configuration>();
+
+ @Override
+ public void updateResourceConfiguration(ConfigurationUpdateRequest request) {
+ try {
+ synchronized (configs) {
+ configs.put(request.getResourceId(), request.getConfiguration());
+ }
+ ConfigurationUpdateResponse response = new ConfigurationUpdateResponse(
+ request.getConfigurationUpdateId(), request.getConfiguration(), ConfigurationUpdateStatus.SUCCESS,
+ null);
+ // simulate agent calling into the server to complete the update
+ ConfigurationServerService server = new ConfigurationServerServiceImpl();
+ server.completeConfigurationUpdate(response);
+ } finally {
+ latch.countDown();
+ }
+ return;
+ }
+
+ @Override
+ public Configuration loadResourceConfiguration(int resourceId) throws PluginContainerException {
+ synchronized (configs) {
+ Integer id = Integer.valueOf(resourceId);
+ if (configs.containsKey(id)) {
+ return configs.get(id);
+ } else {
+ Configuration config = new Configuration();
+ config.put(new PropertySimple(RC_PROP1_NAME, RC_PROP1_VALUE));
+ config.put(new PropertySimple(RC_PROP2_NAME, resourceId));
+ configs.put(id, config);
+ return config;
+ }
+ }
+ }
+
+ @Override
+ public ConfigurationUpdateResponse executeUpdateResourceConfigurationImmediately(
+ ConfigurationUpdateRequest request) throws PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public Configuration merge(Configuration configuration, int resourceId, boolean fromStructured)
+ throws PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public Configuration validate(Configuration configuration, int resourceId, boolean isStructured)
+ throws PluginContainerException {
+ return null;
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBeanTest.java
new file mode 100644
index 0000000..cdb5359
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBeanTest.java
@@ -0,0 +1,277 @@
+/*
+ * 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, 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.enterprise.server.configuration.metadata;
+
+import static java.util.Arrays.asList;
+import static org.rhq.core.clientapi.shared.PluginDescriptorUtil.loadPluginConfigDefFor;
+import static org.rhq.core.clientapi.shared.PluginDescriptorUtil.loadPluginDescriptor;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
+import javax.transaction.SystemException;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionEnumeration;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.configuration.definition.PropertyGroupDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyOptionsSource;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.test.AssertUtils;
+
+/**
+ * These are data-driven tests that exercise the plugin upgrade functionality around configurations such as plugin
+ * configurations and resource configurations. The data sets that are used are defined in two plugin descriptors. One
+ * is the original version and the other is the upgraded version. In order to avoid inter-dependencies between test
+ * methods, a separate plugin configuration should be used for each test method. A separate resource type is declared
+ * for each test, further documenting and delinating where each configuration is used. In the test methods, the
+ * original and updated configuration definitions are initialized with an xpath expression that specifies the owning
+ * resource type.
+ */
+public class ConfigurationMetadataManagerBeanTest extends AbstractEJB3Test {
+
+ private static final boolean ENABLED = true;
+
+ PluginDescriptor originalDescriptor;
+
+ PluginDescriptor updatedDescriptor;
+
+ ConfigurationDefinition originalConfigDef;
+
+ ConfigurationDefinition updatedConfigDef;
+
+ @BeforeClass
+ public void setupClass() {
+ String pluginFileBaseName = "configuration_metadata_manager_bean_test";
+ String version1 = pluginFileBaseName + "_v1.xml";
+ String version2 = pluginFileBaseName + "_v2.xml";
+
+ originalDescriptor = loadPluginDescriptor(getClass().getResource(version1));
+ updatedDescriptor = loadPluginDescriptor(getClass().getResource(version2));
+ }
+
+ @Test(enabled = ENABLED)
+ public void addNewUngroupedSimplePropertyDef() {
+ initConfigDefs("servers[name='MyServer1']", "test");
+
+ String propertyName = "newUngroupedProperty";
+ PropertyDefinitionSimple expected = updatedConfigDef.getPropertyDefinitionSimple(propertyName);
+ PropertyDefinitionSimple actual = originalConfigDef.getPropertyDefinitionSimple(propertyName);
+
+ assertPropertyDefinitionMatches("New ungrouped property defs should be added to the configuration definition",
+ expected, actual);
+ }
+
+ @Test(enabled = ENABLED)
+ public void removePropertyDefThatIsNotInNewDescriptor() {
+ initConfigDefs("servers[name='MyServer1']", "test");
+
+ assertNull("The property exists in version 1 but not in version 2 of the plugin; therefore, it should be "
+ + "removed the configuration definition", originalConfigDef.get("v1OnlyProperty"));
+ }
+
+ @Test(enabled = ENABLED)
+ public void doNotModifyExistingPropertyDefThatIsNotModifiedInUpgrade() {
+ initConfigDefs("servers[name='MyServer1']", "test");
+
+ String propertyName = "myExistingProperty";
+ PropertyDefinitionSimple expected = updatedConfigDef.getPropertyDefinitionSimple(propertyName);
+ PropertyDefinitionSimple actual = originalConfigDef.getPropertyDefinitionSimple(propertyName);
+
+ assertPropertyDefinitionMatches("Existing property that is not changed in new version of pluign should "
+ + "not change", expected, actual);
+ }
+
+ @Test(enabled = ENABLED)
+ public void updatePropertyWithAddedOptions() {
+ initConfigDefs("servers[name='ServerWithAddedOptions']", "UpdatedPropertyWithAddedOptions");
+
+ String propertyName = "mySimple";
+ PropertyDefinitionSimple expectedProperty = updatedConfigDef.getPropertyDefinitionSimple(propertyName);
+ List<PropertyDefinitionEnumeration> expected = expectedProperty.getEnumeratedValues();
+
+ PropertyDefinitionSimple actualProperty = originalConfigDef.getPropertyDefinitionSimple(propertyName);
+ List<PropertyDefinitionEnumeration> actual = actualProperty.getEnumeratedValues();
+
+ // TODO Need to verify order here as well
+ AssertUtils.assertCollectionEqualsNoOrder(expected, actual, "Options should have been added to property");
+ }
+
+ @Test(enabled = ENABLED)
+ public void addNewGroup() {
+ initConfigDefs("servers[name='GroupTests']", "GroupTests");
+
+ assertNotNull("The new property should be added to the configuration definition",
+ findGroup("newGroup", originalConfigDef));
+ }
+
+ @Test(enabled = ENABLED)
+ public void replaceMemberDefinitionOfPropertyList() {
+ initConfigDefs("servers[name='UpdatedPropertyList']", "ReplaceMemberDefinitionOfPropertyList");
+
+ String propertyName = "myList";
+ PropertyDefinitionList expectedList = updatedConfigDef.getPropertyDefinitionList(propertyName);
+ PropertyDefinitionList actualList = originalConfigDef.getPropertyDefinitionList(propertyName);
+
+ assertPropertyDefinitionMatches("The member definition should be replaced with the new version", expectedList,
+ actualList);
+ }
+
+ @Test(enabled = ENABLED)
+ public void mapPropertyOrderTest() {
+ initConfigDefs("servers[name='UnchangedMap']", "UnchangedMap");
+
+ String propertyName = "myMap";
+ PropertyDefinitionMap map = originalConfigDef.getPropertyDefinitionMap(propertyName);
+ Map<String, PropertyDefinition> propDefs = map.getMap();
+ assertEquals("Expected three properties in unchanged map", 2, propDefs.size());
+ assertEquals("Expected property to be kept", "property1ToKeep", propDefs.get("property1ToKeep").getName());
+ assertEquals("Expected property to be kept", "property2ToKeep", propDefs.get("property2ToKeep").getName());
+ assertEquals("Expected order_index to be 0", 0, propDefs.get("property1ToKeep").getOrder());
+ assertEquals("Expected order_index to be 1", 1, propDefs.get("property2ToKeep").getOrder());
+ }
+
+ @Test(enabled = ENABLED)
+ public void updateMapWithAddRemoveProperty() {
+ initConfigDefs("servers[name='UpdatedMapWithAddRemoveProperty']", "UpdateMapWithAddRemoveProperty");
+
+ String propertyName = "myMap";
+ PropertyDefinitionMap map = originalConfigDef.getPropertyDefinitionMap(propertyName);
+ Map<String, PropertyDefinition> propDefs = map.getMap();
+ assertEquals("Expected three properties in updated map", 3, propDefs.size());
+ assertEquals("Expected property to be kept", "property1ToKeep", propDefs.get("property1ToKeep").getName());
+ assertEquals("Expected property to be added", "propertyToAdd", propDefs.get("propertyToAdd").getName());
+ assertEquals("Expected property to be kept", "property2ToKeep", propDefs.get("property2ToKeep").getName());
+ assertEquals("Expected order_index to be 0", 0, propDefs.get("property1ToKeep").getOrder());
+ assertEquals("Expected order_index to be 1", 1, propDefs.get("propertyToAdd").getOrder());
+ assertEquals("Expected order_index to be 2", 2, propDefs.get("property2ToKeep").getOrder());
+ }
+
+ @Test(enabled = ENABLED)
+ public void updateMapWithUpdatedProperty() {
+ initConfigDefs("servers[name='UpdatedMapWithUpdatedProperty']", "UpdateMapWithUpdatedProperty");
+
+ String propertyName = "propertyToUpdate";
+ String mapPropertyName = "myMap";
+
+ PropertyDefinitionMap expectedMap = updatedConfigDef.getPropertyDefinitionMap(mapPropertyName);
+ PropertyDefinitionSimple expected = expectedMap.getPropertyDefinitionSimple(propertyName);
+
+ PropertyDefinitionMap actualMap = originalConfigDef.getPropertyDefinitionMap(mapPropertyName);
+ PropertyDefinitionSimple actual = actualMap.getPropertyDefinitionSimple(propertyName);
+
+ List<String> ignoredProperties = asList("id", "parentPropertyMapDefinition");
+
+ assertPropertyDefinitionMatches("Expected property who is a child of map to get updated and remain in the map",
+ expected, actual, ignoredProperties);
+
+ assertEquals("Expected order_index to be 0", 0, actualMap.getMap().get("propertyToUpdate")
+ .getOrder());
+ }
+
+ @Test(enabled = ENABLED)
+ public void updatePropertyDefinitionOptionSource() {
+ initConfigDefs("servers[name='OptionSourceTest']", "OptionSourceTest");
+
+ // now check the upgrades
+ PropertyDefinitionSimple prop1 = (PropertyDefinitionSimple) updatedConfigDef.get("prop1");
+ assert prop1 != null;
+ assert prop1.getEnumeratedValues().size() == 0 : "Found an option value. ";
+ PropertyOptionsSource source = prop1.getOptionsSource();
+ assert source != null : "PropertyOptionSource was not persisted";
+ assert source.getFilter() == null : "Assumed filter to be null, but was " + source.getFilter();
+
+ PropertyDefinitionSimple prop2 = (PropertyDefinitionSimple) updatedConfigDef.get("prop2");
+ assert prop2 != null;
+ assert prop2.getEnumeratedValues().size() == 1;
+ assert prop2.getOptionsSource() != null;
+ assert prop2.getOptionsSource().getExpression().equals("*");
+
+ }
+
+ private void initConfigDefs(String path, String configName) {
+ loadAndPersistConfigDefs(path, configName);
+ updateConfigDef();
+ }
+
+ private void loadAndPersistConfigDefs(String path, String configName) {
+ originalConfigDef = loadPluginConfigDefFor(originalDescriptor, path, configName);
+ assertNotNull(originalConfigDef);
+ updatedConfigDef = loadPluginConfigDefFor(updatedDescriptor, path, configName);
+ assertNotNull(updatedConfigDef);
+
+ try {
+ getTransactionManager().begin();
+
+ EntityManager entityMgr = getEntityManager();
+ entityMgr.persist(originalConfigDef);
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ getTransactionManager().rollback();
+ } catch (SystemException e1) {
+ throw new RuntimeException(e1);
+ }
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void updateConfigDef() {
+ ConfigurationMetadataManagerLocal configMetadataMgr = LookupUtil.getConfigurationMetadataManager();
+ // The next line updates originalConfigDef with the content of updatedConfigDef
+ configMetadataMgr.updateConfigurationDefinition(updatedConfigDef, originalConfigDef);
+ }
+
+ private String getPackagePath() {
+ return "/" + getClass().getPackage().getName().replace('.', '/') + "/";
+ }
+
+ private PropertyGroupDefinition findGroup(String name, ConfigurationDefinition configDef) {
+ for (PropertyGroupDefinition groupDef : configDef.getGroupDefinitions()) {
+ if (groupDef.getName().equals(name)) {
+ return groupDef;
+ }
+ }
+ return null;
+ }
+
+ void assertPropertyDefinitionMatches(String msg, PropertyDefinition expected, PropertyDefinition actual) {
+ AssertUtils.assertPropertiesMatch(msg, expected, actual, "id", "configurationDefinition");
+ }
+
+ void assertPropertyDefinitionMatches(String msg, PropertyDefinition expected, PropertyDefinition actual,
+ List<String> ignoredProperties) {
+ AssertUtils.assertPropertiesMatch(msg, expected, actual, ignoredProperties);
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/metadata/test/ContentSourcePluginHandlingTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/metadata/test/ContentSourcePluginHandlingTest.java
new file mode 100644
index 0000000..cb310c9
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/metadata/test/ContentSourcePluginHandlingTest.java
@@ -0,0 +1,200 @@
+/*
+ * 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.enterprise.server.content.metadata.test;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertySimpleType;
+import org.rhq.core.domain.content.ContentSourceType;
+
+/**
+ * Test the handling on Plugin updates / hotdeployments etc.
+ *
+ * @author John Mazzitelli
+ */
+@Test
+public class ContentSourcePluginHandlingTest extends TestBase {
+ @AfterMethod
+ @SuppressWarnings("unchecked")
+ protected void afterMethod() throws Exception {
+ // I tried and tried to get it to work where I create a single tx and just rollback
+ // after the test but I could not get the entity manager/tx used by my SLSBs to be the
+ // same as used in my test. So, I had to just let the SLSB create its own entity manager/tx
+ // and commit. I will clean up the tests here.
+ getTransactionManager().begin();
+
+ EntityManager em = getEntityManager();
+ List<ContentSourceType> list = em.createQuery(
+ "select c from ContentSourceType c where c.name like 'testCSPHT%'").getResultList();
+
+ for (ContentSourceType doomed : list) {
+ em.remove(doomed);
+ }
+
+ getTransactionManager().commit();
+ }
+
+ public void testUpdateContentSourceTypes() throws Throwable {
+ ContentSourceType type1;
+ ContentSourceType type2;
+ ContentSourceType type3;
+ ContentSourceType type4;
+ ConfigurationDefinition def;
+
+ try {
+ registerPlugin("./test/metadata/content-source-update-v1.xml");
+ type1 = getContentSourceType("testCSPHT1");
+ type2 = getContentSourceType("testCSPHT2");
+ type3 = getContentSourceType("testCSPHT3");
+ type4 = getContentSourceType("testCSPHT4");
+
+ assert type1 != null;
+ assert type2 != null;
+ assert type3 == null;
+ assert type4 != null;
+
+ assert type1.getId() > 0;
+ assert type1.getName().equals("testCSPHT1");
+ assert type1.getDisplayName().equals("displayName1");
+ assert type1.getDescription().equals("description1");
+ assert type1.getContentSourceApiClass().equals("org.abc.ApiClass1");
+ def = type1.getContentSourceConfigurationDefinition();
+ assert def.getPropertyDefinitions().size() == 1;
+ assert def.getPropertyDefinitionSimple("prop1").getType() == PropertySimpleType.DIRECTORY;
+ assert def.getPropertyDefinitionSimple("prop1").isRequired() == true;
+
+ assert type2.getId() > 0;
+ assert type2.getName().equals("testCSPHT2");
+ assert type2.getDisplayName().equals("displayName2");
+ assert type2.getDescription().equals("description2");
+ assert type2.getContentSourceApiClass().equals("org.abc.ApiClass2");
+ def = type2.getContentSourceConfigurationDefinition();
+ assert def.getPropertyDefinitions().size() == 1;
+ assert def.getPropertyDefinitionSimple("prop2").getType() == PropertySimpleType.INTEGER;
+ assert def.getPropertyDefinitionSimple("prop2").isRequired() == false;
+
+ assert type4.getId() > 0;
+ assert type4.getName().equals("testCSPHT4");
+ assert type4.getDisplayName().equals("displayName4");
+ assert type4.getDescription().equals("description4");
+ assert type4.getContentSourceApiClass().equals("org.abc.ApiClass4");
+ def = type4.getContentSourceConfigurationDefinition();
+ assert def.getPropertyDefinitions().size() == 1;
+ assert def.getPropertyDefinitionSimple("prop4").getType() == PropertySimpleType.FILE;
+ assert def.getPropertyDefinitionSimple("prop4").isRequired() == false;
+
+ // now hot deploy a new version of that plugin
+ registerPlugin("./test/metadata/content-source-update-v2.xml");
+ getEntityManager().clear();
+ type1 = getContentSourceType("testCSPHT1");
+ type2 = getContentSourceType("testCSPHT2");
+ type3 = getContentSourceType("testCSPHT3");
+ type4 = getContentSourceType("testCSPHT4");
+
+ assert type1 != null;
+ assert type2 == null;
+ assert type3 != null;
+ assert type4 != null;
+
+ assert type1.getId() > 0;
+ assert type1.getName().equals("testCSPHT1");
+ assert type1.getDisplayName().equals("displayName1");
+ assert type1.getDescription().equals("description1");
+ assert type1.getContentSourceApiClass().equals("org.abc.ApiClass1");
+ def = type1.getContentSourceConfigurationDefinition();
+ assert def.getPropertyDefinitions().size() == 1;
+ assert def.getPropertyDefinitionSimple("prop1").getType() == PropertySimpleType.DIRECTORY;
+ assert def.getPropertyDefinitionSimple("prop1").isRequired() == true;
+
+ assert type3.getId() > 0;
+ assert type3.getName().equals("testCSPHT3");
+ assert type3.getDisplayName().equals("displayName3");
+ assert type3.getDescription().equals("description3");
+ assert type3.getContentSourceApiClass().equals("org.abc.ApiClass3");
+ def = type3.getContentSourceConfigurationDefinition();
+ assert def.getPropertyDefinitions().size() == 1;
+ assert def.getPropertyDefinitionSimple("prop3").getType() == PropertySimpleType.STRING;
+ assert def.getPropertyDefinitionSimple("prop3").isRequired() == true;
+
+ assert type4.getId() > 0;
+ assert type4.getName().equals("testCSPHT4");
+ assert type4.getDisplayName().equals("displayName4changed");
+ assert type4.getDescription().equals("description4changed");
+ assert type4.getContentSourceApiClass().equals("org.abc.ApiClass4changed");
+ def = type4.getContentSourceConfigurationDefinition();
+ assert def.getPropertyDefinitions().size() == 2;
+ assert def.getPropertyDefinitionSimple("prop4_1").getType() == PropertySimpleType.INTEGER;
+ assert def.getPropertyDefinitionSimple("prop4_1").isRequired() == false;
+ assert def.getPropertyDefinitionSimple("prop4_2").getType() == PropertySimpleType.BOOLEAN;
+ assert def.getPropertyDefinitionSimple("prop4_2").isRequired() == false;
+
+ // Now try the other way round - our first set of asserts from before should again pass
+ registerPlugin("./test/metadata/content-source-update-v1.xml");
+ type1 = getContentSourceType("testCSPHT1");
+ type2 = getContentSourceType("testCSPHT2");
+ type3 = getContentSourceType("testCSPHT3");
+ type4 = getContentSourceType("testCSPHT4");
+
+ assert type1 != null;
+ assert type2 != null;
+ assert type3 == null;
+ assert type4 != null;
+
+ assert type1.getId() > 0;
+ assert type1.getName().equals("testCSPHT1");
+ assert type1.getDisplayName().equals("displayName1");
+ assert type1.getDescription().equals("description1");
+ assert type1.getContentSourceApiClass().equals("org.abc.ApiClass1");
+ def = type1.getContentSourceConfigurationDefinition();
+ assert def.getPropertyDefinitions().size() == 1;
+ assert def.getPropertyDefinitionSimple("prop1").getType() == PropertySimpleType.DIRECTORY;
+ assert def.getPropertyDefinitionSimple("prop1").isRequired() == true;
+
+ assert type2.getId() > 0;
+ assert type2.getName().equals("testCSPHT2");
+ assert type2.getDisplayName().equals("displayName2");
+ assert type2.getDescription().equals("description2");
+ assert type2.getContentSourceApiClass().equals("org.abc.ApiClass2");
+ def = type2.getContentSourceConfigurationDefinition();
+ assert def.getPropertyDefinitions().size() == 1;
+ assert def.getPropertyDefinitionSimple("prop2").getType() == PropertySimpleType.INTEGER;
+ assert def.getPropertyDefinitionSimple("prop2").isRequired() == false;
+
+ assert type4.getId() > 0;
+ assert type4.getName().equals("testCSPHT4");
+ assert type4.getDisplayName().equals("displayName4");
+ assert type4.getDescription().equals("description4");
+ assert type4.getContentSourceApiClass().equals("org.abc.ApiClass4");
+ def = type4.getContentSourceConfigurationDefinition();
+ assert def.getPropertyDefinitions().size() == 1;
+ assert def.getPropertyDefinitionSimple("prop4").getType() == PropertySimpleType.FILE;
+ assert def.getPropertyDefinitionSimple("prop4").isRequired() == false;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw t;
+ } finally {
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/metadata/test/TestBase.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/metadata/test/TestBase.java
new file mode 100644
index 0000000..45d250f
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/metadata/test/TestBase.java
@@ -0,0 +1,85 @@
+/*
+ * 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.enterprise.server.content.metadata.test;
+
+import java.net.URL;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.Unmarshaller;
+
+import org.testng.annotations.BeforeClass;
+
+import org.rhq.core.domain.content.ContentSourceType;
+import org.rhq.enterprise.server.content.metadata.ContentSourceMetadataManagerLocal;
+import org.rhq.enterprise.server.plugin.pc.content.metadata.ContentSourcePluginMetadataManager;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.content.ContentPluginDescriptorType;
+
+/**
+ * Base class for content metadata tests.
+ */
+public class TestBase extends AbstractEJB3Test {
+ protected ContentSourceMetadataManagerLocal metadataManager;
+
+ @BeforeClass
+ protected void beforeClass() {
+ try {
+ metadataManager = LookupUtil.getContentSourceMetadataManager();
+ } catch (Throwable t) {
+ // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
+ // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+
+ protected ContentSourceType getContentSourceType(String typeName) throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ Query q = em.createNamedQuery(ContentSourceType.QUERY_FIND_BY_NAME_WITH_CONFIG_DEF);
+ ContentSourceType type = (ContentSourceType) q.setParameter("name", typeName).getSingleResult();
+ return type;
+ } catch (NoResultException nre) {
+ return null;
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ protected void registerPlugin(String pathToDescriptor) throws Exception {
+ ContentPluginDescriptorType descriptor = loadPluginDescriptor(pathToDescriptor);
+ ContentSourcePluginMetadataManager mm = new ContentSourcePluginMetadataManager();
+ mm.loadPlugin(descriptor);
+ metadataManager.registerTypes(mm.getAllContentSourceTypes());
+ }
+
+ public ContentPluginDescriptorType loadPluginDescriptor(String descriptorFile) throws Exception {
+ URL descriptorUrl = this.getClass().getClassLoader().getResource(descriptorFile);
+ Unmarshaller unmarshaller = ServerPluginDescriptorUtil.getServerPluginDescriptorUnmarshaller();
+ return (ContentPluginDescriptorType) (((JAXBElement<?>) unmarshaller.unmarshal(descriptorUrl.openStream()))
+ .getValue());
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/AdvisoryManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/AdvisoryManagerBeanTest.java
new file mode 100644
index 0000000..abbd145
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/AdvisoryManagerBeanTest.java
@@ -0,0 +1,149 @@
+package org.rhq.enterprise.server.content.test;
+
+import javax.persistence.EntityManager;
+import javax.transaction.TransactionManager;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.content.Advisory;
+import org.rhq.core.domain.content.AdvisoryCVE;
+import org.rhq.core.domain.content.AdvisoryPackage;
+import org.rhq.core.domain.content.Architecture;
+import org.rhq.core.domain.content.CVE;
+import org.rhq.core.domain.content.Package;
+import org.rhq.core.domain.content.PackageCategory;
+import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.content.AdvisoryManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * @author Pradeep Kilambi
+ */
+public class AdvisoryManagerBeanTest extends AbstractEJB3Test {
+ private final static boolean ENABLED = true;
+ private AdvisoryManagerLocal advManager;
+ private Subject overlord;
+ private PackageType packageType1;
+
+ @BeforeMethod
+ public void setupBeforeMethod() throws Exception {
+ TransactionManager tx = getTransactionManager();
+ tx.begin();
+
+ advManager = LookupUtil.getAdvisoryManagerLocal();
+
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+ }
+
+ @AfterMethod
+ public void tearDownAfterMethod() throws Exception {
+ TransactionManager tx = getTransactionManager();
+ if (tx != null) {
+ tx.rollback();
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void createDeleteAdvisory() throws Exception {
+
+ String advisory = "RHBA-2009:1202-3";
+ String advisoryType = "BugFix Advisory";
+ String synopsis = "synopsis to test advisory creation";
+
+ int id1 = advManager.createAdvisory(overlord, advisory, advisoryType, synopsis).getId();
+
+ Advisory advobject = advManager.getAdvisoryByName(advisory);
+
+ assert advobject != null;
+ assert id1 == advobject.getId();
+ advManager.deleteAdvisoryByAdvId(overlord, advobject.getId());
+ advobject = advManager.getAdvisoryByName(advobject.getAdvisory());
+ assert advobject == null;
+
+ }
+
+ @Test(enabled = ENABLED)
+ public void getCVEFromAdvisoryTest() throws Exception {
+ EntityManager entityManager = getEntityManager();
+
+ String advisory = "RHBA-2009:1202-4";
+ String advisoryType = "BugFix Advisory";
+ String synopsis = "synopsis to test advisory creation";
+
+ Advisory advobject = new Advisory(advisory, advisoryType, synopsis);
+ entityManager.persist(advobject);
+ int id1 = advobject.getId();
+ entityManager.flush();
+
+ CVE cve = advManager.createCVE(overlord, "CAN-2009:1203");
+ AdvisoryCVE advisory_cve = advManager.createAdvisoryCVE(overlord, advobject, cve);
+
+ PageList<AdvisoryCVE> cvelist = advManager.getAdvisoryCVEByAdvId(overlord, id1, PageControl
+ .getUnlimitedInstance());
+
+ assert cvelist != null;
+ assert cvelist.size() != 0;
+ advManager.deleteAdvisoryCVE(overlord, id1);
+ advManager.deleteCVE(overlord, cve.getId());
+ advManager.deleteAdvisoryByAdvId(overlord, advobject.getId());
+ advobject = advManager.getAdvisoryByName(advobject.getAdvisory());
+ assert advobject == null;
+
+ }
+
+ @Test(enabled = ENABLED)
+ public void getPackagesForAdvisoryTest() throws Exception {
+ EntityManager em = getEntityManager();
+
+ String advisory = "RHBA-2009:1202-4";
+ String advisoryType = "BugFix Advisory";
+ String synopsis = "synopsis to test advisory creation";
+
+ Advisory advobject = advManager.createAdvisory(overlord, advisory, advisoryType, synopsis); //new Advisory(advisory, advisoryType, synopsis);
+ int id1 = advobject.getId();
+
+ ResourceType resourceType1 = new ResourceType("platform-" + System.currentTimeMillis(), "TestPlugin",
+ ResourceCategory.PLATFORM, null);
+ em.persist(resourceType1);
+ em.flush();
+
+ Architecture architecture1 = em.find(Architecture.class, 1);
+
+ // Add package types to resource type
+ packageType1 = new PackageType();
+ packageType1.setName("package1-" + System.currentTimeMillis());
+ packageType1.setDescription("");
+ packageType1.setCategory(PackageCategory.DEPLOYABLE);
+ packageType1.setDisplayName("TestResourcePackage");
+ packageType1.setCreationData(true);
+ packageType1.setResourceType(resourceType1);
+ em.persist(packageType1);
+ em.flush();
+ Package package1 = new Package("Package1", packageType1);
+
+ package1.addVersion(new PackageVersion(package1, "1.0.0", architecture1));
+ package1.addVersion(new PackageVersion(package1, "2.0.0", architecture1));
+
+ em.persist(package1);
+ em.flush();
+ //AdvisoryPackage ap = new AdvisoryPackage(advobject, package1);
+ //em.persist(ap);
+
+ AdvisoryPackage ap = advManager.createAdvisoryPackage(overlord, advobject, package1.getVersions().get(0));
+
+ PageList<AdvisoryPackage> pkglist = advManager.findPackageByAdvisory(overlord, id1, PageControl
+ .getUnlimitedInstance());
+ assert pkglist != null;
+ assert pkglist.size() != 0;
+
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentManagerBeanMockTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentManagerBeanMockTest.java
new file mode 100644
index 0000000..70eef9d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentManagerBeanMockTest.java
@@ -0,0 +1,456 @@
+/*
+ * 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.enterprise.server.content.test;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.sql.Blob;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import javax.sql.DataSource;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockObjectFactory;
+import org.testng.Assert;
+import org.testng.IObjectFactory;
+import org.testng.annotations.ObjectFactory;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.content.Architecture;
+import org.rhq.core.domain.content.Package;
+import org.rhq.core.domain.content.PackageBits;
+import org.rhq.core.domain.content.PackageBitsBlob;
+import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.enterprise.server.content.ContentManagerBean;
+import org.rhq.enterprise.server.content.ContentManagerHelper;
+import org.rhq.enterprise.server.content.ContentManagerLocal;
+import org.rhq.enterprise.server.plugin.pc.content.PackageTypeBehavior;
+
+(a)PrepareForTest(ContentManagerHelper.class)
+public class ContentManagerBeanMockTest {
+
+ @ObjectFactory
+ public IObjectFactory getObjectFactory() {
+ return new PowerMockObjectFactory();
+ }
+
+ /*
+ * Test createPackageVersionWithDisplayVersion with the following hypothesis:
+ * 1) There are no existing package version objects in the database
+ * 2) A new package will be created because of (1)
+ * 3) Focal point of the test is the first 10 lines of the method.
+ */
+ @Test
+ @SuppressWarnings("rawtypes")
+ public void testCreatePackageVersion() throws Exception {
+
+ //set all the method call arguments
+ Subject mockSubject = mock(Subject.class);
+ String packageName = "PackageName";
+ int packageTypeID = 1;
+ String version = "PackageVersion";
+ String displayVersion = "PackageDisplayVersion";
+ int architectureId = 2;
+ String sampleContent = "SampleContent";
+ InputStream packageBitStream = new ByteArrayInputStream(sampleContent.getBytes());
+
+ //tell the method story as it happens: mock dependencies and make them
+ //behave in a way to get the method under test to completion.
+ EntityManager mockEntityManager = mock(EntityManager.class);
+
+ Query mockQuery = mock(Query.class);
+ when(mockEntityManager.createNamedQuery(eq(PackageVersion.QUERY_FIND_BY_PACKAGE_VER_ARCH))).thenReturn(
+ mockQuery);
+ List mockList = mock(List.class);
+ when(mockQuery.getResultList()).thenReturn(mockList);
+
+ Architecture mockArchitecture = mock(Architecture.class);
+ when(mockArchitecture.getName()).thenReturn("ArchitectureName");
+ when(mockEntityManager.find(eq(Architecture.class), anyInt())).thenReturn(mockArchitecture);
+
+ PackageType mockPackageType = mock(PackageType.class);
+ when(mockEntityManager.find(eq(PackageType.class), eq(1))).thenReturn(mockPackageType);
+
+ PackageTypeBehavior mockPackageTypeBehavior = mock(PackageTypeBehavior.class);
+ PowerMockito.mockStatic(ContentManagerHelper.class);
+ when(ContentManagerHelper.getPackageTypeBehavior(1)).thenReturn(mockPackageTypeBehavior);
+
+ when(mockEntityManager.createNamedQuery(eq(Architecture.QUERY_FIND_BY_NAME))).thenReturn(mockQuery);
+ when(mockEntityManager.createNamedQuery(eq(Package.QUERY_FIND_BY_NAME_PKG_TYPE_ID))).thenReturn(mockQuery);
+
+ ContentManagerLocal mockContentManager = mock(ContentManagerLocal.class);
+ Package mockPackage = mock(Package.class);
+ when(mockContentManager.persistPackage(isNotNull(Package.class))).thenReturn(mockPackage);
+
+ when(mockEntityManager.find(eq(Package.class), any())).thenReturn(mockPackage);
+ when(mockPackage.getPackageType()).thenReturn(mockPackageType);
+
+ PackageVersion mockPackageVersion = mock(PackageVersion.class);
+ when(mockContentManager.persistPackageVersion(isNotNull(PackageVersion.class)))
+ .thenReturn(mockPackageVersion);
+
+ when(mockEntityManager.find(eq(PackageVersion.class), anyInt())).thenReturn(mockPackageVersion);
+ when(mockPackageVersion.getGeneralPackage()).thenReturn(mockPackage);
+ when(mockPackageVersion.getArchitecture()).thenReturn(mockArchitecture);
+
+ PackageBitsBlob mockPackageBitsBlob = mock(PackageBitsBlob.class);
+ when(mockEntityManager.find(eq(PackageBitsBlob.class), anyInt())).thenReturn(mockPackageBitsBlob);
+
+ PackageBits mockBits = mock(PackageBits.class);
+ when(mockEntityManager.find(eq(PackageBits.class), anyInt())).thenReturn(mockBits);
+
+ DataSource mockDataSource = mock(DataSource.class);
+ Connection mockConnection = mock(Connection.class);
+ when(mockDataSource.getConnection()).thenReturn(mockConnection);
+ PreparedStatement mockPreparedStatement1 = mock(PreparedStatement.class);
+ when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement1);
+ ResultSet mockResultSet = mock(ResultSet.class);
+ when(mockPreparedStatement1.executeQuery()).thenReturn(mockResultSet);
+ when(mockResultSet.next()).thenReturn(true, false);
+ Blob mockBlob = mock(Blob.class);
+ when(mockResultSet.getBlob(anyInt())).thenReturn(mockBlob);
+ OutputStream mockOutputStream = mock(OutputStream.class);
+ when(mockBlob.setBinaryStream(anyLong())).thenReturn(mockOutputStream);
+
+ //create object to test and inject required dependencies
+ ContentManagerBean objectUnderTest = new ContentManagerBean();
+ Field[] fields = ContentManagerBean.class.getDeclaredFields();
+
+ for (Field field : fields) {
+ if (field.getName().equals("entityManager")) {
+ field.setAccessible(true);
+ field.set(objectUnderTest, mockEntityManager);
+ field.setAccessible(false);
+ }
+ else if (field.getName().equals("contentManager")) {
+ field.setAccessible(true);
+ field.set(objectUnderTest, mockContentManager);
+ field.setAccessible(false);
+ }
+ else if (field.getName().equals("dataSource")) {
+ field.setAccessible(true);
+ field.set(objectUnderTest, mockDataSource);
+ field.setAccessible(false);
+ }
+ }
+
+ //run the code to be tested
+ PackageVersion result = objectUnderTest.createPackageVersionWithDisplayVersion(mockSubject, packageName,
+ packageTypeID, version, displayVersion, architectureId, packageBitStream);
+
+ //verify the results (Assert and Mock Verification)
+ verify(mockList, times(2)).size();
+ verify(mockList, never()).get(anyInt());
+
+ verify(result, times(2)).setPackageBits(any(PackageBits.class));
+ MessageDigestGenerator digest = new MessageDigestGenerator(MessageDigestGenerator.SHA_256);
+ verify(result).setSHA256(digest.calcDigestString(sampleContent));
+ verify(result).setFileSize((long) sampleContent.getBytes().length);
+ verify(result).setDisplayVersion(displayVersion);
+ }
+
+ /*
+ * Test createPackageVersionWithDisplayVersion with the following hypothesis:
+ * 1) There is an existing package
+ * 2) No package will be created because of (1)
+ * 3) Focal point of the test is the first 10 lines of the method.
+ * 4) No updates required to the packageVersion retrieved because input display version is null.
+ */
+ @Test
+ @SuppressWarnings("rawtypes")
+ public void testCreatePackageVersionExistingPackage() throws Exception {
+
+ //set all the method call arguments
+ Subject mockSubject = mock(Subject.class);
+ String packageName = "PackageName";
+ int packageTypeID = 1;
+ String version = "PackageVersion";
+ String displayVersion = null;
+ int architectureId = 2;
+ String sampleContent = "SampleContent";
+ InputStream packageBitStream = new ByteArrayInputStream(sampleContent.getBytes());
+
+ //tell the method story as it happens: mock dependencies and make them
+ //behave in a way to get the method under test to completion.
+ EntityManager mockEntityManager = mock(EntityManager.class);
+
+ Query mockQuery = mock(Query.class);
+ when(mockEntityManager.createNamedQuery(eq(PackageVersion.QUERY_FIND_BY_PACKAGE_VER_ARCH))).thenReturn(
+ mockQuery);
+ List mockList = mock(List.class);
+ when(mockQuery.getResultList()).thenReturn(mockList);
+ when(mockList.size()).thenReturn(1);
+ PackageVersion mockPackageVersion = mock(PackageVersion.class);
+ when(mockList.get(eq(0))).thenReturn(mockPackageVersion);
+
+ //create object to test and inject required dependencies
+ ContentManagerBean objectUnderTest = new ContentManagerBean();
+ Field[] fields = ContentManagerBean.class.getDeclaredFields();
+
+ for (Field field : fields) {
+ if (field.getName().equals("entityManager")) {
+ field.setAccessible(true);
+ field.set(objectUnderTest, mockEntityManager);
+ field.setAccessible(false);
+ }
+ }
+
+ //run the code to be tested
+ PackageVersion result = objectUnderTest.createPackageVersionWithDisplayVersion(mockSubject, packageName,
+ packageTypeID, version, displayVersion, architectureId, packageBitStream);
+
+ //verify the results (Assert and Mock Verification)
+ verify(mockList, times(1)).size();
+ verify(mockList, times(1)).get(eq(0));
+ verify(mockEntityManager, times(1)).createNamedQuery(anyString());
+
+ Assert.assertEquals(mockPackageVersion, result);
+ }
+
+ /*
+ * Test createPackageVersionWithDisplayVersion with the following hypothesis:
+ * 1) There is an existing package
+ * 2) No package will be created because of (1)
+ * 3) Focal point of the test is the first 10 lines of the method.
+ * 4) No updates required to the packageVersion retrieved because input display version is empty after trimming.
+ */
+ @Test
+ @SuppressWarnings("rawtypes")
+ public void testCreatePackageVersionExistingPackageEmptyDisplayVersion() throws Exception {
+
+ //set all the method call arguments
+ Subject mockSubject = mock(Subject.class);
+ String packageName = "PackageName";
+ int packageTypeID = 1;
+ String version = "PackageVersion";
+ String displayVersion = " ";
+ int architectureId = 2;
+ String sampleContent = "SampleContent";
+ InputStream packageBitStream = new ByteArrayInputStream(sampleContent.getBytes());
+
+ //tell the method story as it happens: mock dependencies and make them
+ //behave in a way to get the method under test to completion.
+ EntityManager mockEntityManager = mock(EntityManager.class);
+
+ Query mockQuery = mock(Query.class);
+ when(mockEntityManager.createNamedQuery(eq(PackageVersion.QUERY_FIND_BY_PACKAGE_VER_ARCH))).thenReturn(
+ mockQuery);
+ List mockList = mock(List.class);
+ when(mockQuery.getResultList()).thenReturn(mockList);
+ when(mockList.size()).thenReturn(1);
+ PackageVersion mockPackageVersion = mock(PackageVersion.class);
+ when(mockList.get(eq(0))).thenReturn(mockPackageVersion);
+
+ //create object to test and inject required dependencies
+ ContentManagerBean objectUnderTest = new ContentManagerBean();
+ Field[] fields = ContentManagerBean.class.getDeclaredFields();
+
+ for (Field field : fields) {
+ if (field.getName().equals("entityManager")) {
+ field.setAccessible(true);
+ field.set(objectUnderTest, mockEntityManager);
+ field.setAccessible(false);
+ }
+ }
+
+ //run the code to be tested
+ PackageVersion result = objectUnderTest.createPackageVersionWithDisplayVersion(mockSubject, packageName,
+ packageTypeID, version, displayVersion, architectureId, packageBitStream);
+
+ //verify the results (Assert and Mock Verification)
+ verify(mockList, times(1)).size();
+ verify(mockList, times(1)).get(eq(0));
+ verify(mockEntityManager, times(1)).createNamedQuery(anyString());
+
+ Assert.assertEquals(mockPackageVersion, result);
+ }
+
+ /*
+ * Test createPackageVersionWithDisplayVersion with the following hypothesis:
+ * 1) There are two existing package version objects stored in the database
+ * 2) Only the first package version is ever touched by this method
+ * 2) No package will be created because of (1)
+ * 3) Focal point of the test is the first 10 lines of the method.
+ * 4) No updates required to the packageVersion retrieved because input display version is empty after trimming.
+ */
+ @Test
+ @SuppressWarnings("rawtypes")
+ public void testCreatePackageVersionExistingPackagePickOnlyFirst() throws Exception {
+
+ //set all the method call arguments
+ Subject mockSubject = mock(Subject.class);
+ String packageName = "PackageName";
+ int packageTypeID = 1;
+ String version = "PackageVersion";
+ String displayVersion = " ";
+ int architectureId = 2;
+ String sampleContent = "SampleContent";
+ InputStream packageBitStream = new ByteArrayInputStream(sampleContent.getBytes());
+
+ //tell the method story as it happens: mock dependencies and make them
+ //behave in a way to get the method under test to completion.
+ EntityManager mockEntityManager = mock(EntityManager.class);
+
+ Query mockQuery = mock(Query.class);
+ when(mockEntityManager.createNamedQuery(eq(PackageVersion.QUERY_FIND_BY_PACKAGE_VER_ARCH))).thenReturn(
+ mockQuery);
+ List mockList = mock(List.class);
+ when(mockQuery.getResultList()).thenReturn(mockList);
+ when(mockList.size()).thenReturn(2);
+ PackageVersion mockPackageVersion = mock(PackageVersion.class);
+ when(mockList.get(eq(0))).thenReturn(mockPackageVersion);
+
+ //create object to test and inject required dependencies
+ ContentManagerBean objectUnderTest = new ContentManagerBean();
+ Field[] fields = ContentManagerBean.class.getDeclaredFields();
+
+ for (Field field : fields) {
+ if (field.getName().equals("entityManager")) {
+ field.setAccessible(true);
+ field.set(objectUnderTest, mockEntityManager);
+ field.setAccessible(false);
+ }
+ }
+
+ //run the code to be tested
+ PackageVersion result = objectUnderTest.createPackageVersionWithDisplayVersion(mockSubject, packageName,
+ packageTypeID, version, displayVersion, architectureId, packageBitStream);
+
+ //verify the results (Assert and Mock Verification)
+ verify(mockList, times(1)).size();
+ verify(mockList, times(1)).get(eq(0));
+ verify(mockList, never()).get(eq(1));
+
+ verify(mockEntityManager, times(1)).createNamedQuery(anyString());
+
+ Assert.assertEquals(mockPackageVersion, result);
+ }
+
+ /*
+ * Test createPackageVersionWithDisplayVersion with the following hypothesis:
+ * 1) There is an existing package
+ * 2) No package will be created because of (1)
+ * 3) Focal point of the test is the first 10 lines of the method.
+ * 4) Updates required to the packageVersion because display version needs to be updated.
+ */
+ @Test
+ @SuppressWarnings("rawtypes")
+ public void testCreatePackageVersionExistingPackageUpdateDisplayVersion() throws Exception {
+
+ //set all the method call arguments
+ Subject mockSubject = mock(Subject.class);
+ String packageName = "PackageName";
+ int packageTypeID = 1;
+ String version = "PackageVersion";
+ String displayVersion = "PackageDisplayVersion";
+ int architectureId = 2;
+ String sampleContent = "SampleContent";
+ InputStream packageBitStream = new ByteArrayInputStream(sampleContent.getBytes());
+
+ //tell the method story as it happens: mock dependencies and make them
+ //behave in a way to get the method under test to completion.
+ EntityManager mockEntityManager = mock(EntityManager.class);
+
+ Query mockQuery = mock(Query.class);
+ when(mockEntityManager.createNamedQuery(eq(PackageVersion.QUERY_FIND_BY_PACKAGE_VER_ARCH))).thenReturn(
+ mockQuery);
+ List mockList = mock(List.class);
+ when(mockQuery.getResultList()).thenReturn(mockList);
+ when(mockList.size()).thenReturn(1);
+ final PackageVersion mockPackageVersion = mock(PackageVersion.class);
+ when(mockList.get(eq(0))).thenReturn(mockPackageVersion);
+
+ when(mockPackageVersion.getId()).thenReturn(0);
+ ContentManagerLocal mockContentManager = mock(ContentManagerLocal.class);
+ when(mockContentManager.persistPackageVersion(any(PackageVersion.class))).thenAnswer(
+ new Answer<PackageVersion>() {
+ public PackageVersion answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ return (PackageVersion) args[0];
+ }
+ });
+
+ when(mockEntityManager.find(eq(PackageVersion.class), eq(0))).thenAnswer(new Answer<PackageVersion>() {
+ public PackageVersion answer(InvocationOnMock invocation) throws Throwable {
+ return mockPackageVersion;
+ }
+ });
+
+ Package mockPackage = mock(Package.class);
+ when(mockPackageVersion.getGeneralPackage()).thenReturn(mockPackage);
+ Architecture mockArchitecture = mock(Architecture.class);
+ when(mockPackageVersion.getArchitecture()).thenReturn(mockArchitecture);
+ when(mockPackageVersion.getExtraProperties()).thenReturn(null);
+
+ //create object to test and inject required dependencies
+ ContentManagerBean objectUnderTest = new ContentManagerBean();
+ Field[] fields = ContentManagerBean.class.getDeclaredFields();
+
+ for (Field field : fields) {
+ if (field.getName().equals("entityManager")) {
+ field.setAccessible(true);
+ field.set(objectUnderTest, mockEntityManager);
+ field.setAccessible(false);
+ }
+ else if (field.getName().equals("contentManager")) {
+ field.setAccessible(true);
+ field.set(objectUnderTest, mockContentManager);
+ field.setAccessible(false);
+ }
+ }
+
+ //run the code to be tested
+ PackageVersion result = objectUnderTest.createPackageVersionWithDisplayVersion(mockSubject, packageName,
+ packageTypeID, version, displayVersion, architectureId, packageBitStream);
+
+ //verify the results (Assert and Mock Verification)
+ verify(mockList, times(1)).size();
+ verify(mockList, times(1)).get(eq(0));
+ verify(mockEntityManager, times(1)).createNamedQuery(anyString());
+
+ verify(mockPackageVersion, times(1)).setDisplayVersion(displayVersion);
+
+ Assert.assertEquals(mockPackageVersion, result);
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentManagerBeanTest.java
new file mode 100644
index 0000000..e201328
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentManagerBeanTest.java
@@ -0,0 +1,1720 @@
+/*
+ * 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.enterprise.server.content.test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.agent.PluginContainerException;
+import org.rhq.core.clientapi.agent.content.ContentAgentService;
+import org.rhq.core.clientapi.server.content.ContentDiscoveryReport;
+import org.rhq.core.clientapi.server.content.DeletePackagesRequest;
+import org.rhq.core.clientapi.server.content.DeployPackagesRequest;
+import org.rhq.core.clientapi.server.content.RetrievePackageBitsRequest;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.content.Architecture;
+import org.rhq.core.domain.content.ContentRequestStatus;
+import org.rhq.core.domain.content.ContentRequestType;
+import org.rhq.core.domain.content.ContentServiceRequest;
+import org.rhq.core.domain.content.InstalledPackage;
+import org.rhq.core.domain.content.InstalledPackageHistory;
+import org.rhq.core.domain.content.InstalledPackageHistoryStatus;
+import org.rhq.core.domain.content.Package;
+import org.rhq.core.domain.content.PackageCategory;
+import org.rhq.core.domain.content.PackageDetailsKey;
+import org.rhq.core.domain.content.PackageInstallationStep;
+import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.domain.content.transfer.ContentResponseResult;
+import org.rhq.core.domain.content.transfer.DeployIndividualPackageResponse;
+import org.rhq.core.domain.content.transfer.DeployPackageStep;
+import org.rhq.core.domain.content.transfer.DeployPackagesResponse;
+import org.rhq.core.domain.content.transfer.RemoveIndividualPackageResponse;
+import org.rhq.core.domain.content.transfer.RemovePackagesResponse;
+import org.rhq.core.domain.content.transfer.ResourcePackageDetails;
+import org.rhq.core.domain.criteria.PackageVersionCriteria;
+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.domain.util.PageList;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.content.ContentManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.ResourceTreeHelper;
+
+@Test
+public class ContentManagerBeanTest extends AbstractEJB3Test {
+ // Attributes --------------------------------------------
+
+ private static final boolean ENABLE_TESTS = false;
+
+ /**
+ * ContentAgentService method implementations should synchronize on this to allow the test method to pause before
+ * the reponse is sent and check the state of the server.
+ */
+ private static final Object responseLock = new Object();
+
+ private ContentManagerLocal contentManager;
+ private SubjectManagerLocal subjectManager;
+
+ private MockContentAgentService contentAgentService = new MockContentAgentService();
+
+ private PackageType packageType1;
+ private PackageType packageType2;
+ private PackageType packageType3;
+ private PackageType packageType4;
+
+ /**
+ * Type: packageType1 Versions: 2
+ */
+ private Package package1;
+
+ /**
+ * Type: packageType2 Versions: 2
+ */
+ private Package package2;
+
+ /**
+ * Type: packageType3 Versions: 1
+ */
+ private Package package3;
+
+ /**
+ * Type: packageType4 Versions: 2 Installed: Version 1
+ */
+ private Package package4;
+
+ /**
+ * Type: packageType4 Versions: 1 Installed: Version 1
+ */
+ private Package package5;
+
+ private InstalledPackage installedPackage1;
+ private InstalledPackage installedPackage2;
+
+ /**
+ * Architecture used in the creation of all sample package versions.
+ */
+ private Architecture architecture1;
+
+ /**
+ * Extra architecture used in tests.
+ */
+ private Architecture architecture2;
+
+ private List<DeployPackageStep> stepResults;
+
+ private ResourceType resourceType1;
+ private Resource resource1;
+
+ // Setup --------------------------------------------
+
+ @BeforeClass
+ public void setupBeforeClass() throws Exception {
+ contentManager = LookupUtil.getContentManager();
+ subjectManager = LookupUtil.getSubjectManager();
+
+ populateResponseSteps();
+ }
+
+ @BeforeMethod
+ public void setupBeforeMethod() throws Exception {
+ setupTestEnvironment();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDownAfterMethod() throws Exception {
+ tearDownTestEnvironment();
+ }
+
+ // Test Cases --------------------------------------------
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testPersistSafely() throws Throwable {
+
+ final String pkgName = "testPersistSafelyPackage";
+ final String pvName = "testPersistSafelyPackageVersion version";
+ final PackageType pkgType = packageType1;
+ final Architecture arch = architecture1;
+
+ // these will not have any JPA stubs inside them (i.e. no lazy exceptions will occur with these)
+ Package pkgPojo = new Package(pkgName, pkgType);
+ PackageVersion pvPojo = new PackageVersion(pkgPojo, pvName, arch);
+ Configuration configPojo = new Configuration();
+ configPojo.put(new PropertySimple("one", "two"));
+ pvPojo.setExtraProperties(configPojo);
+
+ Package persistedPkg = null;
+ PackageVersion persistedPV = null;
+
+ try {
+ // create the entities that we will pass to the persist methods - these will get altered
+ Package pkg = new Package(pkgName, pkgType);
+ PackageVersion pv = new PackageVersion(pkg, pvName, arch);
+ pv.setExtraProperties(configPojo);
+
+ persistedPkg = this.contentManager.persistOrMergePackageSafely(pkg);
+ assert persistedPkg != null;
+ assert persistedPkg.getId() > 0;
+ assert persistedPkg.equals(pkgPojo) : "not equal: " + persistedPkg + "<>" + pkgPojo;
+
+ persistedPV = this.contentManager.persistOrMergePackageVersionSafely(pv);
+ assert persistedPV != null;
+ assert persistedPV.getId() > 0;
+ assert persistedPV.equals(pvPojo) : "not equal: " + persistedPV + "<>" + pvPojo;
+ assert persistedPV.getExtraProperties() != null;
+ assert persistedPV.getExtraProperties().getId() > 0;
+ assert persistedPV.getExtraProperties().getSimple("one").getStringValue().equals("two");
+
+ // remember their new IDs - we want to make sure the same IDs are reused later
+ int pkgId = persistedPkg.getId();
+ int pvId = persistedPV.getId();
+ int configId = persistedPV.getExtraProperties().getId();
+ int propId = persistedPV.getExtraProperties().getSimple("one").getId();
+
+ // we've persisted them, let's make sure our "safely" methods still work
+ // create new entities that we will pass to the persist methods - these will get altered
+ pkg = new Package(pkgName, pkgType);
+ pv = new PackageVersion(pkg, pvName, arch);
+ pv.setExtraProperties(configPojo);
+
+ persistedPkg = this.contentManager.persistOrMergePackageSafely(pkg);
+ assert persistedPkg != null;
+ assert persistedPkg.getId() > 0;
+ assert persistedPkg.equals(pkgPojo) : "not equal: " + persistedPkg + "<>" + pkgPojo;
+
+ persistedPV = this.contentManager.persistOrMergePackageVersionSafely(pv);
+ assert persistedPV != null;
+ assert persistedPV.getId() > 0;
+ assert persistedPV.equals(pvPojo) : "not equal: " + persistedPV + "<>" + pvPojo;
+ assert persistedPV.getExtraProperties() != null;
+ assert persistedPV.getExtraProperties().getId() > 0;
+ assert persistedPV.getExtraProperties().getSimple("one").getStringValue().equals("two");
+
+ // make sure we merged the existing entities - we should not have created new ones
+ assert pkgId == persistedPkg.getId();
+ assert pvId == persistedPV.getId();
+ assert configId == persistedPV.getExtraProperties().getId();
+ assert propId == persistedPV.getExtraProperties().getSimple("one").getId();
+
+ // now pass in existing entities with non-zero IDs
+ pkg = new Package(pkgName, pkgType);
+ pv = new PackageVersion(pkg, pvName, arch);
+ pv.setExtraProperties(configPojo);
+ pkg.setId(persistedPkg.getId());
+ pv.setId(persistedPV.getId());
+
+ persistedPkg = this.contentManager.persistOrMergePackageSafely(pkg);
+ assert persistedPkg != null;
+ assert persistedPkg.getId() > 0;
+ assert persistedPkg.equals(pkgPojo) : "not equal: " + persistedPkg + "<>" + pkgPojo;
+
+ persistedPV = this.contentManager.persistOrMergePackageVersionSafely(pv);
+ assert persistedPV != null;
+ assert persistedPV.getId() > 0;
+ assert persistedPV.equals(pvPojo) : "not equal: " + persistedPV + "<>" + pvPojo;
+ assert persistedPV.getExtraProperties() != null;
+ assert persistedPV.getExtraProperties().getId() > 0;
+ assert persistedPV.getExtraProperties().getSimple("one").getStringValue().equals("two");
+
+ // make sure we merged the existing entities - we should not have created new ones
+ assert pkgId == persistedPkg.getId();
+ assert pvId == persistedPV.getId();
+ assert configId == persistedPV.getExtraProperties().getId();
+ assert propId == persistedPV.getExtraProperties().getSimple("one").getId();
+
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw t;
+ } finally {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ if (persistedPV != null && persistedPV.getId() > 0) {
+ persistedPV = em.find(PackageVersion.class, persistedPV.getId());
+ em.remove(persistedPV);
+ }
+ if (persistedPkg != null && persistedPkg.getId() > 0) {
+ persistedPkg = em.find(Package.class, persistedPkg.getId());
+ em.remove(persistedPkg);
+ }
+ } finally {
+ getTransactionManager().commit();
+ em.close();
+ }
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test(enabled = ENABLE_TESTS)
+ public void testInventoryMerge() throws Exception {
+ // Setup --------------------------------------------
+ ContentDiscoveryReport report = new ContentDiscoveryReport();
+ report.setResourceId(resource1.getId());
+
+ // Package version that exists
+ PackageDetailsKey key1 = new PackageDetailsKey(package1.getName(), "2.0.0",
+ package1.getPackageType().getName(), architecture1.getName());
+ ResourcePackageDetails package1 = new ResourcePackageDetails(key1);
+
+ report.addDeployedPackage(package1);
+
+ // Package version number that doesn't exist
+ PackageDetailsKey key2 = new PackageDetailsKey(package2.getName(), "3.0.0", this.package2.getPackageType()
+ .getName(), architecture1.getName());
+ ResourcePackageDetails package2 = new ResourcePackageDetails(key2);
+
+ report.addDeployedPackage(package2);
+
+ // Package with same version number but different architecture
+ PackageDetailsKey key3 = new PackageDetailsKey(package3.getName(), "1.0.0", this.package3.getPackageType()
+ .getName(), architecture2.getName());
+ ResourcePackageDetails package3 = new ResourcePackageDetails(key3);
+
+ report.addDeployedPackage(package3);
+
+ // Package where entire package does not exist
+ PackageDetailsKey key4 = new PackageDetailsKey("PackageX", "1.0.0", packageType4.getName(),
+ architecture1.getName());
+ ResourcePackageDetails package4 = new ResourcePackageDetails(key4);
+
+ // Fully populate this version to make sure the translation from details -> domain model works
+ // Don't need to do this on all packages
+ package4.setClassification("Package X1 Category");
+ package4.setDisplayName("Package X1 Display Name");
+ package4.setDisplayVersion("Package X1 Display Version");
+ package4.setFileCreatedDate(System.currentTimeMillis());
+ package4.setFileName("package4.tar.gz");
+ package4.setFileSize(1000L);
+ package4.setLicenseName("GPL");
+ package4.setLicenseVersion("2");
+ package4.setLongDescription("Package X1 Long Description");
+ package4.setMD5("7bf1adec93fdb899aeca248a38603d58");
+ package4.setSHA256("935f051cab5240b979bba87ce58183d50f592a962202ca683f12a7966414fe6c");
+ package4.setShortDescription("Package X1 Short Description");
+
+ String package4Metadata = "Package X1 Metadata";
+ package4.setMetadata(package4Metadata.getBytes());
+
+ Configuration package4DeploymentConfiguration = new Configuration();
+ package4DeploymentConfiguration.put(new PropertySimple("property1", "value1"));
+ package4.setDeploymentTimeConfiguration(package4DeploymentConfiguration);
+
+ Configuration package4ExtraProperties = new Configuration();
+ package4ExtraProperties.put(new PropertySimple("property2", "value2"));
+ package4.setExtraProperties(package4ExtraProperties);
+
+ report.addDeployedPackage(package4);
+
+ // Upgraded package to package version known to the system
+ PackageDetailsKey key5 = new PackageDetailsKey("Package4", "2.0.0", this.package4.getPackageType().getName(),
+ architecture1.getName());
+ ResourcePackageDetails package5 = new ResourcePackageDetails(key5);
+
+ report.addDeployedPackage(package5);
+
+ // In most cases, the same package report will come back from the agent (i.e. no changes). This is a simple way
+ // of testing that to ensure we're not messing up and adding multiple installed packages.
+ for (int ii = 0; ii < 2; ii++) {
+ // Test --------------------------------------------
+ contentManager.mergeDiscoveredPackages(report);
+
+ // Verify --------------------------------------------
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ // Simple count checks
+ Query installedPackageQuery = em.createNamedQuery(InstalledPackage.QUERY_FIND_BY_RESOURCE_ID);
+ installedPackageQuery.setParameter("resourceId", resource1.getId());
+ List<InstalledPackage> installedPackages = installedPackageQuery.getResultList();
+ assert installedPackages.size() == 5 : "Incorrect number of packages discovered. Expected 5, Found "
+ + installedPackages.size();
+
+ // PackageX didn't already exist in the system, so ensure it was created and populated correctly from our
+ // discovered package
+ Query packageXQuery = em.createNamedQuery(Package.QUERY_FIND_BY_NAME_PKG_TYPE_ID);
+ packageXQuery.setParameter("name", "PackageX");
+ packageXQuery.setParameter("packageTypeId", packageType4.getId());
+ Package packageX = (Package) packageXQuery.getSingleResult();
+
+ assert packageX.getName().equals("PackageX") : "Package name not specified on created package";
+ assert packageX.getPackageType().equals(packageType4) : "Package type incorrect on created package. Expected: "
+ + packageType4 + ", Found: " + packageX.getPackageType();
+
+ Query packageVersionQuery = em.createNamedQuery(PackageVersion.QUERY_FIND_BY_PACKAGE_ID);
+ packageVersionQuery.setParameter("packageId", packageX.getId());
+ List<PackageVersion> packageVersions = packageVersionQuery.getResultList();
+
+ assert packageVersions.size() == 1 : "Incorrect number of versions for package. Expected: 1, Found: "
+ + packageVersions.size();
+
+ PackageVersion packageVersionX = packageVersions.get(0);
+
+ assert packageVersionX.getArchitecture().equals(architecture1) : "Incorrect architecture on package version. Expected: "
+ + architecture1 + ", Found: " + packageVersionX.getArchitecture();
+ assert packageVersionX.getDisplayName().equals(package4.getDisplayName()) : "Incorrect display name on package version. Expected: "
+ + package4.getDisplayName() + ", Found: " + packageVersionX.getDisplayName();
+ assert packageVersionX.getDisplayVersion().equals(package4.getDisplayVersion()) : "Incorrect display version on package version. Expected: "
+ + package4.getDisplayVersion() + ", Found: " + packageVersionX.getDisplayVersion();
+ // assert packageVersionX.getFileCreatedDate().equals(package4.getFileCreatedDate()) : "Incorrect file created date on package version. Expected: " + package4.getFileCreatedDate() + ", Found: " + packageVersionX.getFileCreatedDate();
+ assert packageVersionX.getFileName().equals(package4.getFileName()) : "Incorrect file name on package version. Expected: "
+ + package4.getFileName() + ", Found: " + packageVersionX.getFileName();
+ assert packageVersionX.getFileSize().equals(package4.getFileSize()) : "Incorrect file size on package version. Expected: "
+ + package4.getFileSize() + ", Found: " + packageVersionX.getFileSize();
+ assert packageVersionX.getLicenseName().equals(package4.getLicenseName()) : "Incorrect license name on package version. Expected: "
+ + package4.getLicenseName() + ", Found: " + packageVersionX.getLicenseName();
+ assert packageVersionX.getLicenseVersion().equals(package4.getLicenseVersion()) : "Incorrect license version on package version. Expected: "
+ + package4.getLicenseVersion() + ", Found: " + packageVersionX.getLicenseVersion();
+ assert packageVersionX.getLongDescription().equals(package4.getLongDescription()) : "Incorrect long description on package version. Expected: "
+ + package4.getLongDescription() + ", Found: " + packageVersionX.getLongDescription();
+ assert packageVersionX.getMD5().equals(package4.getMD5()) : "Incorrect MD5 on package version. Expected: "
+ + package4.getMD5() + ", Found: " + packageVersionX.getMD5();
+ assert Arrays.equals(packageVersionX.getMetadata(), package4.getMetadata()) : "Incorrect metadata on package version.";
+ assert packageVersionX.getPackageBits() == null : "Non-null package bits specified for package version: "
+ + packageVersionX.getPackageBits();
+ assert packageVersionX.getSHA256().equals(package4.getSHA256()) : "Incorrect SHA256 for package version. Expected: "
+ + package4.getSHA256() + ", Found: " + packageVersionX.getSHA256();
+ assert packageVersionX.getShortDescription().equals(package4.getShortDescription()) : "Incorrect short description. Expected: "
+ + package4.getShortDescription() + ", Found: " + packageVersionX.getShortDescription();
+ assert packageVersionX.getVersion().equals(package4.getVersion()) : "Incorrect version. Expected: "
+ + package4.getVersion() + ", Found: " + packageVersionX.getVersion();
+
+ Configuration extraProperties = packageVersionX.getExtraProperties();
+ assert extraProperties != null : "Package version extra properties not persisted.";
+ assert extraProperties.getSimple("property2") != null : "Properties inside of extra properties were missing";
+ assert extraProperties.getSimple("property2").getStringValue().equals("value2") : "Incorrect value of property2";
+
+ // Load the installed package for the above package to check for the rest of the properties
+ Query packageXInstalledPackageQuery = em
+ .createNamedQuery(InstalledPackage.QUERY_FIND_BY_RESOURCE_ID_AND_PKG_VER_ID);
+ packageXInstalledPackageQuery.setParameter("resourceId", resource1.getId());
+ packageXInstalledPackageQuery.setParameter("packageVersionId", packageVersionX.getId());
+ InstalledPackage packageXInstalledPackage = (InstalledPackage) packageXInstalledPackageQuery
+ .getSingleResult();
+
+ assert packageXInstalledPackage != null;
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+ }
+
+ // @Test(enabled = ENABLE_TESTS)
+ @Test(enabled = true)
+ public void testSuccessfulDeployPackages() throws Exception {
+ // Setup --------------------------------------------
+ Subject overlord = subjectManager.getOverlord();
+
+ Set<ResourcePackageDetails> installUs = new HashSet<ResourcePackageDetails>(2);
+
+ // Package 1, Version 2 with configuration values
+ PackageVersion packageVersion1 = package1.getVersions().get(0);
+ Configuration deploymentConfiguration1 = new Configuration();
+ deploymentConfiguration1.put(new PropertySimple("property1", "value1"));
+
+ PackageDetailsKey key1 = new PackageDetailsKey(package1.getName(), packageVersion1.getVersion(), package1
+ .getPackageType().getName(), packageVersion1.getArchitecture().getName());
+ ResourcePackageDetails packageDetails1 = new ResourcePackageDetails(key1);
+ packageDetails1.setDeploymentTimeConfiguration(deploymentConfiguration1);
+
+ installUs.add(packageDetails1);
+
+ // Package 2, Version 1 (intentionally older version) with no configuration values
+ PackageVersion packageVersion2 = package2.getVersions().get(0);
+
+ PackageDetailsKey key2 = new PackageDetailsKey(package2.getName(), packageVersion2.getVersion(), package2
+ .getPackageType().getName(), packageVersion2.getArchitecture().getName());
+ ResourcePackageDetails packageDetails2 = new ResourcePackageDetails(key2);
+
+ installUs.add(packageDetails2);
+
+ // Make sure the mock is configured to return a success
+ this.contentAgentService.setResponseReturnStatus(ContentResponseResult.SUCCESS);
+ this.contentAgentService.setThrowError(false);
+ this.contentAgentService.setReturnIndividualResponses(true);
+
+ String notes = "Test package deployment";
+
+ // Test --------------------------------------------
+
+ // Perform the deploy while locking the agent service. This allows us to check the state after the request
+ // is sent to the agent but before the agent has replied.
+ synchronized (responseLock) {
+ contentManager.deployPackages(overlord, resource1.getId(), installUs, notes);
+
+ // Check to see if the request and installed package were created and have the right status
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ // Content request
+ Query query = em.createNamedQuery(ContentServiceRequest.QUERY_FIND_BY_RESOURCE);
+ query.setParameter("resourceId", resource1.getId());
+
+ List<?> results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of content service requests. Expected: 1, Found: "
+ + results.size();
+
+ ContentServiceRequest request = (ContentServiceRequest) results.get(0);
+ assert request.getContentRequestType() == ContentRequestType.DEPLOY : "Request type incorrect. Expected: DEPLOY, Found: "
+ + request.getContentRequestType();
+ assert request.getStatus() == ContentRequestStatus.IN_PROGRESS : "Request status incorrect. Expected: IN_PROGRESS, Found: "
+ + request.getStatus();
+ assert request.getInstalledPackageHistory().size() == 2 : "Incorrect number of installed packages attached to request. Expected: 2, Found: "
+ + request.getInstalledPackageHistory().size();
+ assert request.getNotes() != null : "Null notes found";
+ assert request.getNotes().equals(notes) : "Incorrect notes found: " + request.getNotes();
+
+ // Verify a history entry has been added for each package in the request
+ Set<InstalledPackageHistory> history = request.getInstalledPackageHistory();
+
+ assert history.size() == 2 : "Incorrect number of history entries on request. Expected: 2, Found: "
+ + history.size();
+
+ for (InstalledPackageHistory historyEntry : history) {
+ assert historyEntry.getStatus() == InstalledPackageHistoryStatus.BEING_INSTALLED : "Incorrect state on history entity. Expected: BEING_INSTALLED, Found: "
+ + historyEntry.getStatus();
+ }
+
+ // Ensure the installed package has not been added to the resource yet
+
+ // Package 1, Version 2
+ query = em.createNamedQuery(InstalledPackage.QUERY_FIND_BY_RESOURCE_ID_AND_PKG_VER_ID);
+ query.setParameter("resourceId", resource1.getId());
+ query.setParameter("packageVersionId", packageVersion1.getId());
+
+ results = query.getResultList();
+ assert results.size() == 0 : "Incorrect number of installed packages for package 1, version 2. Expected: 0, Found: "
+ + results.size();
+
+ // Check status of audit trail
+ query = em.createNamedQuery(InstalledPackageHistory.QUERY_FIND_BY_CSR_ID_AND_PKG_VER_ID);
+ query.setParameter("contentServiceRequestId", request.getId());
+ query.setParameter("packageVersionId", packageVersion1.getId());
+
+ results = query.getResultList();
+
+ assert results.size() == 1 : "Incorrect number of audit trail entries. Expected: 1, Found: "
+ + results.size();
+
+ InstalledPackageHistory historyEntity = (InstalledPackageHistory) results.get(0);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.BEING_INSTALLED : "Incorrect status on first entity. Expected: BEING_INSTALLED, Found: "
+ + historyEntity.getStatus();
+
+ // Package 2, Version 1
+ query = em.createNamedQuery(InstalledPackage.QUERY_FIND_BY_RESOURCE_ID_AND_PKG_VER_ID);
+ query.setParameter("resourceId", resource1.getId());
+ query.setParameter("packageVersionId", packageVersion2.getId());
+
+ results = query.getResultList();
+ assert results.size() == 0 : "Incorrect number of installed packages for package 2, version 1. Expected: 0, Found: "
+ + results.size();
+
+ // Check status of audit trail
+ query = em.createNamedQuery(InstalledPackageHistory.QUERY_FIND_BY_CSR_ID_AND_PKG_VER_ID);
+ query.setParameter("contentServiceRequestId", request.getId());
+ query.setParameter("packageVersionId", packageVersion2.getId());
+
+ results = query.getResultList();
+
+ assert results.size() == 1 : "Incorrect number of audit trail entries. Expected: 1, Found: "
+ + results.size();
+
+ historyEntity = (InstalledPackageHistory) results.get(0);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.BEING_INSTALLED : "Incorrect status on second entity. Expected: BEING_INSTALLED, Found: "
+ + historyEntity.getStatus();
+
+ } finally {
+ responseLock.notifyAll();
+
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ // Verify --------------------------------------------
+
+ // Give the agent service a second to make sure it finishes out its call
+ Thread.sleep(1000);
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ // Content request
+ Query query = em.createNamedQuery(ContentServiceRequest.QUERY_FIND_BY_RESOURCE);
+ query.setParameter("resourceId", resource1.getId());
+
+ List<?> results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of content service requests. Expected: 1, Found: "
+ + results.size();
+
+ ContentServiceRequest request = (ContentServiceRequest) results.get(0);
+ assert request.getStatus() == ContentRequestStatus.SUCCESS : "Request status incorrect. Expected: SUCCESS, Found: "
+ + request.getStatus();
+
+ // Verify a history entry has been added for the completion of the request per package
+ Set<InstalledPackageHistory> history = request.getInstalledPackageHistory();
+
+ assert history.size() == 4 : "Incorrect number of history entries on request. Expected: 4, Found: "
+ + history.size();
+
+ // Check for Package 1
+ query = em.createNamedQuery(InstalledPackageHistory.QUERY_FIND_BY_CSR_ID_AND_PKG_VER_ID);
+ query.setParameter("contentServiceRequestId", request.getId());
+ query.setParameter("packageVersionId", packageVersion1.getId());
+
+ results = query.getResultList();
+
+ assert results.size() == 2 : "Incorrect number of history entries. Expected: 2, Found: " + results.size();
+
+ InstalledPackageHistory historyEntity = (InstalledPackageHistory) results.get(0);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.INSTALLED : "Incorrect status on first entity. Expected: INSTALLED, Found: "
+ + historyEntity.getStatus();
+
+ historyEntity = (InstalledPackageHistory) results.get(1);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.BEING_INSTALLED : "Incorrect status on first entity. Expected: BEING_INSTALLED, Found: "
+ + historyEntity.getStatus();
+
+ // Check for Package 2
+ query = em.createNamedQuery(InstalledPackageHistory.QUERY_FIND_BY_CSR_ID_AND_PKG_VER_ID);
+ query.setParameter("contentServiceRequestId", request.getId());
+ query.setParameter("packageVersionId", packageVersion2.getId());
+
+ results = query.getResultList();
+
+ assert results.size() == 2 : "Incorrect number of history entries. Expected: 2, Found: " + results.size();
+
+ historyEntity = (InstalledPackageHistory) results.get(0);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.INSTALLED : "Incorrect status on first entity. Expected: INSTALLED, Found: "
+ + historyEntity.getStatus();
+
+ historyEntity = (InstalledPackageHistory) results.get(1);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.BEING_INSTALLED : "Incorrect status on first entity. Expected: BEING_INSTALLED, Found: "
+ + historyEntity.getStatus();
+
+ // Add a few tests for the new Criteria Search feature
+ PackageVersionCriteria criteria = new PackageVersionCriteria();
+ criteria.addFilterResourceId(resource1.getId());
+ PageList<PackageVersion> pageList = contentManager.findPackageVersionsByCriteria(overlord, criteria);
+ assertNotNull(pageList);
+ ArrayList<PackageVersion> pvs = pageList.getValues();
+ assertEquals(2, pvs.size());
+ PackageVersion pv0 = pvs.get(0);
+
+ criteria.addFilterPackageTypeId(pv0.getGeneralPackage().getPackageType().getId());
+ pageList = contentManager.findPackageVersionsByCriteria(overlord, criteria);
+ assertNotNull(pageList);
+ pvs = pageList.getValues();
+ assertEquals(1, pvs.size());
+ assertEquals(pv0.getId(), pvs.get(0).getId());
+
+ // there is no repo assignment, any valid ID should eliminate all PVs
+ criteria.addFilterRepoId(38465);
+ pageList = contentManager.findPackageVersionsByCriteria(overlord, criteria);
+ assertNotNull(pageList);
+ pvs = pageList.getValues();
+ assertEquals(0, pvs.size());
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testDeployWithSteps() throws Exception {
+ // Setup --------------------------------------------
+ Subject overlord = subjectManager.getOverlord();
+
+ Set<ResourcePackageDetails> installUs = new HashSet<ResourcePackageDetails>(2);
+
+ // Package 1, Version 2 with configuration values
+ PackageVersion packageVersion1 = package1.getVersions().get(0);
+ Configuration deploymentConfiguration1 = new Configuration();
+ deploymentConfiguration1.put(new PropertySimple("property1", "value1"));
+
+ PackageDetailsKey key1 = new PackageDetailsKey(package1.getName(), packageVersion1.getVersion(), package1
+ .getPackageType().getName(), packageVersion1.getArchitecture().getName());
+ ResourcePackageDetails packageDetails1 = new ResourcePackageDetails(key1);
+ packageDetails1.setDeploymentTimeConfiguration(deploymentConfiguration1);
+
+ installUs.add(packageDetails1);
+
+ // Make sure the mock is configured to return a success
+ this.contentAgentService.setResponseReturnStatus(ContentResponseResult.SUCCESS);
+ this.contentAgentService.setThrowError(false);
+ this.contentAgentService.setReturnIndividualResponses(true);
+ this.contentAgentService.setDeployPackageSteps(stepResults);
+
+ String notes = "Test deploy notes";
+
+ // Test --------------------------------------------
+
+ // Perform the deploy while locking the agent service. This allows us to check the state after the request
+ // is sent to the agent but before the agent has replied.
+ synchronized (responseLock) {
+ contentManager.deployPackages(overlord, resource1.getId(), installUs, notes);
+
+ // Check to see if the request and installed package were created and have the right status
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ // Content request
+ Query query = em.createNamedQuery(ContentServiceRequest.QUERY_FIND_BY_RESOURCE);
+ query.setParameter("resourceId", resource1.getId());
+
+ List<?> results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of content service requests. Expected: 1, Found: "
+ + results.size();
+
+ ContentServiceRequest request = (ContentServiceRequest) results.get(0);
+ assert request.getContentRequestType() == ContentRequestType.DEPLOY : "Request type incorrect. Expected: DEPLOY, Found: "
+ + request.getContentRequestType();
+ assert request.getStatus() == ContentRequestStatus.IN_PROGRESS : "Request status incorrect. Expected: IN_PROGRESS, Found: "
+ + request.getStatus();
+ assert request.getInstalledPackageHistory().size() == 1 : "Incorrect number of installed packages attached to request. Expected: 1, Found: "
+ + request.getInstalledPackageHistory().size();
+ assert request.getNotes() != null : "Null notes found";
+ assert request.getNotes().equals(notes) : "Incorrect notes found: " + request.getNotes();
+
+ // Verify a history entry has been added for each package in the request
+ Set<InstalledPackageHistory> history = request.getInstalledPackageHistory();
+
+ assert history.size() == 1 : "Incorrect number of history entries on request. Expected: 2, Found: "
+ + history.size();
+
+ for (InstalledPackageHistory historyEntry : history) {
+ assert historyEntry.getStatus() == InstalledPackageHistoryStatus.BEING_INSTALLED : "Incorrect state on history entity. Expected: BEING_INSTALLED, Found: "
+ + historyEntry.getStatus();
+ }
+
+ } finally {
+ responseLock.notifyAll();
+
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ // Verify --------------------------------------------
+
+ // Give the agent service a second to make sure it finishes out its call
+ Thread.sleep(1000);
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ // Content request
+ Query query = em.createNamedQuery(ContentServiceRequest.QUERY_FIND_BY_RESOURCE);
+ query.setParameter("resourceId", resource1.getId());
+
+ List<?> results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of content service requests. Expected: 1, Found: "
+ + results.size();
+
+ ContentServiceRequest request = (ContentServiceRequest) results.get(0);
+ assert request.getStatus() == ContentRequestStatus.SUCCESS : "Request status incorrect. Expected: SUCCESS, Found: "
+ + request.getStatus();
+
+ // Verify a history entry has been added for the completion of the request per package
+ Set<InstalledPackageHistory> history = request.getInstalledPackageHistory();
+
+ assert history.size() == 2 : "Incorrect number of history entries on request. Expected: 2, Found: "
+ + history.size();
+
+ // Check for Package 1
+ query = em.createNamedQuery(InstalledPackageHistory.QUERY_FIND_BY_CSR_ID_AND_PKG_VER_ID);
+ query.setParameter("contentServiceRequestId", request.getId());
+ query.setParameter("packageVersionId", packageVersion1.getId());
+
+ results = query.getResultList();
+
+ assert results.size() == 2 : "Incorrect number of history entries. Expected: 2, Found: " + results.size();
+
+ InstalledPackageHistory historyEntity = (InstalledPackageHistory) results.get(0);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.INSTALLED : "Incorrect status on first entity. Expected: INSTALLED, Found: "
+ + historyEntity.getStatus();
+
+ // The installed entry should contain the steps that were done in the installation
+ List<PackageInstallationStep> installationSteps = historyEntity.getInstallationSteps();
+
+ assert installationSteps != null : "Installation steps were null";
+ assert installationSteps.size() == 3 : "Incorrect number of installation steps. Expected: 3, Found: "
+ + installationSteps.size();
+
+ PackageInstallationStep step = installationSteps.get(0);
+
+ assert step.getOrder() == 0 : "Incorrect order applied for step";
+ assert step.getDescription() != null : "Description not saved";
+ assert step.getResult() == ContentResponseResult.SUCCESS : "Incorrect status on step. Expected: SUCCESS, Found: "
+ + step.getResult();
+ assert step.getErrorMessage() == null : "Error message found on successful step";
+ assert step.getInstalledPackageHistory() != null : "Relationship to packge history isn't established";
+
+ step = installationSteps.get(1);
+
+ assert step.getOrder() == 1 : "Incorrect order applied for step";
+ assert step.getDescription() != null : "Description not saved";
+ assert step.getResult() == ContentResponseResult.NOT_PERFORMED : "Incorrect status on step. Expected: NOT_PERFORMED, Found: "
+ + step.getResult();
+ assert step.getErrorMessage() == null : "Error message found on skipped step";
+ assert step.getInstalledPackageHistory() != null : "Relationship to packge history isn't established";
+
+ step = installationSteps.get(2);
+
+ assert step.getOrder() == 2 : "Incorrect order applied for step";
+ assert step.getDescription() != null : "Description not saved";
+ assert step.getResult() == ContentResponseResult.FAILURE : "Incorrect status on step. Expected: FAILURE, Found: "
+ + step.getResult();
+ assert step.getErrorMessage() != null : "Null error message found on error step";
+ assert step.getInstalledPackageHistory() != null : "Relationship to packge history isn't established";
+
+ historyEntity = (InstalledPackageHistory) results.get(1);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.BEING_INSTALLED : "Incorrect status on first entity. Expected: BEING_INSTALLED, Found: "
+ + historyEntity.getStatus();
+
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testFailedDeployPackages() throws Exception {
+ // Setup --------------------------------------------
+ Subject overlord = subjectManager.getOverlord();
+
+ Set<ResourcePackageDetails> installUs = new HashSet<ResourcePackageDetails>(1);
+
+ // Package 1, Version 2 with configuration values
+ Configuration deploymentConfiguration1 = new Configuration();
+ deploymentConfiguration1.put(new PropertySimple("property1", "value1"));
+
+ PackageVersion packageVersion1 = package1.getVersions().get(1);
+ PackageDetailsKey key1 = new PackageDetailsKey(package1.getName(), packageVersion1.getVersion(), package1
+ .getPackageType().getName(), packageVersion1.getArchitecture().getName());
+
+ ResourcePackageDetails packageDetails1 = new ResourcePackageDetails(key1);
+ packageDetails1.setDeploymentTimeConfiguration(deploymentConfiguration1);
+
+ installUs.add(packageDetails1);
+
+ // Make sure the mock is configured to return a failure
+ this.contentAgentService.setResponseReturnStatus(ContentResponseResult.FAILURE);
+ this.contentAgentService.setThrowError(false);
+ this.contentAgentService.setReturnIndividualResponses(true);
+
+ String notes = "Test deploy notes";
+
+ // Test --------------------------------------------
+ contentManager.deployPackages(overlord, resource1.getId(), installUs, notes);
+
+ // Verify --------------------------------------------
+
+ // Give the agent service a second to make sure it finishes out its call
+ Thread.sleep(1000);
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ // Content request
+ Query query = em.createNamedQuery(ContentServiceRequest.QUERY_FIND_BY_RESOURCE);
+ query.setParameter("resourceId", resource1.getId());
+
+ List<?> results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of content service requests. Expected: 1, Found: "
+ + results.size();
+
+ ContentServiceRequest request = (ContentServiceRequest) results.get(0);
+ assert request.getStatus() == ContentRequestStatus.FAILURE : "Request status incorrect. Expected: IN_PROGRESS, Found: "
+ + request.getStatus();
+ assert request.getNotes() != null : "Null notes found";
+ assert request.getNotes().equals(notes) : "Incorrect notes found: " + request.getNotes();
+
+ // Check for Package 1
+ query = em.createNamedQuery(InstalledPackageHistory.QUERY_FIND_BY_CSR_ID_AND_PKG_VER_ID);
+ query.setParameter("contentServiceRequestId", request.getId());
+ query.setParameter("packageVersionId", packageVersion1.getId());
+
+ results = query.getResultList();
+
+ assert results.size() == 2 : "Incorrect number of history entries. Expected: 2, Found: " + results.size();
+
+ InstalledPackageHistory historyEntity = (InstalledPackageHistory) results.get(0);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.FAILED : "Incorrect status on first entity. Expected: FAILED, Found: "
+ + historyEntity.getStatus();
+
+ historyEntity = (InstalledPackageHistory) results.get(1);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.BEING_INSTALLED : "Incorrect status on first entity. Expected: BEING_INSTALLED, Found: "
+ + historyEntity.getStatus();
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testDeployPackageFailToContactAgent() throws Exception {
+ // Setup --------------------------------------------
+ Subject overlord = subjectManager.getOverlord();
+
+ Set<ResourcePackageDetails> installUs = new HashSet<ResourcePackageDetails>(1);
+
+ // Package 1, Version 2 with configuration values
+ Configuration deploymentConfiguration1 = new Configuration();
+ deploymentConfiguration1.put(new PropertySimple("property1", "value1"));
+
+ PackageVersion packageVersion1 = package1.getVersions().get(1);
+ PackageDetailsKey key1 = new PackageDetailsKey(package1.getName(), packageVersion1.getVersion(), package1
+ .getPackageType().getName(), packageVersion1.getArchitecture().getName());
+ ResourcePackageDetails packageDetails1 = new ResourcePackageDetails(key1);
+ packageDetails1.setDeploymentTimeConfiguration(deploymentConfiguration1);
+
+ installUs.add(packageDetails1);
+
+ // Make sure the mock is configured to return a failure
+ this.contentAgentService.setResponseReturnStatus(ContentResponseResult.FAILURE);
+ this.contentAgentService.setThrowError(true);
+ this.contentAgentService.setReturnIndividualResponses(false);
+
+ String notes = "Test deploy notes";
+
+ // Test --------------------------------------------
+ try {
+ contentManager.deployPackages(overlord, resource1.getId(), installUs, notes);
+ assert false : "No exception thrown from deploy call";
+ } catch (Exception e) {
+ // Expected
+ }
+
+ // Verify --------------------------------------------
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ // Content request
+ Query query = em.createNamedQuery(ContentServiceRequest.QUERY_FIND_BY_RESOURCE);
+ query.setParameter("resourceId", resource1.getId());
+
+ List<?> results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of content service requests. Expected: 1, Found: "
+ + results.size();
+
+ ContentServiceRequest request = (ContentServiceRequest) results.get(0);
+ assert request.getStatus() == ContentRequestStatus.FAILURE : "Request status incorrect. Expected: IN_PROGRESS, Found: "
+ + request.getStatus();
+ assert request.getNotes() != null : "Null notes found";
+ assert request.getNotes().equals(notes) : "Incorrect notes found: " + request.getNotes();
+
+ // Check for Package 1
+ query = em.createNamedQuery(InstalledPackageHistory.QUERY_FIND_BY_CSR_ID_AND_PKG_VER_ID);
+ query.setParameter("contentServiceRequestId", request.getId());
+ query.setParameter("packageVersionId", packageVersion1.getId());
+
+ results = query.getResultList();
+
+ assert results.size() == 2 : "Incorrect number of history entries. Expected: 2, Found: " + results.size();
+
+ InstalledPackageHistory historyEntity = (InstalledPackageHistory) results.get(0);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.FAILED : "Incorrect status on first entity. Expected: FAILED, Found: "
+ + historyEntity.getStatus();
+
+ historyEntity = (InstalledPackageHistory) results.get(1);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.BEING_INSTALLED : "Incorrect status on first entity. Expected: BEING_INSTALLED, Found: "
+ + historyEntity.getStatus();
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testDeployPackagesNoIndividualResponses() throws Exception {
+ // Setup --------------------------------------------
+ Subject overlord = subjectManager.getOverlord();
+
+ Set<ResourcePackageDetails> installUs = new HashSet<ResourcePackageDetails>(1);
+
+ // Package 1, Version 2 with configuration values
+ Configuration deploymentConfiguration1 = new Configuration();
+ deploymentConfiguration1.put(new PropertySimple("property1", "value1"));
+
+ PackageVersion packageVersion1 = package1.getVersions().get(1);
+ PackageDetailsKey key1 = new PackageDetailsKey(package1.getName(), packageVersion1.getVersion(), package1
+ .getPackageType().getName(), packageVersion1.getArchitecture().getName());
+ ResourcePackageDetails packageDetails1 = new ResourcePackageDetails(key1);
+ packageDetails1.setDeploymentTimeConfiguration(deploymentConfiguration1);
+
+ installUs.add(packageDetails1);
+
+ // Make sure the mock is configured to return a failure
+ this.contentAgentService.setResponseReturnStatus(ContentResponseResult.FAILURE);
+ this.contentAgentService.setThrowError(false);
+ this.contentAgentService.setReturnIndividualResponses(false);
+
+ String notes = "Test deploy notes";
+
+ // Test --------------------------------------------
+ contentManager.deployPackages(overlord, resource1.getId(), installUs, notes);
+
+ // Give the agent service a second to make sure it finishes out its call
+ Thread.sleep(1000);
+
+ // Verify --------------------------------------------
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ // Content request
+ Query query = em.createNamedQuery(ContentServiceRequest.QUERY_FIND_BY_RESOURCE);
+ query.setParameter("resourceId", resource1.getId());
+
+ List<?> results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of content service requests. Expected: 1, Found: "
+ + results.size();
+
+ ContentServiceRequest request = (ContentServiceRequest) results.get(0);
+ assert request.getStatus() == ContentRequestStatus.FAILURE : "Request status incorrect. Expected: FAILURE, Found: "
+ + request.getStatus();
+ assert request.getNotes() != null : "Null notes found";
+ assert request.getNotes().equals(notes) : "Incorrect notes found: " + request.getNotes();
+
+ // Check for Package 1
+ query = em.createNamedQuery(InstalledPackageHistory.QUERY_FIND_BY_CSR_ID_AND_PKG_VER_ID);
+ query.setParameter("contentServiceRequestId", request.getId());
+ query.setParameter("packageVersionId", packageVersion1.getId());
+
+ results = query.getResultList();
+
+ assert results.size() == 2 : "Incorrect number of history entries. Expected: 2, Found: " + results.size();
+
+ InstalledPackageHistory historyEntity = (InstalledPackageHistory) results.get(0);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.FAILED : "Incorrect status on first entity. Expected: FAILED, Found: "
+ + historyEntity.getStatus();
+
+ historyEntity = (InstalledPackageHistory) results.get(1);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.BEING_INSTALLED : "Incorrect status on first entity. Expected: BEING_INSTALLED, Found: "
+ + historyEntity.getStatus();
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test(enabled = ENABLE_TESTS)
+ public void testLoadDependencies() throws Exception {
+ // Setup --------------------------------------------
+ Set<PackageDetailsKey> loadUs = new HashSet<PackageDetailsKey>(3);
+
+ // Package 1, Version 2
+ PackageVersion packageVersion1 = package1.getVersions().get(1);
+ PackageDetailsKey packageKey1 = new PackageDetailsKey(package1.getName(), packageVersion1.getVersion(),
+ package1.getPackageType().getName(), packageVersion1.getArchitecture().getName());
+
+ loadUs.add(packageKey1);
+
+ // Package 2, Version 2
+ PackageVersion packageVersion2 = package2.getVersions().get(1);
+ PackageDetailsKey packageKey2 = new PackageDetailsKey(package2.getName(), packageVersion2.getVersion(),
+ package2.getPackageType().getName(), packageVersion2.getArchitecture().getName());
+
+ loadUs.add(packageKey2);
+
+ // Package that does not exist in the server
+ PackageDetailsKey packageKey3 = new PackageDetailsKey("foo", "1.0.0", "fooType", "fooArch");
+
+ loadUs.add(packageKey3);
+
+ // Need to create a content service request off of which to hang the dependencies as new installed package requests
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ ContentServiceRequest request = null;
+ try {
+ resource1 = em.find(Resource.class, resource1.getId());
+ Subject overlord = subjectManager.getOverlord();
+ PackageVersion packageVersion = em.find(PackageVersion.class, package3.getVersions().get(0).getId());
+
+ request = new ContentServiceRequest(resource1, overlord.getName(), ContentRequestType.DEPLOY);
+
+ InstalledPackageHistory originalRequestedPackage = new InstalledPackageHistory();
+ originalRequestedPackage.setContentServiceRequest(request);
+ originalRequestedPackage.setPackageVersion(packageVersion);
+ originalRequestedPackage.setStatus(InstalledPackageHistoryStatus.BEING_INSTALLED);
+ originalRequestedPackage.setTimestamp(System.currentTimeMillis());
+ originalRequestedPackage.setResource(resource1);
+
+ request.addInstalledPackageHistory(originalRequestedPackage);
+
+ em.persist(request);
+
+ getTransactionManager().commit();
+ } catch (Throwable t) {
+ getTransactionManager().rollback();
+
+ assert false : "Error during setup: " + t;
+ } finally {
+ em.close();
+ }
+
+ // Test --------------------------------------------
+ contentManager.loadDependencies(request.getId(), loadUs);
+
+ // Verify --------------------------------------------
+
+ // Verify installed packages were created for the two dependency packages
+ getTransactionManager().begin();
+ em = getEntityManager();
+
+ try {
+ // Overall package count on the request
+ Query query = em.createNamedQuery(ContentServiceRequest.QUERY_FIND_BY_ID);
+ query.setParameter("id", request.getId());
+
+ List<ContentServiceRequest> resultList = query.getResultList();
+
+ assert resultList.size() == 1 : "Incorrect number of requests loaded. Expected: 1, Found: "
+ + resultList.size();
+
+ request = (ContentServiceRequest) resultList.get(0);
+
+ assert request.getInstalledPackageHistory().size() == 3 : "Incorrect number of being installed packages on request. Expected: 3, Found: "
+ + resultList.size();
+
+ // Quick check for the status of each
+ query = em.createNamedQuery(InstalledPackageHistory.QUERY_FIND_BY_CSR_ID);
+ query.setParameter("contentServiceRequestId", request.getId());
+
+ List<InstalledPackageHistory> historyEntries = query.getResultList();
+
+ for (InstalledPackageHistory historyEntry : historyEntries) {
+ assert historyEntry.getContentServiceRequest().equals(request) : "ContentServiceRequest relationship not set up correctly for package history";
+ assert historyEntry.getStatus() == InstalledPackageHistoryStatus.BEING_INSTALLED : "Incorrect status on installed package history. Expected: BEING_INSTALLED, Found: "
+ + historyEntry.getStatus();
+ }
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testSuccessfullyDeletePackages() throws Exception {
+ // Setup --------------------------------------------
+ Subject overlord = subjectManager.getOverlord();
+
+ // Delete installed package for package4
+ int[] deleteUs = new int[] { installedPackage1.getId() };
+
+ // Leave package5 installed
+
+ // Make sure the mock is configured to return a success
+ this.contentAgentService.setResponseReturnStatus(ContentResponseResult.SUCCESS);
+ this.contentAgentService.setThrowError(false);
+ this.contentAgentService.setReturnIndividualResponses(true);
+
+ String notes = "Test delete notes";
+
+ // Test --------------------------------------------
+
+ // Perform the deploy while locking the agent service. This allows us to check the state after the request
+ // is sent to the agent but before the agent has replied.
+ synchronized (responseLock) {
+ contentManager.deletePackages(overlord, resource1.getId(), deleteUs, notes);
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ // Content request
+ Query query = em.createNamedQuery(ContentServiceRequest.QUERY_FIND_BY_RESOURCE);
+ query.setParameter("resourceId", resource1.getId());
+
+ List<?> results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of content service requests. Expected: 1, Found: "
+ + results.size();
+
+ ContentServiceRequest request = (ContentServiceRequest) results.get(0);
+ assert request.getStatus() == ContentRequestStatus.IN_PROGRESS : "Request status incorrect. Expected: IN_PROGRESS, Found: "
+ + request.getStatus();
+ assert request.getNotes() != null : "Null notes found";
+ assert request.getNotes().equals(notes) : "Incorrect notes found: " + request.getNotes();
+
+ // Verify a history entry has been added for each package in the request
+ Set<InstalledPackageHistory> history = request.getInstalledPackageHistory();
+
+ assert history.size() == 1 : "Incorrect number of history entries on request. Expected: 1, Found: "
+ + history.size();
+
+ for (InstalledPackageHistory historyEntry : history) {
+ assert historyEntry.getStatus() == InstalledPackageHistoryStatus.BEING_DELETED : "Incorrect state on history entity. Expected: BEING_DELETED, Found: "
+ + historyEntry.getStatus();
+ }
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ // Verify --------------------------------------------
+
+ // Give the agent service a second to make sure it finishes out its call
+ Thread.sleep(1000);
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ // Content request
+ Query query = em.createNamedQuery(ContentServiceRequest.QUERY_FIND_BY_RESOURCE);
+ query.setParameter("resourceId", resource1.getId());
+
+ List<?> results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of content service requests. Expected: 1, Found: "
+ + results.size();
+
+ ContentServiceRequest request = (ContentServiceRequest) results.get(0);
+ assert request.getStatus() == ContentRequestStatus.SUCCESS : "Request status incorrect. Expected: SUCCESS, Found: "
+ + request.getStatus();
+
+ // Verify history entries
+ query = em.createNamedQuery(InstalledPackageHistory.QUERY_FIND_BY_CSR_ID_AND_PKG_VER_ID);
+ query.setParameter("contentServiceRequestId", request.getId());
+ query.setParameter("packageVersionId", installedPackage1.getPackageVersion().getId());
+
+ results = query.getResultList();
+
+ assert results.size() == 2 : "Incorrect number of history entries. Expected: 2, Found: " + results.size();
+
+ InstalledPackageHistory historyEntity = (InstalledPackageHistory) results.get(0);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.DELETED : "Incorrect status on first entity. Expected: DELETED, Found: "
+ + historyEntity.getStatus();
+
+ historyEntity = (InstalledPackageHistory) results.get(1);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.BEING_DELETED : "Incorrect status on first entity. Expected: BEING_DELETED, Found: "
+ + historyEntity.getStatus();
+
+ // Package 4, Version 2
+ query = em.createNamedQuery(InstalledPackage.QUERY_FIND_BY_RESOURCE_ID_AND_PKG_VER_ID);
+ query.setParameter("resourceId", resource1.getId());
+ query.setParameter("packageVersionId", installedPackage1.getPackageVersion().getId());
+
+ results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of installed packages for package 1, version 2. Expected: 0, Found: "
+ + results.size();
+
+ // Package 2, Version 1
+ query = em.createNamedQuery(InstalledPackage.QUERY_FIND_BY_RESOURCE_ID_AND_PKG_VER_ID);
+ query.setParameter("resourceId", resource1.getId());
+ query.setParameter("packageVersionId", package5.getVersions().get(0).getId());
+
+ results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of installed packages for package 2, version 1. Expected: 1, Found: "
+ + results.size();
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testDeletePackagesNoIndividualResponses() throws Exception {
+ // Setup --------------------------------------------
+ Subject overlord = subjectManager.getOverlord();
+
+ // Delete installed package for package4
+ int[] deleteUs = new int[] { installedPackage1.getId() };
+
+ // Leave package5 installed
+
+ // Make sure the mock is configured to return a success
+ this.contentAgentService.setResponseReturnStatus(ContentResponseResult.FAILURE);
+ this.contentAgentService.setThrowError(false);
+ this.contentAgentService.setReturnIndividualResponses(false);
+
+ String notes = "Test delete notes";
+
+ // Test --------------------------------------------
+
+ // Perform the deploy while locking the agent service. This allows us to check the state after the request
+ // is sent to the agent but before the agent has replied.
+ synchronized (responseLock) {
+ contentManager.deletePackages(overlord, resource1.getId(), deleteUs, notes);
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ // Content request
+ Query query = em.createNamedQuery(ContentServiceRequest.QUERY_FIND_BY_RESOURCE);
+ query.setParameter("resourceId", resource1.getId());
+
+ List<?> results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of content service requests. Expected: 1, Found: "
+ + results.size();
+
+ ContentServiceRequest request = (ContentServiceRequest) results.get(0);
+ assert request.getStatus() == ContentRequestStatus.IN_PROGRESS : "Request status incorrect. Expected: IN_PROGRESS, Found: "
+ + request.getStatus();
+ assert request.getNotes() != null : "Null notes found";
+ assert request.getNotes().equals(notes) : "Incorrect notes found: " + request.getNotes();
+
+ // Verify a history entry has been added for each package in the request
+ Set<InstalledPackageHistory> history = request.getInstalledPackageHistory();
+
+ assert history.size() == 1 : "Incorrect number of history entries on request. Expected: 1, Found: "
+ + history.size();
+
+ for (InstalledPackageHistory historyEntry : history) {
+ assert historyEntry.getStatus() == InstalledPackageHistoryStatus.BEING_DELETED : "Incorrect state on history entity. Expected: BEING_DELETED, Found: "
+ + historyEntry.getStatus();
+ }
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ // Verify --------------------------------------------
+
+ // Give the agent service a second to make sure it finishes out its call
+ Thread.sleep(1000);
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ // Content request
+ Query query = em.createNamedQuery(ContentServiceRequest.QUERY_FIND_BY_RESOURCE);
+ query.setParameter("resourceId", resource1.getId());
+
+ List<?> results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of content service requests. Expected: 1, Found: "
+ + results.size();
+
+ ContentServiceRequest request = (ContentServiceRequest) results.get(0);
+ assert request.getStatus() == ContentRequestStatus.FAILURE : "Request status incorrect. Expected: FAILURE, Found: "
+ + request.getStatus();
+
+ // Verify history entries
+ query = em.createNamedQuery(InstalledPackageHistory.QUERY_FIND_BY_CSR_ID_AND_PKG_VER_ID);
+ query.setParameter("contentServiceRequestId", request.getId());
+ query.setParameter("packageVersionId", installedPackage1.getPackageVersion().getId());
+
+ results = query.getResultList();
+
+ assert results.size() == 2 : "Incorrect number of history entries. Expected: 2, Found: " + results.size();
+
+ InstalledPackageHistory historyEntity = (InstalledPackageHistory) results.get(0);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.FAILED : "Incorrect status on first entity. Expected: FAILED, Found: "
+ + historyEntity.getStatus();
+
+ historyEntity = (InstalledPackageHistory) results.get(1);
+ assert historyEntity.getStatus() == InstalledPackageHistoryStatus.BEING_DELETED : "Incorrect status on first entity. Expected: BEING_DELETED, Found: "
+ + historyEntity.getStatus();
+
+ // Package 4, Version 2
+ query = em.createNamedQuery(InstalledPackage.QUERY_FIND_BY_RESOURCE_ID_AND_PKG_VER_ID);
+ query.setParameter("resourceId", resource1.getId());
+ query.setParameter("packageVersionId", installedPackage1.getPackageVersion().getId());
+
+ results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of installed packages for package 1, version 2. Expected: 0, Found: "
+ + results.size();
+
+ // Package 2, Version 1
+ query = em.createNamedQuery(InstalledPackage.QUERY_FIND_BY_RESOURCE_ID_AND_PKG_VER_ID);
+ query.setParameter("resourceId", resource1.getId());
+ query.setParameter("packageVersionId", package5.getVersions().get(0).getId());
+
+ results = query.getResultList();
+ assert results.size() == 1 : "Incorrect number of installed packages for package 2, version 1. Expected: 1, Found: "
+ + results.size();
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ // Private --------------------------------------------
+
+ private void setupTestEnvironment() throws Exception {
+ TestServerCommunicationsService agentServiceContainer = prepareForTestAgents();
+ agentServiceContainer.contentService = contentAgentService;
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ try {
+ architecture1 = em.find(Architecture.class, 1);
+ architecture2 = em.find(Architecture.class, 2);
+
+ resourceType1 = new ResourceType("resourcetype-" + System.currentTimeMillis(), "TestPlugin",
+ ResourceCategory.PLATFORM, null);
+ em.persist(resourceType1);
+
+ // Add package types to resource type
+ packageType1 = new PackageType();
+ packageType1.setName("package1-" + System.currentTimeMillis());
+ packageType1.setDescription("");
+ packageType1.setCategory(PackageCategory.DEPLOYABLE);
+ packageType1.setDisplayName("TestResourcePackage");
+ packageType1.setCreationData(true);
+ packageType1.setResourceType(resourceType1);
+ em.persist(packageType1);
+
+ packageType2 = new PackageType();
+ packageType2.setName("package2-" + System.currentTimeMillis());
+ packageType2.setDescription("");
+ packageType2.setCategory(PackageCategory.DEPLOYABLE);
+ packageType2.setDisplayName("TestResourcePackage2");
+ packageType2.setCreationData(true);
+ packageType2.setResourceType(resourceType1);
+ em.persist(packageType2);
+
+ packageType3 = new PackageType();
+ packageType3.setName("package3-" + System.currentTimeMillis());
+ packageType3.setDescription("");
+ packageType3.setCategory(PackageCategory.DEPLOYABLE);
+ packageType3.setDisplayName("TestResourcePackage3");
+ packageType3.setCreationData(true);
+ packageType3.setResourceType(resourceType1);
+ em.persist(packageType3);
+
+ packageType4 = new PackageType();
+ packageType4.setName("package4-" + System.currentTimeMillis());
+ packageType4.setDescription("");
+ packageType4.setCategory(PackageCategory.DEPLOYABLE);
+ packageType4.setDisplayName("TestResourcePackage4");
+ packageType4.setCreationData(true);
+ packageType4.setResourceType(resourceType1);
+ em.persist(packageType4);
+
+ resourceType1.addPackageType(packageType1);
+ resourceType1.addPackageType(packageType2);
+ resourceType1.addPackageType(packageType3);
+
+ // Package 1 - Contains 2 versions
+ package1 = new Package("Package1", packageType1);
+
+ package1.addVersion(new PackageVersion(package1, "1.0.0", architecture1));
+ package1.addVersion(new PackageVersion(package1, "2.0.0", architecture1));
+
+ em.persist(package1);
+
+ // Package 2 - Contains 2 versions
+ package2 = new Package("Package2", packageType2);
+
+ package2.addVersion(new PackageVersion(package2, "1.0.0", architecture1));
+ package2.addVersion(new PackageVersion(package2, "2.0.0", architecture1));
+
+ em.persist(package2);
+
+ // Package 3 - Contains 1 version
+ package3 = new Package("Package3", packageType3);
+
+ package3.addVersion(new PackageVersion(package3, "1.0.0", architecture1));
+
+ em.persist(package3);
+
+ // Package 4 - Contains 2 versions, the first is installed
+ package4 = new Package("Package4", packageType4);
+
+ PackageVersion package4Installed = new PackageVersion(package4, "1.0.0", architecture1);
+ package4.addVersion(package4Installed);
+ package4.addVersion(new PackageVersion(package4, "2.0.0", architecture1));
+
+ em.persist(package4);
+
+ // Package 5 - Contains 1 version, it is installed
+ package5 = new Package("Package5", packageType3);
+
+ PackageVersion package5Installed = new PackageVersion(package5, "1.0.0", architecture1);
+ package5.addVersion(package5Installed);
+
+ em.persist(package5);
+
+ // Create resource against which we'll merge the discovery report
+ resource1 = new Resource("parent" + System.currentTimeMillis(), "name", resourceType1);
+ resource1.setUuid("" + new Random().nextInt());
+ em.persist(resource1);
+
+ // Install packages on the resource
+ installedPackage1 = new InstalledPackage();
+ installedPackage1.setResource(resource1);
+ installedPackage1.setPackageVersion(package4Installed);
+ resource1.addInstalledPackage(installedPackage1);
+
+ installedPackage2 = new InstalledPackage();
+ installedPackage2.setResource(resource1);
+ installedPackage2.setPackageVersion(package5Installed);
+ resource1.addInstalledPackage(installedPackage2);
+
+ installedPackage1.setResource(resource1);
+ installedPackage2.setResource(resource1);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ getTransactionManager().rollback();
+ throw e;
+ }
+ } finally {
+ em.close();
+ }
+ }
+
+ private void tearDownTestEnvironment() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ try {
+ resource1 = em.find(Resource.class, resource1.getId());
+ for (InstalledPackage ip : resource1.getInstalledPackages()) {
+ em.remove(ip);
+ }
+
+ for (InstalledPackageHistory history : resource1.getInstalledPackageHistory()) {
+ em.remove(history);
+ }
+
+ for (ContentServiceRequest request : resource1.getContentServiceRequests()) {
+ em.remove(request);
+ }
+
+ package1 = em.find(Package.class, package1.getId());
+ em.remove(package1);
+
+ package2 = em.find(Package.class, package2.getId());
+ em.remove(package2);
+
+ package3 = em.find(Package.class, package3.getId());
+ em.remove(package3);
+
+ package4 = em.find(Package.class, package4.getId());
+ em.remove(package4);
+
+ package5 = em.find(Package.class, package5.getId());
+ em.remove(package5);
+
+ packageType1 = em.find(PackageType.class, packageType1.getId());
+ em.remove(packageType1);
+
+ packageType2 = em.find(PackageType.class, packageType2.getId());
+ em.remove(packageType2);
+
+ packageType3 = em.find(PackageType.class, packageType3.getId());
+ em.remove(packageType3);
+
+ packageType4 = em.find(PackageType.class, packageType4.getId());
+ em.remove(packageType4);
+
+ ResourceTreeHelper.deleteResource(em, resource1);
+
+ resourceType1 = em.find(ResourceType.class, resourceType1.getId());
+ em.remove(resourceType1);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ getTransactionManager().rollback();
+ throw e;
+ }
+ } finally {
+ em.close();
+ unprepareForTestAgents();
+ }
+ }
+
+ private void populateResponseSteps() {
+ stepResults = new ArrayList<DeployPackageStep>(3);
+
+ DeployPackageStep step1 = new DeployPackageStep("Step1", "First step");
+ step1.setStepResult(ContentResponseResult.SUCCESS);
+
+ DeployPackageStep step2 = new DeployPackageStep("Step2", "Second step");
+ step2.setStepResult(ContentResponseResult.NOT_PERFORMED);
+
+ DeployPackageStep step3 = new DeployPackageStep("Step3", "Third step");
+ step3.setStepResult(ContentResponseResult.FAILURE);
+ step3.setStepErrorMessage("Error executing the third step");
+
+ stepResults.add(step1);
+ stepResults.add(step2);
+ stepResults.add(step3);
+ }
+
+ // Inner Classes --------------------------------------------
+
+ private class MockContentAgentService implements ContentAgentService {
+ // Attributes --------------------------------------------
+
+ private ContentResponseResult responseReturnStatus;
+
+ private boolean throwError;
+ private boolean returnIndividualResponses = true;
+
+ private List<DeployPackageStep> deployPackageSteps;
+
+ // Public --------------------------------------------
+
+ /**
+ * The value set in this method will be the status of the response object sent back to the EJB.
+ *
+ * @param responseReturnStatus status to use for all response objects
+ */
+ public void setResponseReturnStatus(ContentResponseResult responseReturnStatus) {
+ this.responseReturnStatus = responseReturnStatus;
+ }
+
+ /**
+ * If this is set to <code>true</code>, calls into this mock will trigger a <code>RuntimeException</code>.
+ *
+ * @param throwError flag indicating if an error should be thrown
+ */
+ public void setThrowError(boolean throwError) {
+ this.throwError = throwError;
+ }
+
+ /**
+ * Calls to deploy will include this list for all packages in the deployment request.
+ *
+ * @param deployPackageSteps indicates if deployed package responses should have steps attached to them
+ */
+ public void setDeployPackageSteps(List<DeployPackageStep> deployPackageSteps) {
+ this.deployPackageSteps = deployPackageSteps;
+ }
+
+ /**
+ * If this is set to <code>true</code> the response will include an entry for each package requested.
+ *
+ * @param returnIndividualResponses flag indicating if individual package results should be returned
+ */
+ public void setReturnIndividualResponses(boolean returnIndividualResponses) {
+ this.returnIndividualResponses = returnIndividualResponses;
+ }
+
+ // ContentAgentService Implementation --------------------------------------------
+
+ public Set<ResourcePackageDetails> getLastDiscoveredResourcePackages(int resourceId) {
+ return null;
+ }
+
+ public ContentDiscoveryReport executeResourcePackageDiscoveryImmediately(int resourceId, String packageTypeName)
+ throws PluginContainerException {
+ return null;
+ }
+
+ public List<DeployPackageStep> translateInstallationSteps(int resourceId, ResourcePackageDetails packageDetails) {
+ return null;
+ }
+
+ public void deployPackages(final DeployPackagesRequest request) {
+ if (throwError) {
+ throw new RuntimeException("Mock exception - This is expected");
+ }
+
+ Runnable responseRunner = new Runnable() {
+ public void run() {
+ synchronized (responseLock) {
+ DeployPackagesResponse response = new DeployPackagesResponse(responseReturnStatus);
+
+ // This setting of the ID will be done by the plugin container; we're not relying on the plugin
+ // to do it. Since I'm skipping the PC entirely for this test, I'll do it here.
+ response.setRequestId(request.getRequestId());
+
+ if (returnIndividualResponses) {
+ for (ResourcePackageDetails packageDetails : request.getPackages()) {
+ DeployIndividualPackageResponse individualResponse = new DeployIndividualPackageResponse(
+ packageDetails.getKey(), responseReturnStatus);
+
+ individualResponse.setDeploymentSteps(deployPackageSteps);
+
+ response.addPackageResponse(individualResponse);
+ }
+ }
+
+ ContentManagerBeanTest.this.contentManager.completeDeployPackageRequest(response);
+ }
+ }
+ };
+
+ Thread runner = new Thread(responseRunner);
+ runner.start();
+ }
+
+ public void deletePackages(final DeletePackagesRequest request) {
+ if (throwError) {
+ throw new RuntimeException("Mock exception - This is expected");
+ }
+
+ Runnable responseRunner = new Runnable() {
+ public void run() {
+ synchronized (responseLock) {
+ RemovePackagesResponse response = new RemovePackagesResponse(responseReturnStatus);
+
+ // This setting of the ID will be done by the plugin container; we're not relying on the plugin
+ // to do it. Since I'm skipping the PC entirely for this test, I'll do it here.
+ response.setRequestId(request.getRequestId());
+
+ if (returnIndividualResponses) {
+ for (ResourcePackageDetails packageDetails : request.getPackages()) {
+ RemoveIndividualPackageResponse individualResponse = new RemoveIndividualPackageResponse(
+ packageDetails.getKey(), responseReturnStatus);
+ response.addPackageResponse(individualResponse);
+ }
+ }
+
+ ContentManagerBeanTest.this.contentManager.completeDeletePackageRequest(response);
+ }
+ }
+ };
+
+ Thread runner = new Thread(responseRunner);
+ runner.start();
+ }
+
+ public void retrievePackageBits(RetrievePackageBitsRequest request) {
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
new file mode 100644
index 0000000..a3a561a
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
@@ -0,0 +1,1205 @@
+/*
+ * 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.enterprise.server.content.test;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.testng.annotations.AfterClass;
+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.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.content.Architecture;
+import org.rhq.core.domain.content.ContentSource;
+import org.rhq.core.domain.content.ContentSourceSyncResults;
+import org.rhq.core.domain.content.ContentSourceType;
+import org.rhq.core.domain.content.ContentSyncStatus;
+import org.rhq.core.domain.content.DownloadMode;
+import org.rhq.core.domain.content.InstalledPackage;
+import org.rhq.core.domain.content.Package;
+import org.rhq.core.domain.content.PackageCategory;
+import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.domain.content.PackageVersionContentSource;
+import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.content.RepoSyncResults;
+import org.rhq.core.domain.content.composite.PackageVersionMetadataComposite;
+import org.rhq.core.domain.resource.ProductVersion;
+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.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.enterprise.server.content.ContentManagerLocal;
+import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
+import org.rhq.enterprise.server.content.RepoManagerLocal;
+import org.rhq.enterprise.server.content.metadata.ContentSourceMetadataManagerLocal;
+import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails;
+import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetailsKey;
+import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
+import org.rhq.enterprise.server.plugin.pc.content.TestContentServerPluginService;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.ResourceTreeHelper;
+
+public class ContentSourceManagerBeanTest extends AbstractEJB3Test {
+
+ private static final boolean TESTS_ENABLED = true;
+
+ private ContentManagerLocal contentManager;
+ private ContentSourceManagerLocal contentSourceManager;
+ private ContentSourceMetadataManagerLocal contentSourceMetadataManager;
+ private RepoManagerLocal repoManager;
+ private Subject overlord;
+ private PackageType packageType1;
+ private PackageType packageType2;
+ private PackageType packageType3;
+ private PackageType packageType4;
+
+ /**
+ * Type: packageType1 Versions: 2
+ */
+ private Package package1;
+
+ /**
+ * Type: packageType2 Versions: 2
+ */
+ private Package package2;
+
+ /**
+ * Type: packageType3 Versions: 1
+ */
+ private Package package3;
+
+ /**
+ * Type: packageType4 Versions: 2 Installed: Version 1
+ */
+ private Package package4;
+
+ /**
+ * Type: packageType4 Versions: 1 Installed: Version 1
+ */
+ private Package package5;
+
+ private InstalledPackage installedPackage1;
+ private InstalledPackage installedPackage2;
+
+ /**
+ * Architecture used in the creation of all sample package versions.
+ */
+ private Architecture architecture1;
+
+ /**
+ * Extra architecture used in tests.
+ */
+ private Architecture architecture2;
+
+ private ResourceType resourceType1;
+ private Resource resource1;
+ private TestContentServerPluginService pluginService;
+
+ @BeforeClass
+ public void setupBeforeClass() throws Exception {
+ contentManager = LookupUtil.getContentManager();
+ contentSourceManager = LookupUtil.getContentSourceManager();
+ contentSourceMetadataManager = LookupUtil.getContentSourceMetadataManager();
+ repoManager = LookupUtil.getRepoManagerLocal();
+
+ // This delete is temporary. There are content sources left over from previous runs of this test
+ // that need to be deleted and this is the simplest way of clearing everyone's environment without
+ // requesting a dbsetup.
+ cleanupPreviousTestRuns();
+ }
+
+ @AfterClass
+ public void tearDownAfterClass() throws Exception {
+ // This delete is temporary. There are content sources left over from previous runs of this test
+ // that need to be deleted and this is the simplest way of clearing everyone's environment without
+ // requesting a dbsetup.
+ cleanupPreviousTestRuns();
+ }
+
+ @BeforeMethod
+ public void setupBeforeMethod() throws Exception {
+ setupTestEnvironment();
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+ prepareScheduler();
+ TestContentServerPluginService pluginService = new TestContentServerPluginService(this);
+ cleanupPreviousTestRuns();
+ }
+
+ @AfterMethod
+ public void tearDownAfterMethod() throws Exception {
+ tearDownTestEnvironment();
+ unprepareServerPluginService();
+ unprepareScheduler();
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testGetSyncResultsList() throws Throwable {
+ getTransactionManager().begin();
+
+ try {
+ // create a content source type and a content source
+ ContentSourceType type = new ContentSourceType("testGetSyncResultsListCST");
+ Set<ContentSourceType> types = new HashSet<ContentSourceType>();
+ types.add(type);
+ contentSourceMetadataManager.registerTypes(types); // this blows away any previous existing types
+ ContentSource contentSource = new ContentSource("testGetSyncResultsListCS", type);
+ contentSource = contentSourceManager.simpleCreateContentSource(overlord, contentSource);
+
+ // make sure we have nothing yet
+ PageList<ContentSourceSyncResults> list;
+ list = contentSourceManager.getContentSourceSyncResults(overlord, contentSource.getId(),
+ PageControl.getUnlimitedInstance());
+ assert list.size() == 0 : "-->" + list;
+
+ // create our first INPROGRESS result
+ ContentSourceSyncResults results = new ContentSourceSyncResults(contentSource);
+ results = contentSourceManager.persistContentSourceSyncResults(results);
+ assert results != null;
+
+ // make sure it persisted
+ list = contentSourceManager.getContentSourceSyncResults(overlord, contentSource.getId(),
+ PageControl.getUnlimitedInstance());
+ assert list.size() == 1 : "-->" + list;
+ assert list.get(0).getId() == results.getId() : "-->" + list;
+
+ // try to create another INPROGRESS, this is not allowed so null must be returned by persist
+ ContentSourceSyncResults another = new ContentSourceSyncResults(contentSource);
+ another = contentSourceManager.persistContentSourceSyncResults(another);
+ assert another == null : "Not allowed to have two INPROGRESS results persisted";
+
+ // verify that we really did not persist a second one
+ list = contentSourceManager.getContentSourceSyncResults(overlord, contentSource.getId(),
+ PageControl.getUnlimitedInstance());
+ assert list.size() == 1 : "-->" + list;
+ assert list.get(0).getId() == results.getId() : "-->" + list;
+
+ // try to create another but this one is a FAILURE, this is allowed
+ another = new ContentSourceSyncResults(contentSource);
+ another.setStatus(ContentSyncStatus.FAILURE);
+ another.setEndTime(System.currentTimeMillis());
+ another = contentSourceManager.persistContentSourceSyncResults(another);
+ assert another != null : "Allowed to have two results persisted if only one is INPROGRESS";
+
+ // verify that we really did persist a second one
+ list = contentSourceManager.getContentSourceSyncResults(overlord, contentSource.getId(),
+ PageControl.getUnlimitedInstance());
+ assert list.size() == 2 : "-->" + list;
+ assert list.get(0).getId() == another.getId() : "-->" + list;
+ assert list.get(1).getId() == results.getId() : "-->" + list;
+
+ // delete the content source and make sure we cascade delete the results
+ contentSourceManager.deleteContentSource(overlord, contentSource.getId());
+
+ list = contentSourceManager.getContentSourceSyncResults(overlord, contentSource.getId(),
+ PageControl.getUnlimitedInstance());
+ assert list.size() == 0 : "-->" + list;
+
+ contentSourceMetadataManager.registerTypes(new HashSet<ContentSourceType>());
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw t;
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testMergeSyncReport() throws Exception {
+ PageControl pc;
+ int repoId = 0;
+ int contentSourceId = 0;
+
+ try {
+ // create content source type
+ ContentSourceType type = new ContentSourceType("testMergeSyncReportCST");
+ Set<ContentSourceType> types = new HashSet<ContentSourceType>();
+ types.add(type);
+ contentSourceMetadataManager.registerTypes(types); // this blows away any previous existing types
+ type = contentSourceManager.getContentSourceType(type.getName());
+ assert type != null;
+ assert type.getId() > 0;
+
+ // create content source
+ ContentSource contentSource = new ContentSource("testMergeSyncReportCS", type);
+ contentSource = contentSourceManager.simpleCreateContentSource(overlord, contentSource);
+ assert contentSource != null;
+ contentSourceId = contentSource.getId();
+ assert contentSourceId > 0;
+
+ // create a repo
+ Repo repo = new Repo("testRepo");
+ repo = repoManager.createRepo(overlord, repo);
+ repoId = repo.getId();
+
+ // this report will add a mapping to PV->CS
+ // we didn't set up any mappings like that yet - this will be the first one
+ PackageSyncReport report = new PackageSyncReport();
+ ContentProviderPackageDetailsKey key = new ContentProviderPackageDetailsKey("testCreateContentSourceFoo",
+ "testCreateContentSourceVer", packageType1.getName(), architecture1.getName(), resourceType1.getName(),
+ resourceType1.getPlugin());
+ ContentProviderPackageDetails details = new ContentProviderPackageDetails(key);
+ details.setLocation("dummy-location");
+ details.setMetadata("dummy-metadata".getBytes());
+ details.addResourceVersion("1.0.0");
+ details.addResourceVersion("2.0.0");
+ report.addNewPackage(details);
+ Map<ContentProviderPackageDetailsKey, PackageVersionContentSource> previous;
+ previous = new HashMap<ContentProviderPackageDetailsKey, PackageVersionContentSource>();
+
+ // merge the report!
+ RepoSyncResults results = new RepoSyncResults(repo);
+ results = repoManager.persistRepoSyncResults(results);
+ assert results != null;
+
+ results = contentSourceManager.mergePackageSyncReport(contentSource, repo, report, previous, results);
+ assert results != null;
+
+ // Verify the product version was created
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ resourceType1 = em.find(ResourceType.class, resourceType1.getId());
+
+ Query productVersionQuery = em.createNamedQuery(ProductVersion.QUERY_FIND_BY_RESOURCE_TYPE_AND_VERSION);
+ productVersionQuery.setParameter("resourceType", resourceType1);
+ productVersionQuery.setParameter("version", "1.0.0");
+
+ List productVersionList = productVersionQuery.getResultList();
+ assert productVersionList.size() > 0 : "Could not find product version for 1.0.0";
+
+ productVersionQuery = em.createNamedQuery(ProductVersion.QUERY_FIND_BY_RESOURCE_TYPE_AND_VERSION);
+ productVersionQuery.setParameter("resourceType", resourceType1);
+ productVersionQuery.setParameter("version", "2.0.0");
+
+ productVersionList = productVersionQuery.getResultList();
+ assert productVersionList.size() > 0 : "Could not find product version for 2.0.0";
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+
+ // see that the resource sees no metadata yet - not subscribed yet
+ pc = PageControl.getUnlimitedInstance();
+ PageList<PackageVersionMetadataComposite> metadataList;
+ metadataList = contentSourceManager.getPackageVersionMetadata(resource1.getId(), pc);
+ assert metadataList != null;
+ assert metadataList.size() == 0 : "-->" + metadataList;
+ String metadataMd5 = contentSourceManager.getResourceSubscriptionMD5(resource1.getId());
+ assert metadataMd5 != null;
+ assert metadataMd5.length() == 32 : "-->" + metadataMd5;
+ assert metadataMd5.equals("d41d8cd98f00b204e9800998ecf8427e") : "-->" + metadataMd5;
+
+ // just to make sure the MD5 for empty data is what we think it is...
+ metadataMd5 = contentSourceManager.getResourceSubscriptionMD5(Integer.MIN_VALUE); // should find no metadata at all
+ assert metadataMd5 != null;
+ assert metadataMd5.length() == 32 : "-->" + metadataMd5;
+ assert metadataMd5.equals("d41d8cd98f00b204e9800998ecf8427e") : "-->" + metadataMd5;
+
+ // add the content source's packages to the repo
+ repoManager.addContentSourcesToRepo(overlord, repoId, new int[] { contentSourceId });
+
+ // see the package versions have been assigned to the repo and content source
+ List<PackageVersion> inRepo;
+ List<PackageVersionContentSource> inContentSources;
+ List<PackageVersionContentSource> inContentSource;
+
+ pc = PageControl.getUnlimitedInstance();
+ inRepo = repoManager.findPackageVersionsInRepo(overlord, repoId, pc);
+ pc = PageControl.getUnlimitedInstance();
+ inContentSources = contentSourceManager.getPackageVersionsFromContentSources(overlord,
+ new int[] { contentSourceId }, pc);
+ inContentSource = contentSourceManager.getPackageVersionsFromContentSource(overlord, contentSourceId, pc);
+ assert inRepo != null;
+ assert inContentSources != null;
+ assert inContentSource != null;
+ assert inRepo.size() == 1 : inRepo;
+ assert inContentSources.size() == 1 : inContentSources;
+ assert inContentSource.size() == 1 : inContentSource;
+
+ // confirm that we didn't load the bits yet
+ pc = PageControl.getUnlimitedInstance();
+ List<PackageVersionContentSource> unloaded;
+ unloaded = contentSourceManager.getUnloadedPackageVersionsFromContentSourceInRepo(overlord,
+ contentSourceId, repoId, pc);
+ assert unloaded != null;
+ assert unloaded.size() == 1;
+
+ // check the counts
+ long pvccount = repoManager.getPackageVersionCountFromRepo(overlord, repo.getId());
+ assert (pvccount == 1) : "-->" + pvccount;
+ long pvcscount = contentSourceManager.getPackageVersionCountFromContentSource(overlord, contentSourceId);
+ assert (pvcscount == 1) : "-->" + pvcscount;
+
+ // subscribe the resource
+ repoManager.subscribeResourceToRepos(overlord, resource1.getId(), new int[] { repoId });
+
+ // confirm the resource is subscribed
+ pc = PageControl.getUnlimitedInstance();
+ metadataList = contentSourceManager.getPackageVersionMetadata(resource1.getId(), pc);
+ assert metadataList != null;
+ assert metadataList.size() == 1 : "-->" + metadataList;
+ metadataMd5 = contentSourceManager.getResourceSubscriptionMD5(resource1.getId());
+ assert metadataMd5 != null;
+ assert metadataMd5.length() == 32 : "-->" + metadataMd5;
+
+ // MD5 is based on the hash code of last modified time
+ repo = repoManager.getRepo(overlord, repoId);
+ long modifiedTimestamp = repo.getLastModifiedDate();
+ Date modifiedDate = new Date(modifiedTimestamp);
+ String datehash = Integer.toString(modifiedDate.hashCode());
+ assert metadataMd5.equals(MessageDigestGenerator.getDigestString(datehash)) : "-->" + metadataMd5;
+
+ repoManager.unsubscribeResourceFromRepos(overlord, resource1.getId(), new int[] { repoId });
+
+ // confirm the resource is unsubscribed
+ pc = PageControl.getUnlimitedInstance();
+ metadataList = contentSourceManager.getPackageVersionMetadata(resource1.getId(), pc);
+ assert metadataList != null;
+ assert metadataList.size() == 0 : "-->" + metadataList;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ try {
+ // clean up - delete all created entities
+ if (repoId != 0) {
+ repoManager.deleteRepo(overlord, repoId);
+ }
+
+ if (contentSourceId != 0) {
+ contentSourceManager.deleteContentSource(overlord, contentSourceId);
+ }
+
+ contentSourceMetadataManager.registerTypes(new HashSet<ContentSourceType>());
+ } catch (Throwable t) {
+ }
+ }
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testMergeSyncReportAddRemoveUpdate() throws Exception {
+ List<PackageVersionContentSource> inCS;
+ PageControl pc = PageControl.getUnlimitedInstance();
+ int contentSourceId = 0;
+ int repoId = 0;
+
+ try {
+ // create content source type and content source
+ ContentSourceType type = new ContentSourceType("testMergeSyncReportAMUCST");
+ Set<ContentSourceType> types = new HashSet<ContentSourceType>();
+ types.add(type);
+ contentSourceMetadataManager.registerTypes(types); // this blows away any previous existing types
+ ContentSource contentSource = new ContentSource("testMergeSyncReportAMUCS", type);
+ contentSource.setLazyLoad(true);
+ contentSource.setDownloadMode(DownloadMode.DATABASE);
+ contentSource = contentSourceManager.simpleCreateContentSource(overlord, contentSource);
+ contentSourceId = contentSource.getId();
+ assert contentSourceId > 0;
+
+ // create repo
+ Repo repo = new Repo("testRepo");
+ repo = repoManager.createRepo(overlord, repo);
+ repoId = repo.getId();
+
+ // just make sure there are no package versions yet
+ inCS = contentSourceManager.getPackageVersionsFromContentSource(overlord, contentSourceId, pc);
+ assert inCS != null;
+ assert inCS.size() == 0 : inCS;
+
+ // need this to pass to merge
+ RepoSyncResults results = new RepoSyncResults(repo);
+ results = repoManager.persistRepoSyncResults(results);
+ assert results != null;
+
+ // this report will add a mapping to PV->CS
+ PackageSyncReport report = new PackageSyncReport();
+ ContentProviderPackageDetailsKey key = new ContentProviderPackageDetailsKey("testARUFoo", "testARUVer",
+ packageType1.getName(), architecture1.getName(), resourceType1.getName(), resourceType1.getPlugin());
+ ContentProviderPackageDetails details = new ContentProviderPackageDetails(key);
+ details.setLocation("dummy-location-aru");
+ details.setFileSize(1234L); // lazy load is on, this should not matter
+ report.addNewPackage(details);
+ Map<ContentProviderPackageDetailsKey, PackageVersionContentSource> previous;
+ previous = new HashMap<ContentProviderPackageDetailsKey, PackageVersionContentSource>();
+
+ // ADD: merge the report!
+ results = contentSourceManager.mergePackageSyncReport(contentSource, repo, report, previous, results);
+ assert results != null;
+
+ // see the package version has been assigned to the content source
+ inCS = contentSourceManager.getPackageVersionsFromContentSource(overlord, contentSourceId, pc);
+ assert inCS != null;
+ assert inCS.size() == 1 : inCS;
+
+ // confirm that we didn't load the bits yet
+ List<PackageVersionContentSource> unloaded;
+ unloaded = contentSourceManager.getUnloadedPackageVersionsFromContentSourceInRepo(overlord,
+ contentSourceId, repoId, pc);
+ assert unloaded != null;
+ assert unloaded.size() == 1;
+
+ // check the count
+ long pvcscount = contentSourceManager.getPackageVersionCountFromContentSource(overlord, contentSourceId);
+ assert (pvcscount == 1) : "-->" + pvcscount;
+
+ // this is the new one we just added - we'll pass this to our next merge as the previous state
+ PackageVersionContentSource addedPVCS = unloaded.get(0);
+ assert addedPVCS.getPackageVersionContentSourcePK().getPackageVersion().getFileSize() == 1234L;
+ previous.put(key, addedPVCS);
+
+ System.out.println("content source merge ADD works!");
+
+ // create a new report that updates the one we just added
+ report = new PackageSyncReport();
+ details.setFileSize(9999L);
+ report.addUpdatedPackage(details);
+
+ // UPDATE: merge the report!
+ results = contentSourceManager.mergePackageSyncReport(contentSource, repo, report, previous, results);
+ assert results != null;
+
+ // see the package version is still assigned to the content source
+ inCS = contentSourceManager.getPackageVersionsFromContentSource(overlord, contentSourceId, pc);
+ assert inCS != null;
+ assert inCS.size() == 1 : inCS;
+
+ // it should still be unloaded, make sure and check that it really was updated
+ unloaded = contentSourceManager.getUnloadedPackageVersionsFromContentSourceInRepo(overlord,
+ contentSourceId, repoId, pc);
+ assert unloaded != null;
+ assert unloaded.size() == 1;
+ assert unloaded.get(0).getPackageVersionContentSourcePK().getPackageVersion().getFileSize() == 9999L;
+
+ System.out.println("content source merge UPDATE works!");
+
+ // create a report that removes the one we added/updated, our 'previous' map is still valid
+ report = new PackageSyncReport();
+ report.addDeletePackage(details);
+
+ // REMOVE: merge the report!
+ results = contentSourceManager.mergePackageSyncReport(contentSource, repo, report, previous, results);
+ assert results != null;
+
+ // see the package version is gone
+ inCS = contentSourceManager.getPackageVersionsFromContentSource(overlord, contentSourceId, pc);
+ assert inCS != null;
+ assert inCS.size() == 0 : inCS;
+
+ // check the count - should no longer be any package versions
+ pvcscount = contentSourceManager.getPackageVersionCountFromContentSource(overlord, contentSourceId);
+ assert (pvcscount == 0) : "-->" + pvcscount;
+
+ System.out.println("content source merge REMOVE works!");
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ try {
+ if (repoId != 0) {
+ repoManager.deleteRepo(overlord, repoId);
+ }
+ if (contentSourceId != 0) {
+ contentSourceManager.deleteContentSource(overlord, contentSourceId);
+ }
+
+ contentSourceMetadataManager.registerTypes(new HashSet<ContentSourceType>());
+ } catch (Throwable t) {
+ }
+ }
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testMergeSyncReportAddRemoveUpdateWithRepo() throws Exception {
+ PageControl pc = PageControl.getUnlimitedInstance();
+ int contentSourceId = 0;
+ int repoId = 0;
+
+ try {
+ // create content source type and content source and repo
+ ContentSourceType type = new ContentSourceType("testMergeSyncReportAMU2CST");
+ Set<ContentSourceType> types = new HashSet<ContentSourceType>();
+ types.add(type);
+ contentSourceMetadataManager.registerTypes(types); // this blows away any previous existing types
+ ContentSource contentSource = new ContentSource("testMergeSyncReportAMU2CS", type);
+ contentSource.setLazyLoad(true);
+ contentSource.setDownloadMode(DownloadMode.DATABASE);
+ contentSource = contentSourceManager.simpleCreateContentSource(overlord, contentSource);
+ contentSourceId = contentSource.getId();
+ assert contentSourceId > 0;
+
+ Repo repo = new Repo("testMergeSyncReportAMU2Ch");
+ repo = repoManager.createRepo(overlord, repo);
+ repoId = repo.getId();
+ assert repoId > 0;
+ repoManager.addContentSourcesToRepo(overlord, repoId, new int[] { contentSourceId });
+
+ // just make sure there are no package versions yet
+ assert 0 == contentSourceManager.getPackageVersionCountFromContentSource(overlord, contentSourceId);
+ assert 0 == repoManager.getPackageVersionCountFromRepo(overlord, repoId);
+
+ // need this to pass to merge
+ RepoSyncResults results = new RepoSyncResults(repo);
+ results = repoManager.persistRepoSyncResults(results);
+ assert results != null;
+
+ // this report will add a mapping to PV->CS
+ PackageSyncReport report = new PackageSyncReport();
+ ContentProviderPackageDetailsKey key = new ContentProviderPackageDetailsKey("testARU2Foo", "testARU2Ver",
+ packageType1.getName(), architecture1.getName(), resourceType1.getName(), resourceType1.getPlugin());
+ ContentProviderPackageDetails details = new ContentProviderPackageDetails(key);
+ details.setLocation("dummy-location-aru");
+ report.addNewPackage(details);
+ Map<ContentProviderPackageDetailsKey, PackageVersionContentSource> previous;
+ previous = new HashMap<ContentProviderPackageDetailsKey, PackageVersionContentSource>();
+
+ // ADD: merge the report!
+ results = contentSourceManager.mergePackageSyncReport(contentSource, repo, report, previous, results);
+ assert results != null;
+
+ List<PackageVersionContentSource> unloaded;
+ unloaded = contentSourceManager.getUnloadedPackageVersionsFromContentSourceInRepo(overlord,
+ contentSourceId, repoId, pc);
+ assert unloaded != null;
+ assert unloaded.size() == 1;
+
+ // check the count to make sure the pv was added to the repo
+ assert 1 == contentSourceManager.getPackageVersionCountFromContentSource(overlord, contentSourceId);
+ assert 1 == repoManager.getPackageVersionCountFromRepo(overlord, repoId);
+
+ // this is the new one we just added - we'll pass this to our next merge as the previous state
+ PackageVersionContentSource addedPVCS = unloaded.get(0);
+ previous.put(key, addedPVCS);
+
+ // create a report that removes the one we added
+ report = new PackageSyncReport();
+ report.addDeletePackage(details);
+
+ // REMOVE: merge the report!
+ results = contentSourceManager.mergePackageSyncReport(contentSource, repo, report, previous, results);
+ assert results != null;
+
+ // check the count - since the pv does not have a provider nor an installed package,
+ // is it removed from the repo as well
+ assert 0 == contentSourceManager.getPackageVersionCountFromContentSource(overlord, contentSourceId);
+ long pvCountFromRepo = repoManager.getPackageVersionCountFromRepo(overlord, repoId);
+ assert 0 == pvCountFromRepo : "Expected: 0, Found: " + pvCountFromRepo;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ try {
+ if (repoId != 0) {
+ repoManager.deleteRepo(overlord, repoId);
+ }
+
+ if (contentSourceId != 0) {
+ contentSourceManager.deleteContentSource(overlord, contentSourceId);
+ }
+
+ contentSourceMetadataManager.registerTypes(new HashSet<ContentSourceType>());
+ } catch (Throwable t) {
+ }
+ }
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testDeleteContentSource() throws Exception {
+ PageControl pc = PageControl.getUnlimitedInstance();
+ // getTransactionManager().begin();
+ try {
+ ContentSourceType type = null;
+ ContentSource contentSource = null;
+
+ int csTypeCount = contentSourceManager.getAllContentSourceTypes().size();
+ List csList = contentSourceManager.getAllContentSources(overlord, pc);
+ int csCount = contentSourceManager.getAllContentSources(overlord, pc).size();
+
+ // create the content source type
+ type = new ContentSourceType("testDel-" + RandomStringUtils.randomAlphanumeric(6));
+
+ Set<ContentSourceType> types = new HashSet<ContentSourceType>();
+ types.add(type);
+ contentSourceMetadataManager.registerTypes(types); // this blows away any previous existing types
+ type = contentSourceManager.getContentSourceType(type.getName());
+ assert type != null;
+ assert type.getId() > 0;
+
+ // test the getAll API
+ assert (csTypeCount + 1) == contentSourceManager.getAllContentSourceTypes().size();
+
+ // create the content source
+ contentSource = new ContentSource("testDel-" + RandomStringUtils.randomAlphanumeric(6), type);
+ contentSource = contentSourceManager.simpleCreateContentSource(overlord, contentSource);
+ assert contentSource != null;
+ int contentSourceId = contentSource.getId();
+ assert contentSourceId > 0;
+
+ // test the getAll API
+ assert (csCount + 1) == contentSourceManager.getAllContentSources(overlord, pc).size();
+
+ // create a repo and associate the new content source with it
+ Repo repo = new Repo("testDel-" + RandomStringUtils.randomAlphanumeric(6));
+ repoManager.createRepo(overlord, repo);
+ repoManager.addContentSourcesToRepo(overlord, repo.getId(), new int[] { contentSourceId });
+
+ // try to delete the content source
+ assert null != contentSourceManager.getContentSource(overlord, contentSourceId) : "should exist";
+ contentSourceManager.deleteContentSource(overlord, contentSourceId);
+ assert null == contentSourceManager.getContentSource(overlord, contentSourceId) : "should have been deleted";
+
+ // I need to clean these up now
+ repoManager.deleteRepo(overlord, repo.getId());
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ contentSourceMetadataManager.registerTypes(new HashSet<ContentSourceType>());
+ }
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testUpdateContentSourceNoConfig() throws Exception {
+ try {
+ ContentSourceType type = null;
+ ContentSource contentSource = null;
+
+ // create the content source type
+ type = new ContentSourceType("testUpdateContentSourceCST");
+ Set<ContentSourceType> types = new HashSet<ContentSourceType>();
+ types.add(type);
+ contentSourceMetadataManager.registerTypes(types); // this blows away any previous existing types
+ type = contentSourceManager.getContentSourceType(type.getName());
+ assert type != null;
+ assert type.getId() > 0;
+
+ // create the content source - note it doesn't have any config yet
+ contentSource = new ContentSource("testUpdateContentSource", type);
+ contentSource = contentSourceManager.simpleCreateContentSource(overlord, contentSource);
+ assert contentSource != null;
+ int contentSourceId = contentSource.getId();
+ assert contentSourceId > 0;
+
+ // now update its description
+ ContentSource loaded = contentSourceManager.getContentSource(overlord, contentSourceId);
+ assert loaded != null : "should exist";
+ assert loaded.getDescription() == null;
+ loaded.setDescription("new updated description");
+ loaded = contentSourceManager.updateContentSource(overlord, loaded, false);
+ assert loaded != null : "should have been updated";
+ loaded = contentSourceManager.getContentSource(overlord, contentSourceId);
+ assert loaded.getDescription().equals("new updated description");
+
+ // now give it a config
+ assert loaded.getConfiguration() == null : "should not have a config yet";
+ Configuration config = new Configuration();
+ config.put(new PropertySimple("updateCSName", "updateCSValue"));
+ loaded.setConfiguration(config);
+ loaded = contentSourceManager.updateContentSource(overlord, loaded, false);
+ assert loaded != null : "should have been updated";
+ config = loaded.getConfiguration();
+ assert config != null : "should have a config now";
+ assert config.getSimple("updateCSName").getStringValue().equals("updateCSValue") : config;
+ assert loaded.getDescription().equals("new updated description") : "desc should still be there";
+
+ // delete the content source
+ contentSourceManager.deleteContentSource(overlord, contentSourceId);
+ assert null == contentSourceManager.getContentSource(overlord, contentSourceId) : "should have been deleted";
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ contentSourceMetadataManager.registerTypes(new HashSet<ContentSourceType>());
+ }
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testUpdateContentSourceConfig() throws Exception {
+ try {
+ ContentSourceType type = null;
+ ContentSource contentSource = null;
+
+ // create the content source type
+ type = new ContentSourceType("testUpdateContentSourceCST2");
+ Set<ContentSourceType> types = new HashSet<ContentSourceType>();
+ types.add(type);
+ contentSourceMetadataManager.registerTypes(types); // this blows away any previous existing types
+ type = contentSourceManager.getContentSourceType(type.getName());
+ assert type != null;
+ assert type.getId() > 0;
+
+ // create the content source - note it has a config that should be persisted
+ Configuration config = new Configuration();
+ config.put(new PropertySimple("updateCSName", "updateCSValue"));
+ contentSource = new ContentSource("testUpdateContentSource2", type);
+ contentSource.setConfiguration(config);
+ contentSource = contentSourceManager.simpleCreateContentSource(overlord, contentSource);
+ assert contentSource != null;
+ int contentSourceId = contentSource.getId();
+ assert contentSourceId > 0;
+
+ // now update its config
+ ContentSource loaded = contentSourceManager.getContentSource(overlord, contentSourceId);
+ assert loaded != null : "should exist";
+ assert loaded.getConfiguration() != null;
+ assert loaded.getConfiguration().getSimple("updateCSName").getStringValue().equals("updateCSValue");
+ loaded.getConfiguration().getSimple("updateCSName").setStringValue("UPDATED");
+ loaded = contentSourceManager.updateContentSource(overlord, loaded, false);
+ assert loaded != null : "should have been updated";
+ assert loaded.getConfiguration() != null;
+ assert loaded.getConfiguration().getSimple("updateCSName").getStringValue().equals("UPDATED");
+ loaded = contentSourceManager.getContentSource(overlord, contentSourceId);
+ assert loaded != null : "should exist";
+ assert loaded.getConfiguration() != null;
+ assert loaded.getConfiguration().getSimple("updateCSName").getStringValue().equals("UPDATED");
+
+ // now delete its config
+ loaded.setConfiguration(null);
+ loaded = contentSourceManager.updateContentSource(overlord, loaded, false);
+ assert loaded != null : "should have been updated";
+ assert loaded.getConfiguration() == null : "config should be null -> " + loaded.getConfiguration();
+
+ // delete the content source
+ contentSourceManager.deleteContentSource(overlord, contentSourceId);
+ assert null == contentSourceManager.getContentSource(overlord, contentSourceId) : "should have been deleted";
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ contentSourceMetadataManager.registerTypes(new HashSet<ContentSourceType>());
+ }
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testConstraintViolation() throws Exception {
+ ContentSourceType type = null;
+ ContentSource contentSource = null;
+
+ try {
+ type = new ContentSourceType("testConstraintViolationCST");
+ Set<ContentSourceType> types = new HashSet<ContentSourceType>();
+ types.add(type);
+ contentSourceMetadataManager.registerTypes(types); // this blows away any previous existing types
+ type = contentSourceManager.getContentSourceType(type.getName());
+ assert type != null;
+ assert type.getId() > 0;
+ contentSource = new ContentSource("testConstraintViolation", type);
+ contentSource = contentSourceManager.simpleCreateContentSource(overlord, contentSource);
+ assert contentSource != null;
+ int contentSourceId = contentSource.getId();
+ assert contentSourceId > 0;
+
+ ContentSource dup = new ContentSource("testConstraintViolation", type);
+
+ try {
+ contentSourceManager.simpleCreateContentSource(overlord, dup);
+ assert false : "Should not have been able to create the same content source";
+ } catch (Exception expected) {
+ } finally {
+ contentSourceManager.deleteContentSource(overlord, contentSourceId);
+ contentSourceMetadataManager.registerTypes(new HashSet<ContentSourceType>());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
+ /**
+ * This tests that when you merge a sync report and a repo is associated with a content source, the repo gets
+ * the package versions assigned to it. It also tests that deleting repo and content source will purge orphaned
+ * PVs.
+ *
+ * @throws Exception
+ */
+ @Test(enabled = TESTS_ENABLED)
+ public void testMergeWithRepo() throws Exception {
+ try {
+ ContentSourceType type = null;
+ ContentSource contentSource = null;
+
+ // create the content source type
+ type = new ContentSourceType("testMergeWithRepoCST");
+ Set<ContentSourceType> types = new HashSet<ContentSourceType>();
+ types.add(type);
+ contentSourceMetadataManager.registerTypes(types); // this blows away any previous existing types
+ type = contentSourceManager.getContentSourceType(type.getName());
+ assert type != null;
+ assert type.getId() > 0;
+
+ // create the content source
+ contentSource = new ContentSource("testMergeWithRepoCS", type);
+ contentSource = contentSourceManager.simpleCreateContentSource(overlord, contentSource);
+ assert contentSource != null;
+ int contentSourceId = contentSource.getId();
+ assert contentSourceId > 0;
+
+ // create a repo and associate the new content source with it
+ Repo repo = new Repo("testMergeWithRepo");
+ repo = repoManager.createRepo(overlord, repo);
+ repoManager.addContentSourcesToRepo(overlord, repo.getId(), new int[] { contentSourceId });
+
+ // this report will add a mapping to PV->CS
+ // we didn't set up any mappings like that yet - this will be the first one
+ // since a repo has this CS - the repo->PV will also get mapped
+ PackageSyncReport report = new PackageSyncReport();
+ ContentProviderPackageDetailsKey key = new ContentProviderPackageDetailsKey("testMergeWithRepofoo",
+ "testMergeWithRepo-Version", packageType1.getName(), architecture1.getName(), resourceType1.getName(),
+ resourceType1.getPlugin());
+ ContentProviderPackageDetails details = new ContentProviderPackageDetails(key);
+ details.setExtraProperties(new Configuration());
+ details.getExtraProperties().put(new PropertySimple("hello", "world"));
+ details.setLocation("dummy-location");
+ details.setFileSize(0L); // under the covers this ends up allowing us to create a package bits of size 0
+ report.addNewPackage(details);
+ Map<ContentProviderPackageDetailsKey, PackageVersionContentSource> previous;
+ previous = new HashMap<ContentProviderPackageDetailsKey, PackageVersionContentSource>();
+
+ RepoSyncResults results = new RepoSyncResults(repo);
+ results = repoManager.persistRepoSyncResults(results);
+ assert results != null;
+
+ contentSourceManager.mergePackageSyncReport(contentSource, repo, report, previous, results);
+
+ List<PackageVersion> inRepo;
+ inRepo = repoManager.findPackageVersionsInRepo(overlord, repo.getId(), PageControl.getUnlimitedInstance());
+ assert inRepo != null;
+ assert inRepo.size() == 1;
+ assert "testMergeWithRepo-Version".equals(inRepo.get(0).getVersion());
+
+ // sanity check - make sure our own entity manager can find the PV entity
+ getTransactionManager().begin();
+ try {
+ PackageVersion foundPv = getEntityManager().find(PackageVersion.class, inRepo.get(0).getId());
+ assert foundPv != null;
+ assert foundPv.getExtraProperties() != null;
+ assert foundPv.getExtraProperties().getSimple("hello").getStringValue().equals("world");
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ // delete the content source first
+ contentSourceManager.deleteContentSource(overlord, contentSourceId);
+
+ // make sure our PV isn't orphaned yet! It is directly related to the repo still
+ getTransactionManager().begin();
+ try {
+ assert null != getEntityManager().find(PackageVersion.class, inRepo.get(0).getId());
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ // delete the repo - this finally orphans the PV, so the PV should get deleted automatically
+ repoManager.deleteRepo(overlord, repo.getId());
+
+ // test to make sure we purged the orphaned package version (since both content source and repo are gone now)
+ getTransactionManager().begin();
+ try {
+ assert null == getEntityManager().find(PackageVersion.class, inRepo.get(0).getId());
+ } finally {
+ getTransactionManager().rollback();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ contentSourceMetadataManager.registerTypes(new HashSet<ContentSourceType>());
+ }
+ }
+
+ private void setupTestEnvironment() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ try {
+ architecture1 = em.find(Architecture.class, 1);
+ architecture2 = em.find(Architecture.class, 2);
+
+ resourceType1 = new ResourceType("platform-" + System.currentTimeMillis(), "TestPlugin",
+ ResourceCategory.PLATFORM, null);
+ em.persist(resourceType1);
+
+ // Add package types to resource type
+ packageType1 = new PackageType();
+ packageType1.setName("package1-" + System.currentTimeMillis());
+ packageType1.setDescription("");
+ packageType1.setCategory(PackageCategory.DEPLOYABLE);
+ packageType1.setDisplayName("TestResourcePackage");
+ packageType1.setCreationData(true);
+ packageType1.setResourceType(resourceType1);
+ em.persist(packageType1);
+
+ packageType2 = new PackageType();
+ packageType2.setName("package2-" + System.currentTimeMillis());
+ packageType2.setDescription("");
+ packageType2.setCategory(PackageCategory.DEPLOYABLE);
+ packageType2.setDisplayName("TestResourcePackage2");
+ packageType2.setCreationData(true);
+ packageType2.setResourceType(resourceType1);
+ em.persist(packageType2);
+
+ packageType3 = new PackageType();
+ packageType3.setName("package3-" + System.currentTimeMillis());
+ packageType3.setDescription("");
+ packageType3.setCategory(PackageCategory.DEPLOYABLE);
+ packageType3.setDisplayName("TestResourcePackage3");
+ packageType3.setCreationData(true);
+ packageType3.setResourceType(resourceType1);
+ em.persist(packageType3);
+
+ packageType4 = new PackageType();
+ packageType4.setName("package4-" + System.currentTimeMillis());
+ packageType4.setDescription("");
+ packageType4.setCategory(PackageCategory.DEPLOYABLE);
+ packageType4.setDisplayName("TestResourcePackage4");
+ packageType4.setCreationData(true);
+ packageType4.setResourceType(resourceType1);
+ em.persist(packageType4);
+
+ resourceType1.addPackageType(packageType1);
+ resourceType1.addPackageType(packageType2);
+ resourceType1.addPackageType(packageType3);
+
+ // Package 1 - Contains 2 versions
+ package1 = new Package("Package1", packageType1);
+
+ package1.addVersion(new PackageVersion(package1, "1.0.0", architecture1));
+ package1.addVersion(new PackageVersion(package1, "2.0.0", architecture1));
+
+ em.persist(package1);
+
+ // Package 2 - Contains 2 versions
+ package2 = new Package("Package2", packageType2);
+
+ package2.addVersion(new PackageVersion(package2, "1.0.0", architecture1));
+ package2.addVersion(new PackageVersion(package2, "2.0.0", architecture1));
+
+ em.persist(package2);
+
+ // Package 3 - Contains 1 version
+ package3 = new Package("Package3", packageType3);
+
+ package3.addVersion(new PackageVersion(package3, "1.0.0", architecture1));
+
+ em.persist(package3);
+
+ // Package 4 - Contains 2 versions, the first is installed
+ package4 = new Package("Package4", packageType4);
+
+ PackageVersion package4Installed = new PackageVersion(package4, "1.0.0", architecture1);
+ package4.addVersion(package4Installed);
+ package4.addVersion(new PackageVersion(package4, "2.0.0", architecture1));
+
+ em.persist(package4);
+
+ // Package 5 - Contains 1 version, it is installed
+ package5 = new Package("Package5", packageType4);
+
+ PackageVersion package5Installed = new PackageVersion(package5, "1.0.0", architecture1);
+ package5.addVersion(package5Installed);
+
+ em.persist(package5);
+
+ // Create resource against which we'll merge the discovery report
+ resource1 = new Resource("parent" + System.currentTimeMillis(), "name", resourceType1);
+ resource1.setUuid("" + new Random().nextInt());
+ em.persist(resource1);
+
+ // Install packages on the resource
+ installedPackage1 = new InstalledPackage();
+ installedPackage1.setResource(resource1);
+ installedPackage1.setPackageVersion(package4Installed);
+ resource1.addInstalledPackage(installedPackage1);
+
+ installedPackage2 = new InstalledPackage();
+ installedPackage2.setResource(resource1);
+ installedPackage2.setPackageVersion(package4Installed);
+ resource1.addInstalledPackage(installedPackage2);
+
+ installedPackage1.setResource(resource1);
+ installedPackage2.setResource(resource1);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ getTransactionManager().rollback();
+ throw e;
+ }
+ } finally {
+ em.close();
+ }
+ }
+
+ private void tearDownTestEnvironment() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ try {
+ resource1 = em.find(Resource.class, resource1.getId());
+ for (InstalledPackage ip : resource1.getInstalledPackages()) {
+ em.remove(ip);
+ }
+
+ package1 = em.find(Package.class, package1.getId());
+ em.remove(package1);
+
+ package2 = em.find(Package.class, package2.getId());
+ em.remove(package2);
+
+ package3 = em.find(Package.class, package3.getId());
+ em.remove(package3);
+
+ package4 = em.find(Package.class, package4.getId());
+ em.remove(package4);
+
+ package5 = em.find(Package.class, package5.getId());
+ em.remove(package5);
+
+ packageType1 = em.find(PackageType.class, packageType1.getId());
+ em.remove(packageType1);
+
+ packageType2 = em.find(PackageType.class, packageType2.getId());
+ em.remove(packageType2);
+
+ packageType3 = em.find(PackageType.class, packageType3.getId());
+ em.remove(packageType3);
+
+ packageType4 = em.find(PackageType.class, packageType4.getId());
+ em.remove(packageType4);
+
+ ResourceTreeHelper.deleteResource(em, resource1);
+
+ resourceType1 = em.find(ResourceType.class, resourceType1.getId());
+ em.remove(resourceType1);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ getTransactionManager().rollback();
+ throw e;
+ }
+ } finally {
+ em.close();
+ }
+ }
+
+ /**
+ * This is a temporary method to undo the messiness of this test in the past. The test will be changed to
+ * clean up after itself, however this call will set the state to a clean one for environments that have
+ * run the previous incarnation.
+ *
+ * @throws Exception
+ */
+ private void cleanupPreviousTestRuns() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ try {
+ Query query;
+ List results;
+
+ query = em.createNamedQuery(ContentSource.QUERY_FIND_BY_NAME_AND_TYPENAME);
+ query.setParameter("name", "testUpdateContentSource");
+ query.setParameter("typeName", "testUpdateContentSourceCST");
+ results = query.getResultList();
+
+ if (results.size() > 0) {
+ ContentSource deleteMe = (ContentSource) results.get(0);
+ em.remove(deleteMe);
+ }
+
+ query = em.createNamedQuery(ContentSource.QUERY_FIND_BY_NAME_AND_TYPENAME);
+ query.setParameter("name", "testUpdateContentSource2");
+ query.setParameter("typeName", "testUpdateContentSourceCST2");
+ results = query.getResultList();
+
+ if (results.size() > 0) {
+ ContentSource deleteMe = (ContentSource) results.get(0);
+ em.remove(deleteMe);
+ }
+
+ query = em.createNamedQuery(ContentSource.QUERY_FIND_BY_NAME_AND_TYPENAME);
+ query.setParameter("name", "testConstraintViolation");
+ query.setParameter("typeName", "testConstraintViolationCST");
+ results = query.getResultList();
+
+ if (results.size() > 0) {
+ ContentSource deleteMe = (ContentSource) results.get(0);
+ em.remove(deleteMe);
+ }
+
+ query = em.createNamedQuery(ContentSourceType.QUERY_FIND_BY_NAME);
+ query.setParameter("name", "testUpdateContentSourceCST");
+ results = query.getResultList();
+
+ if (results.size() > 0) {
+ ContentSourceType deleteMe = (ContentSourceType) results.get(0);
+ em.remove(deleteMe);
+ }
+
+ query = em.createNamedQuery(ContentSourceType.QUERY_FIND_BY_NAME);
+ query.setParameter("name", "testUpdateContentSourceCST2");
+ results = query.getResultList();
+
+ if (results.size() > 0) {
+ ContentSourceType deleteMe = (ContentSourceType) results.get(0);
+ em.remove(deleteMe);
+ }
+
+ query = em.createNamedQuery(ContentSourceType.QUERY_FIND_BY_NAME);
+ query.setParameter("name", "testConstraintViolationCST");
+ results = query.getResultList();
+
+ if (results.size() > 0) {
+ ContentSourceType deleteMe = (ContentSourceType) results.get(0);
+ em.remove(deleteMe);
+ }
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ getTransactionManager().rollback();
+ throw e;
+ }
+ } finally {
+ em.close();
+ }
+
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentUIManagerBeanEligiblePackagesTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentUIManagerBeanEligiblePackagesTest.java
new file mode 100644
index 0000000..b382347
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentUIManagerBeanEligiblePackagesTest.java
@@ -0,0 +1,339 @@
+/*
+ * 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.enterprise.server.content.test;
+
+import java.util.Random;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+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.auth.Subject;
+import org.rhq.core.domain.content.Architecture;
+import org.rhq.core.domain.content.InstalledPackage;
+import org.rhq.core.domain.content.Package;
+import org.rhq.core.domain.content.PackageCategory;
+import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.domain.content.ProductVersionPackageVersion;
+import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.content.RepoPackageVersion;
+import org.rhq.core.domain.content.ResourceRepo;
+import org.rhq.core.domain.content.composite.PackageVersionComposite;
+import org.rhq.core.domain.resource.ProductVersion;
+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.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.content.ContentUIManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.ResourceTreeHelper;
+
+/**
+ * Specifically tests the logic to ensure the query to find what packages can be installed on a resource.
+ *
+ * @author Jason Dobies
+ */
+public class ContentUIManagerBeanEligiblePackagesTest extends AbstractEJB3Test {
+
+ private static final boolean ENABLE_TESTS = true;
+
+ private final Log log = LogFactory.getLog(this.getClass());
+
+ private ContentUIManagerLocal contentUIManager;
+ private SubjectManagerLocal subjectManager;
+
+ private Architecture architecture;
+ private PackageType packageType1;
+
+ private Package package1;
+ private Package package2;
+ private Package package3;
+ private Package package4;
+
+ private RepoPackageVersion repoPackageVersion1;
+ private RepoPackageVersion repoPackageVersion2;
+ private RepoPackageVersion repoPackageVersion3;
+ private RepoPackageVersion repoPackageVersion4;
+
+ private InstalledPackage installedPackage1;
+
+ private Resource resource;
+ private ResourceType resourceType;
+
+ private Repo repo1;
+ private Repo repo2;
+
+ private ResourceRepo resourceRepo1;
+ private ResourceRepo resourceRepo2;
+
+ private ProductVersion productVersion1;
+ private ProductVersion productVersion2;
+
+ // Setup --------------------------------------------
+
+ @BeforeClass
+ public void setupBeforeClass() throws Exception {
+ contentUIManager = LookupUtil.getContentUIManager();
+ subjectManager = LookupUtil.getSubjectManager();
+ }
+
+ @BeforeMethod
+ public void populateDatabase() throws Exception {
+ setupTestEnvironment();
+ }
+
+ @AfterMethod
+ public void cleanDatabase() throws Exception {
+ tearDownTestEnvironment();
+ }
+
+ // Test Cases --------------------------------------------
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testEligiblePackagesLogic() throws Exception {
+
+ Subject overlord = subjectManager.getOverlord();
+ PageControl pageControl = new PageControl(0, 100);
+
+ PageList<PackageVersionComposite> pageList = contentUIManager.getPackageVersionCompositesByFilter(overlord,
+ resource.getId(), null, pageControl);
+
+ assert pageList != null : "Null page list returned from query";
+
+ /* Expected results:
+ - Package 1 - Included in the list; it has no product version thus is always applicable
+ - Package 2 - Included in the list; it includes the resource's version in its product version list
+ - Package 3 - Not included; it contains a product version list but not the resource's version
+ - Package 4 - Not included; it has no product version but it is already installed on the resource
+
+ */
+
+ for (PackageVersionComposite pvc : pageList.getValues()) {
+ log.warn("Package: " + pvc.getPackageName());
+ }
+
+ assert pageList.getTotalSize() == 2 : "Incorrect total size found. Found: " + pageList.getTotalSize();
+ }
+
+ private void setupTestEnvironment() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ try {
+ architecture = em.find(Architecture.class, 1);
+
+ resourceType = new ResourceType("resourcetype-" + System.currentTimeMillis(), "TestPlugin",
+ ResourceCategory.PLATFORM, null);
+ em.persist(resourceType);
+
+ // Create resource against which we'll be retrieving packages
+ resource = new Resource("parent" + System.currentTimeMillis(), "name", resourceType);
+ resource.setUuid("" + new Random().nextInt());
+ resource.setVersion("1.0");
+ em.persist(resource);
+
+ // Product versions
+ productVersion1 = new ProductVersion();
+ productVersion1.setVersion("1.0");
+ productVersion1.setResourceType(resourceType);
+ em.persist(productVersion1);
+
+ resource.setProductVersion(productVersion1);
+
+ productVersion2 = new ProductVersion();
+ productVersion2.setVersion("2.0");
+ productVersion2.setResourceType(resourceType);
+ em.persist(productVersion2);
+
+ // Add package types to resource type
+ packageType1 = new PackageType();
+ packageType1.setName("package1-" + System.currentTimeMillis());
+ packageType1.setDescription("");
+ packageType1.setCategory(PackageCategory.DEPLOYABLE);
+ packageType1.setDisplayName("TestResourcePackage");
+ packageType1.setCreationData(true);
+ packageType1.setResourceType(resourceType);
+ em.persist(packageType1);
+
+ resourceType.addPackageType(packageType1);
+
+ // Package 1 - No product versions specified
+ package1 = new Package("Package1", packageType1);
+ PackageVersion packageVersion1 = new PackageVersion(package1, "1.0.0", architecture);
+ package1.addVersion(packageVersion1);
+
+ em.persist(package1);
+
+ // Package 2 - Has list of product versions that contains the resource's version
+ package2 = new Package("Package2", packageType1);
+ PackageVersion packageVersion2 = new PackageVersion(package2, "1.0.0", architecture);
+ ProductVersionPackageVersion pvpv1 = packageVersion2.addProductVersion(productVersion1);
+ ProductVersionPackageVersion pvpv2 = packageVersion2.addProductVersion(productVersion2);
+ package2.addVersion(packageVersion2);
+
+ em.persist(package2);
+ em.persist(pvpv1);
+ em.persist(pvpv2);
+
+ // Package 3 - Has list of product versions where the resource version is not included
+ package3 = new Package("Package3", packageType1);
+ PackageVersion packageVersion3 = new PackageVersion(package3, "1.0.0", architecture);
+ ProductVersionPackageVersion pvpv3 = packageVersion3.addProductVersion(productVersion2);
+ package3.addVersion(packageVersion3);
+
+ em.persist(package3);
+ em.persist(pvpv3);
+
+ // Package 4 - No product version restriction, but already installed on the resource
+ package4 = new Package("Package4", packageType1);
+ PackageVersion packageVersion4 = new PackageVersion(package4, "1.0.0", architecture);
+ package4.addVersion(packageVersion4);
+
+ em.persist(package4);
+
+ // Wire up the repo to the resource and add all of these packages to it
+ repo1 = new Repo("repo-" + RandomStringUtils.randomNumeric(6));
+ em.persist(repo1);
+
+ repoPackageVersion1 = repo1.addPackageVersion(packageVersion1);
+ repoPackageVersion2 = repo1.addPackageVersion(packageVersion2);
+ repoPackageVersion3 = repo1.addPackageVersion(packageVersion3);
+ repoPackageVersion4 = repo1.addPackageVersion(packageVersion4);
+
+ em.persist(repoPackageVersion1);
+ em.persist(repoPackageVersion2);
+ em.persist(repoPackageVersion3);
+ em.persist(repoPackageVersion4);
+
+ resourceRepo1 = repo1.addResource(resource);
+ em.persist(resourceRepo1);
+
+ // Subscribe the resource to a second repo to make sure the joins won't duplicate stuff
+ repo2 = new Repo("test-" + RandomStringUtils.randomNumeric(6));
+ em.persist(repo2);
+
+ resourceRepo2 = repo2.addResource(resource);
+ em.persist(resourceRepo2);
+
+ installedPackage1 = new InstalledPackage();
+ installedPackage1.setResource(resource);
+ installedPackage1.setPackageVersion(packageVersion4);
+ resource.addInstalledPackage(installedPackage1);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ getTransactionManager().rollback();
+ throw e;
+ }
+ } finally {
+ em.close();
+ }
+ }
+
+ private void tearDownTestEnvironment() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ try {
+ Query q = em.createNamedQuery(RepoPackageVersion.DELETE_BY_REPO_ID);
+ q.setParameter("repoId", repo1.getId());
+ q.executeUpdate();
+
+ q = em.createNamedQuery(ResourceRepo.DELETE_BY_RESOURCE_ID);
+ q.setParameter("resourceId", resource.getId());
+ q.executeUpdate();
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ getTransactionManager().rollback();
+ throw e;
+ }
+ } finally {
+ em.close();
+ }
+
+ getTransactionManager().begin();
+ em = getEntityManager();
+
+ try {
+ try {
+ resource = em.find(Resource.class, resource.getId());
+ for (InstalledPackage ip : resource.getInstalledPackages()) {
+ em.remove(ip);
+ }
+
+ package1 = em.find(Package.class, package1.getId());
+ em.remove(package1);
+
+ package2 = em.find(Package.class, package2.getId());
+ em.remove(package2);
+
+ package3 = em.find(Package.class, package3.getId());
+ em.remove(package3);
+
+ package4 = em.find(Package.class, package4.getId());
+ em.remove(package4);
+
+ packageType1 = em.find(PackageType.class, packageType1.getId());
+ em.remove(packageType1);
+
+ ResourceTreeHelper.deleteResource(em, resource);
+
+ repo1 = em.find(Repo.class, repo1.getId());
+ em.remove(repo1);
+
+ repo2 = em.find(Repo.class, repo2.getId());
+ em.remove(repo2);
+
+ productVersion1 = em.find(ProductVersion.class, productVersion1.getId());
+ em.remove(productVersion1);
+
+ productVersion2 = em.find(ProductVersion.class, productVersion2.getId());
+ em.remove(productVersion2);
+
+ resourceType = em.find(ResourceType.class, resourceType.getId());
+ em.remove(resourceType);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ getTransactionManager().rollback();
+ throw e;
+ }
+ } finally {
+ em.close();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentUIManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentUIManagerBeanTest.java
new file mode 100644
index 0000000..54cfb67
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ContentUIManagerBeanTest.java
@@ -0,0 +1,327 @@
+/*
+ * 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.enterprise.server.content.test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import javax.persistence.EntityManager;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.content.Architecture;
+import org.rhq.core.domain.content.Package;
+import org.rhq.core.domain.content.PackageBits;
+import org.rhq.core.domain.content.PackageBitsBlob;
+import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.domain.content.composite.LoadedPackageBitsComposite;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.enterprise.server.content.ContentManagerLocal;
+import org.rhq.enterprise.server.content.ContentUIManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.SessionTestHelper;
+
+/**
+ * Test case for general {@link org.rhq.enterprise.server.content.ContentUIManagerBean} tests. Any tests that would
+ * require a large DB state prior to running are split off into their own test classes.
+ *
+ * @author Jason Dobies
+ */
+public class ContentUIManagerBeanTest extends AbstractEJB3Test {
+
+ private static final boolean ENABLE_TESTS = true;
+
+ private ContentUIManagerLocal contentUIManager;
+ private ContentManagerLocal contentManager;
+
+ // Setup --------------------------------------------
+
+ @BeforeClass
+ public void setupBeforeClass() throws Exception {
+ contentUIManager = LookupUtil.getContentUIManager();
+ contentManager = LookupUtil.getContentManager();
+ }
+
+ // Test Cases --------------------------------------------
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testPackageBits() throws Throwable {
+ LoadedPackageBitsComposite composite;
+
+ getTransactionManager().begin();
+
+ try {
+ EntityManager em = getEntityManager();
+ Resource resource = SessionTestHelper.createNewResource(em, "testPkgBitsResource");
+ PackageType pkgType = new PackageType("testPkgBitsPT", resource.getResourceType());
+ org.rhq.core.domain.content.Package pkg = new Package("testPkgBitsP", pkgType);
+ Architecture arch = new Architecture("testPkgArch");
+ PackageVersion pkgVer = new PackageVersion(pkg, "1", arch);
+
+ em.persist(pkgType);
+ em.persist(pkg);
+ em.persist(arch);
+ em.persist(pkgVer);
+ em.flush();
+
+ // test that no bits are available right now
+ composite = contentUIManager.getLoadedPackageBitsComposite(pkgVer.getId());
+ assert composite != null;
+ assert composite.getPackageVersionId() == pkgVer.getId();
+ assert composite.getPackageBitsId() == null;
+ assert !composite.isPackageBitsAvailable();
+ assert !composite.isPackageBitsInDatabase();
+
+ // pretend we loaded the bits, but we stored them somewhere other then the DB
+ PackageBits packageBits = createPackageBits(em);
+ pkgVer.setPackageBits(packageBits);
+ pkgVer = em.merge(pkgVer);
+ em.flush();
+
+ // test that the bits are available, but are not stored in the DB
+ composite = contentUIManager.getLoadedPackageBitsComposite(pkgVer.getId());
+ assert composite != null;
+ assert composite.getPackageVersionId() == pkgVer.getId();
+ assert composite.getPackageBitsId() == packageBits.getId();
+ assert composite.isPackageBitsAvailable();
+ assert !composite.isPackageBitsInDatabase();
+
+ // let's make sure there really is no data in the DB
+ packageBits = em.find(PackageBits.class, packageBits.getId());
+ assert packageBits != null;
+ assert packageBits.getBlob().getBits() == null;
+
+ // now lets store some bits in the DB
+ final String DATA = "testPackageBits data";
+ PackageBitsBlob packageBitsBlob = em.find(PackageBitsBlob.class, packageBits.getId());
+ packageBitsBlob.setBits(DATA.getBytes());
+ em.merge(packageBitsBlob);
+ em.flush();
+
+ // test that the bits are available and stored in the DB
+ composite = contentUIManager.getLoadedPackageBitsComposite(pkgVer.getId());
+ assert composite != null;
+ assert composite.getPackageVersionId() == pkgVer.getId();
+ assert composite.getPackageBitsId() == packageBits.getId();
+ assert composite.isPackageBitsAvailable();
+ assert composite.isPackageBitsInDatabase();
+
+ // let's make sure the data really is in the DB
+ packageBits = em.find(PackageBits.class, packageBits.getId());
+ assert packageBits != null;
+ assert DATA.equals(new String(packageBits.getBlob().getBits()));
+
+ ////////////////////////////////////////////////////
+ // create another package version and test with that
+ ////////////////////////////////////////////////////
+ PackageVersion pkgVer2 = new PackageVersion(pkg, "2", arch);
+ em.persist(pkgVer2);
+ em.flush();
+
+ // first make sure the query still gets the right answer for the first pkgVer
+ composite = contentUIManager.getLoadedPackageBitsComposite(pkgVer.getId());
+ assert composite != null;
+ assert composite.getPackageVersionId() == pkgVer.getId();
+ assert composite.getPackageBitsId() == packageBits.getId();
+ assert composite.isPackageBitsAvailable();
+ assert composite.isPackageBitsInDatabase();
+
+ // test that no bits are available right now
+ composite = contentUIManager.getLoadedPackageBitsComposite(pkgVer2.getId());
+ assert composite != null;
+ assert composite.getPackageVersionId() == pkgVer2.getId();
+ assert composite.getPackageBitsId() == null;
+ assert !composite.isPackageBitsAvailable();
+ assert !composite.isPackageBitsInDatabase();
+
+ // pretend we loaded the bits, but we stored them somewhere other then the DB
+ PackageBits packageBits2 = createPackageBits(em);
+ pkgVer2.setPackageBits(packageBits2);
+ pkgVer2 = em.merge(pkgVer2);
+ em.flush();
+
+ // make sure the query still gets the right answer for the first pkgVer
+ composite = contentUIManager.getLoadedPackageBitsComposite(pkgVer.getId());
+ assert composite != null;
+ assert composite.getPackageVersionId() == pkgVer.getId();
+ assert composite.getPackageBitsId() == packageBits.getId();
+ assert composite.isPackageBitsAvailable();
+ assert composite.isPackageBitsInDatabase();
+
+ // test that the bits are available, but are not stored in the DB
+ composite = contentUIManager.getLoadedPackageBitsComposite(pkgVer2.getId());
+ assert composite != null;
+ assert composite.getPackageVersionId() == pkgVer2.getId();
+ assert composite.getPackageBitsId() == packageBits2.getId();
+ assert composite.isPackageBitsAvailable();
+ assert !composite.isPackageBitsInDatabase();
+
+ // let's make sure there really is no data in the DB
+ packageBits2 = em.find(PackageBits.class, packageBits2.getId());
+ assert packageBits2 != null;
+ assert packageBits2.getBlob().getBits() == null;
+
+ // now lets store some bits in the DB
+ final String DATA2 = "testPackageBits more data";
+ packageBits2.getBlob().setBits(DATA2.getBytes());
+ em.merge(packageBits2.getBlob());
+ em.flush();
+
+ // make sure the query still gets the right answer for the first pkgVer
+ composite = contentUIManager.getLoadedPackageBitsComposite(pkgVer.getId());
+ assert composite != null;
+ assert composite.getPackageVersionId() == pkgVer.getId();
+ assert composite.getPackageBitsId() == packageBits.getId();
+ assert composite.isPackageBitsAvailable();
+ assert composite.isPackageBitsInDatabase();
+
+ // test that the bits are available and stored in the DB
+ composite = contentUIManager.getLoadedPackageBitsComposite(pkgVer2.getId());
+ assert composite != null;
+ assert composite.getPackageVersionId() == pkgVer2.getId();
+ assert composite.getPackageBitsId() == packageBits2.getId();
+ assert composite.isPackageBitsAvailable();
+ assert composite.isPackageBitsInDatabase();
+
+ // let's make sure the data really is in the DB
+ packageBits2 = em.find(PackageBits.class, packageBits2.getId());
+ assert packageBits2 != null;
+ assert DATA2.equals(new String(packageBits2.getBlob().getBits()));
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw t;
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testPackageBitsBlobStream() throws Throwable {
+ LoadedPackageBitsComposite composite;
+
+ getTransactionManager().begin();
+
+ try {
+ EntityManager em = getEntityManager();
+ Resource resource = SessionTestHelper.createNewResource(em, "testPkgBitsLargeResource");
+ PackageType pkgType = new PackageType("testPkgBitsLargePT", resource.getResourceType());
+ org.rhq.core.domain.content.Package pkg = new Package("testPkgBitsLargeP", pkgType);
+ Architecture arch = new Architecture("testPkgLargeArch");
+ PackageVersion pkgVer = new PackageVersion(pkg, "1", arch);
+
+ em.persist(pkgType);
+ em.persist(pkg);
+ em.persist(arch);
+ em.persist(pkgVer);
+ em.flush();
+
+ // test that no bits are available right now
+ composite = contentUIManager.getLoadedPackageBitsComposite(pkgVer.getId());
+ assert composite != null;
+ assert composite.getPackageVersionId() == pkgVer.getId();
+ assert composite.getPackageBitsId() == null;
+ assert !composite.isPackageBitsAvailable();
+ assert !composite.isPackageBitsInDatabase();
+
+ // pretend we loaded the bits, but we stored them somewhere other then the DB
+ PackageBits packageBits = createPackageBits(em);
+ pkgVer.setPackageBits(packageBits);
+ pkgVer = em.merge(pkgVer);
+ em.flush();
+
+ // test that the bits are available, but are not stored in the DB
+ composite = contentUIManager.getLoadedPackageBitsComposite(pkgVer.getId());
+ assert composite != null;
+ assert composite.getPackageVersionId() == pkgVer.getId();
+ assert composite.getPackageBitsId() == packageBits.getId();
+ assert composite.isPackageBitsAvailable();
+ assert !composite.isPackageBitsInDatabase();
+
+ // let's make sure there really is no data in the DB
+ packageBits = em.find(PackageBits.class, packageBits.getId());
+ assert packageBits != null;
+ assert packageBits.getBlob().getBits() == null;
+
+ // now lets store some bits in the DB using PreparedStatements and BLOB mechanism
+ // to simulate large file transfers where streaming is used instead of reading entire
+ // contents into memory every time.
+
+ //any jar should be fine. Use generated server jar
+ File originalBinary = new File("./src/test/resources/binary-blob-sample.jar");
+ //destination once pulled from db
+ File retrieved = new File("./target/pulled.jar");
+ if (retrieved.exists()) {
+ assertTrue("Unable to delete ./target/pulled.jar for test cleanup.", retrieved.delete());
+ }
+ FileInputStream fos = new FileInputStream(originalBinary);
+
+ contentManager.updateBlobStream(fos, packageBits, null);
+ packageBits = em.find(PackageBits.class, packageBits.getId());
+
+ // test that the bits are available and stored in the DB: Reading the Blob
+ composite = contentUIManager.getLoadedPackageBitsComposite(pkgVer.getId());
+ assert composite != null;
+ assert composite.getPackageVersionId() == pkgVer.getId();
+ assert composite.getPackageBitsId() == packageBits.getId();
+ assert composite.isPackageBitsAvailable();
+ assert composite.isPackageBitsInDatabase();
+
+ FileOutputStream outputStream = new FileOutputStream(retrieved);
+ contentManager.writeBlobOutToStream(outputStream, packageBits, false);
+
+ //Check that db content equal to file system content
+ String originalDigest = new MessageDigestGenerator(MessageDigestGenerator.SHA_256)
+ .calcDigestString(originalBinary);
+ String newDigest = new MessageDigestGenerator(MessageDigestGenerator.SHA_256).calcDigestString(retrieved);
+ assertEquals("Uploaded and retrieved digests differ:", originalDigest, newDigest);
+
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw t;
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ private PackageBits createPackageBits(EntityManager em) {
+ PackageBits bits = null;
+ PackageBitsBlob blob = null;
+
+ // We have to work backwards to avoid constraint violations. PackageBits requires a PackageBitsBlob,
+ // so create and persist that first, getting the ID
+ blob = new PackageBitsBlob();
+ em.persist(blob);
+
+ // Now create the PackageBits entity and assign the Id and blob. Note, do not persist the
+ // entity, the row already exists. Just perform and flush the update.
+ bits = new PackageBits();
+ bits.setId(blob.getId());
+ bits.setBlob(blob);
+ em.flush();
+
+ // return the new PackageBits and associated PackageBitsBlob
+ return bits;
+ }
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java
new file mode 100644
index 0000000..037c071
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java
@@ -0,0 +1,94 @@
+package org.rhq.enterprise.server.content.test;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import javax.transaction.TransactionManager;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.content.Distribution;
+import org.rhq.core.domain.content.DistributionFile;
+import org.rhq.core.domain.content.DistributionType;
+import org.rhq.enterprise.server.content.DistributionManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * @author Pradeep Kilambi
+ */
+public class DistributionManagerBeanTest extends AbstractEJB3Test {
+ private final static boolean ENABLED = true;
+ private DistributionManagerLocal distManager;
+ private DistributionType distType;
+ private Subject overlord;
+
+ @BeforeMethod
+ public void setupBeforeMethod() throws Exception {
+ TransactionManager tx = getTransactionManager();
+ tx.begin();
+
+ distManager = LookupUtil.getDistributionManagerLocal();
+ distType = new DistributionType("kickstart");
+
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+ }
+
+ @AfterMethod
+ public void tearDownAfterMethod() throws Exception {
+ TransactionManager tx = getTransactionManager();
+ if (tx != null) {
+ tx.rollback();
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void createDeleteDistribution() throws Exception {
+
+ String kslabel = "testCreateDeleteRepo";
+ String kspath = "/tmp";
+ int id = distManager.createDistribution(overlord, kslabel, kspath, distType).getId();
+ Distribution distro = distManager.getDistributionByLabel(kslabel);
+
+ assert distro != null;
+
+ assert id == distro.getId();
+
+ distManager.deleteDistributionByDistId(overlord, id);
+ distro = distManager.getDistributionByLabel(kslabel);
+ assert distro == null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testDistributionFiles() throws Exception {
+ String kslabel = "testCreateDeleteRepo";
+ String kspath = "/tmp";
+ // don't get id, if not needed downstream
+ //int id = distManager.createDistribution(overlord, kslabel, kspath, distType).getId();
+ distManager.createDistribution(overlord, kslabel, kspath, distType);
+ Distribution distro = distManager.getDistributionByLabel(kslabel);
+
+ DistributionFile distfile = new DistributionFile(distro, "vmlinux", "d41d8cd98f00b204e9800998ecf8427e");
+ EntityManager em = getEntityManager();
+ em.persist(distfile);
+ Query query = em.createNamedQuery(DistributionFile.SELECT_BY_DIST_ID);
+
+ query.setParameter("distId", distro.getId());
+ List<DistributionFile> results = query.getResultList();
+ assert results.size() != 0;
+ Query querydel = em.createNamedQuery(DistributionFile.DELETE_BY_DIST_ID);
+
+ querydel.setParameter("distId", distro.getId());
+
+ querydel.executeUpdate();
+
+ List<DistributionFile> resultsdel = query.getResultList();
+
+ assert resultsdel.size() == 0;
+
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ProductVersionManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ProductVersionManagerBeanTest.java
new file mode 100644
index 0000000..a583fc7
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/ProductVersionManagerBeanTest.java
@@ -0,0 +1,177 @@
+/*
+ * 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.enterprise.server.content.test;
+
+import java.util.List;
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+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.resource.ProductVersion;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.resource.ProductVersionManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * @author Jason Dobies
+ */
+public class ProductVersionManagerBeanTest extends AbstractEJB3Test {
+ // Attributes --------------------------------------------
+
+ private ResourceType resourceType;
+
+ private ProductVersionManagerLocal productManager;
+
+ // Setup --------------------------------------------
+
+ @BeforeClass
+ public void setupBeforeClass() throws Exception {
+ productManager = LookupUtil.getProductVersionManager();
+ }
+
+ @BeforeMethod
+ public void setupBeforeMethod() throws Exception {
+ setupTestEnvironment();
+ }
+
+ @AfterMethod
+ public void teardownAfterMethod() throws Exception {
+ teardownTestEnvironment();
+ }
+
+ // Test Cases --------------------------------------------
+
+ @Test
+ public void addNewProductVersion() throws Exception {
+ // Test
+ productManager.addProductVersion(resourceType, "1.0.0");
+
+ // Verify
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ try {
+ // Verify
+ resourceType = em.find(ResourceType.class, resourceType.getId());
+
+ Query query = em.createNamedQuery(ProductVersion.QUERY_FIND_BY_RESOURCE_TYPE_AND_VERSION);
+ query.setParameter("resourceType", resourceType);
+ query.setParameter("version", "1.0.0");
+
+ List addedProductVersion = query.getResultList();
+
+ assert addedProductVersion.size() == 1 : "Incorrect number of versions persisted. Expected: 1, Found: "
+ + addedProductVersion.size();
+
+ // Clean up
+ em.remove(addedProductVersion.get(0));
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ getTransactionManager().rollback();
+ }
+ } finally {
+ em.close();
+ }
+ }
+
+ @Test
+ public void addExistingProductVersion() throws Exception {
+ // Setup
+ productManager.addProductVersion(resourceType, "1.0.0");
+ productManager.addProductVersion(resourceType, "1.0.0");
+
+ // Verify
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ try {
+ // Verify
+ resourceType = em.find(ResourceType.class, resourceType.getId());
+
+ Query query = em.createNamedQuery(ProductVersion.QUERY_FIND_BY_RESOURCE_TYPE_AND_VERSION);
+ query.setParameter("resourceType", resourceType);
+ query.setParameter("version", "1.0.0");
+
+ List addedProductVersion = query.getResultList();
+
+ assert addedProductVersion.size() == 1 : "Incorrect number of versions persisted. Expected: 1, Found: "
+ + addedProductVersion.size();
+
+ // Clean up
+ em.remove(addedProductVersion.get(0));
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ getTransactionManager().rollback();
+ }
+ } finally {
+ em.close();
+ }
+ }
+
+ // Private --------------------------------------------
+
+ private void setupTestEnvironment() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ try {
+ resourceType = new ResourceType("testResourceType", "testPlugin", ResourceCategory.PLATFORM, null);
+
+ em.persist(resourceType);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ getTransactionManager().rollback();
+ throw e;
+ }
+ } finally {
+ em.close();
+ }
+ }
+
+ private void teardownTestEnvironment() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ try {
+ resourceType = em.find(ResourceType.class, resourceType.getId());
+ em.remove(resourceType);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ getTransactionManager().rollback();
+ throw e;
+ }
+ } finally {
+ em.close();
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/QuartzScheduleFormatTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/QuartzScheduleFormatTest.java
new file mode 100644
index 0000000..01c1f88
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/QuartzScheduleFormatTest.java
@@ -0,0 +1,55 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.content.test;
+
+import java.text.ParseException;
+
+import junit.framework.TestCase;
+
+import org.quartz.CronExpression;
+
+/**
+ * @author mmccune
+ *
+ */
+public class QuartzScheduleFormatTest extends TestCase {
+
+ public void testValidFormat() {
+ String test = "23asdf";
+ boolean failed = false;
+ try {
+ CronExpression ce = new CronExpression(test);
+ } catch (ParseException e) {
+ failed = true;
+ }
+ assert failed;
+
+ test = "0 0 3 * * ?";
+ failed = false;
+ try {
+ CronExpression ce = new CronExpression(test);
+ } catch (ParseException e) {
+ failed = true;
+ }
+
+ assert !failed;
+
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
new file mode 100644
index 0000000..8fe71cd
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
@@ -0,0 +1,511 @@
+/*
+ * 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.enterprise.server.content.test;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.content.ContentSource;
+import org.rhq.core.domain.content.ContentSourceType;
+import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.content.RepoGroup;
+import org.rhq.core.domain.content.RepoGroupType;
+import org.rhq.core.domain.content.RepoRelationshipType;
+import org.rhq.core.domain.content.RepoRepoRelationship;
+import org.rhq.core.domain.criteria.RepoCriteria;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
+import org.rhq.enterprise.server.content.RepoException;
+import org.rhq.enterprise.server.content.RepoManagerLocal;
+import org.rhq.enterprise.server.content.metadata.ContentSourceMetadataManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+public class RepoManagerBeanTest extends AbstractEJB3Test {
+
+ private final static boolean ENABLED = true;
+
+ //@Inject
+ protected RepoManagerLocal repoManager;
+
+ //@Inject
+ protected ContentSourceManagerLocal contentSourceManager;
+
+ //@Inject
+ protected ContentSourceMetadataManagerLocal contentSourceMetadataManager;
+
+ private Subject overlord;
+
+ //@Inject
+ protected SubjectManagerLocal subjectManager;
+
+ @Override
+ public void beforeMethod() throws Exception {
+ System.out.println("*** 0");
+
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+ System.out.println("*** 1");
+ prepareScheduler();
+ System.out.println("*** 2");
+ repoManager = LookupUtil.getRepoManagerLocal();
+ System.out.println("*** 3");
+ contentSourceManager = LookupUtil.getContentSourceManager();
+ System.out.println("*** 4");
+ contentSourceMetadataManager = LookupUtil.getContentSourceMetadataManager();
+ System.out.println("*** 5");
+ //TestContentServerPluginService pluginService = new TestContentServerPluginService(this);
+ getTransactionManager().begin();
+ System.out.println("*** 6");
+ }
+
+ @Override
+ public void afterMethod() throws Exception {
+ System.out.println("*** 7");
+ unprepareServerPluginService();
+ System.out.println("*** 8");
+ unprepareScheduler();
+ System.out.println("*** 9");
+ getTransactionManager().rollback();
+ System.out.println("*** 10");
+ }
+
+ @Test(enabled = ENABLED)
+ public void createABunchOfRepos() throws Exception {
+ PageList<Repo> repos = repoManager.findRepos(overlord, new PageControl());
+ int origsize = 0;
+ if (repos != null) {
+ origsize = repos.size();
+ }
+ for (int i = 0; i < 10; i++) {
+ Random r = new Random(System.currentTimeMillis());
+ Repo repo = new Repo(r.nextLong() + "");
+ repoManager.createRepo(overlord, repo);
+ }
+ repos = repoManager.findRepos(overlord, new PageControl());
+
+ assert repos.size() == (origsize + 10);
+
+ System.out.println("*** 11");
+ }
+
+ @Test(enabled = ENABLED)
+ public void createDeleteRepo() throws Exception {
+ Repo repo = new Repo("testCreateDeleteRepo");
+ int id = repoManager.createRepo(overlord, repo).getId();
+ Repo lookedUp = repoManager.getRepo(overlord, id);
+ assert lookedUp != null;
+ Repo lookedUp2 = repoManager.getRepoByName(lookedUp.getName()).get(0);
+ assert lookedUp2 != null;
+ assert id == lookedUp.getId();
+ assert id == lookedUp2.getId();
+
+ repoManager.deleteRepo(overlord, id);
+ lookedUp = repoManager.getRepo(overlord, id);
+ assert lookedUp == null;
+ }
+
+ @Test(enabled = ENABLED)
+ public void createDeleteRepoGroup() throws Exception {
+ // Setup
+ EntityManager entityManager = getEntityManager();
+
+ RepoGroupType groupType = new RepoGroupType("testCreateDeleteRepoGroupType");
+ entityManager.persist(groupType);
+ entityManager.flush();
+
+ String groupName = "testCreateDeleteRepoGroup";
+ RepoGroup group = repoManager.getRepoGroupByName(groupName);
+ assert group == null;
+
+ // Test
+ group = new RepoGroup(groupName);
+ group.setRepoGroupType(groupType);
+ group = repoManager.createRepoGroup(overlord, group);
+
+ // Verify
+ int id = group.getId();
+ group = repoManager.getRepoGroup(overlord, id);
+ assert group != null;
+ assert group.getName().equals(groupName);
+
+ // Cleanup
+ repoManager.deleteRepoGroup(overlord, id);
+ group = repoManager.getRepoGroup(overlord, id);
+ assert group == null;
+
+ entityManager.remove(groupType);
+ }
+
+ @Test(enabled = ENABLED)
+ public void createFindDeleteCandidateRepo() throws Exception {
+ // Setup
+ Repo repo = new Repo("test create candidate repo");
+
+ PageList<Repo> importedRepos = repoManager.findRepos(overlord, new PageControl());
+ int origSize = 0;
+ if (importedRepos != null) {
+ origSize = importedRepos.size();
+ }
+
+ // Test
+ repo.setCandidate(true);
+ repo = repoManager.createRepo(overlord, repo);
+
+ // Verify
+ try {
+ assert repo.isCandidate();
+
+ // Should not be returned from this call since it's a candidate repo
+ importedRepos = repoManager.findRepos(overlord, new PageControl());
+ assert importedRepos.size() == origSize;
+ assert repoManager.getRepo(overlord, repo.getId()) != null;
+ } finally {
+ repoManager.deleteRepo(overlord, repo.getId());
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void createDuplicateRepoGroup() throws Exception {
+ // Setup
+ EntityManager entityManager = getEntityManager();
+
+ RepoGroupType groupType = new RepoGroupType("testCreateDuplicateRepoGroup");
+ entityManager.persist(groupType);
+ entityManager.flush();
+
+ String groupName = "testCreateDuplicateRepoGroup";
+
+ RepoGroup existing = new RepoGroup(groupName);
+ existing.setRepoGroupType(groupType);
+ repoManager.createRepoGroup(overlord, existing);
+
+ existing = repoManager.getRepoGroupByName(groupName);
+ assert existing != null;
+
+ // Test
+ RepoGroup duplicate = new RepoGroup(groupName);
+ duplicate.setRepoGroupType(groupType);
+
+ try {
+ repoManager.createRepoGroup(overlord, existing);
+ assert false;
+ } catch (RepoException e) {
+ // Expected
+ }
+
+ // Cleanup
+ repoManager.deleteRepoGroup(overlord, existing.getId());
+ existing = repoManager.getRepoGroup(overlord, existing.getId());
+ assert existing == null;
+
+ entityManager.remove(groupType);
+ }
+
+ @Test(enabled = ENABLED)
+ public void getRepoGroupByNameNoGroup() throws Exception {
+ // Test
+ RepoGroup group = repoManager.getRepoGroupByName("foo");
+
+ assert group == null;
+ }
+
+ @Test(enabled = ENABLED)
+ public void getRepoGroupTypeByName() throws Exception {
+ // Setup
+ EntityManager entityManager = getEntityManager();
+ String name = "test-repo-type";
+
+ RepoGroupType groupType = new RepoGroupType(name);
+ entityManager.persist(groupType);
+ entityManager.flush();
+
+ // Test
+ RepoGroupType type = repoManager.getRepoGroupTypeByName(overlord, name);
+ assert type != null;
+ assert type.getName().equals(name);
+
+ // Cleanup
+ type = entityManager.find(RepoGroupType.class, type.getId());
+ entityManager.remove(type);
+ entityManager.flush();
+ }
+
+ @Test(enabled = ENABLED)
+ public void addRepoRelationship() throws Exception {
+ // Setup
+ EntityManager entityManager = getEntityManager();
+
+ Repo repo = new Repo("repo1");
+ Repo relatedRepo = new Repo("repo2");
+
+ repo = repoManager.createRepo(overlord, repo);
+ relatedRepo = repoManager.createRepo(overlord, relatedRepo);
+
+ String relationshipTypeName = "testRelationshipType";
+ RepoRelationshipType relationshipType = new RepoRelationshipType(relationshipTypeName);
+ entityManager.persist(relationshipType);
+ entityManager.flush();
+
+ // Test
+ repoManager.addRepoRelationship(overlord, repo.getId(), relatedRepo.getId(), relationshipTypeName);
+
+ // Verify
+ RepoCriteria repoCriteria = new RepoCriteria();
+ repoCriteria.fetchRepoRepoGroups(true);
+ repoCriteria.addFilterId(repo.getId());
+
+ PageList<Repo> repoPageList = repoManager.findReposByCriteria(overlord, repoCriteria);
+ assert repoPageList.size() == 1;
+
+ Repo persistedRepo = repoPageList.get(0);
+ Set<RepoRepoRelationship> relationships = persistedRepo.getRepoRepoRelationships();
+ assert relationships.size() == 1;
+
+ RepoRepoRelationship relationship = relationships.iterator().next();
+ assert relationship.getRepoRepoRelationshipPK().getRepo().getName().equals("repo1");
+ assert relationship.getRepoRepoRelationshipPK().getRepoRelationship().getRelatedRepo().getName()
+ .equals("repo2");
+ assert relationship.getRepoRepoRelationshipPK().getRepoRelationship().getRepoRelationshipType().getName()
+ .equals(relationshipTypeName);
+
+ // Cleanup handled by rollback in tear down method
+ }
+
+ @Test(enabled = ENABLED)
+ public void findCandidatesByContentProvider() throws Exception {
+ // Setup
+ String candidateRepoName = "candidate with source";
+
+ // Create a content source type and a content source
+ ContentSourceType type = new ContentSourceType("testGetSyncResultsListCST");
+ Set<ContentSourceType> types = new HashSet<ContentSourceType>();
+ types.add(type);
+ contentSourceMetadataManager.registerTypes(types); // this blows away any previous existing types
+ ContentSource contentSource = new ContentSource("testGetSyncResultsListCS", type);
+ contentSource = contentSourceManager.simpleCreateContentSource(overlord, contentSource);
+
+ // Create an imported (non-candidate) repo associated with the source
+ Repo importedRepo = new Repo("imported repo");
+ importedRepo.addContentSource(contentSource);
+ importedRepo = repoManager.createRepo(overlord, importedRepo);
+
+ // Create a candidate repo associated with that source
+ Repo candidateRepo = new Repo(candidateRepoName);
+ candidateRepo.setCandidate(true);
+ candidateRepo.addContentSource(contentSource);
+ candidateRepo = repoManager.createRepo(overlord, candidateRepo);
+
+ // Test
+ RepoCriteria criteria = new RepoCriteria();
+ criteria.addFilterCandidate(true);
+ criteria.addFilterContentSourceIds(contentSource.getId());
+ criteria.fetchRepoContentSources(true);
+
+ PageList<Repo> foundRepos = repoManager.findReposByCriteria(overlord, criteria);
+
+ // Verify
+
+ // Make sure only one of the two repos from above came back
+ assert foundRepos.size() == 1;
+
+ Repo foundRepo = foundRepos.get(0);
+ assert foundRepo.getName().equals(candidateRepoName);
+ assert foundRepo.isCandidate();
+
+ // Cleanup handled by rollback in tear down method
+ }
+
+ @Test(enabled = ENABLED)
+ public void importCandidateRepo() throws Exception {
+ // Setup
+ Repo candidate = new Repo("create me");
+ candidate.setCandidate(true);
+ Repo created = repoManager.createRepo(overlord, candidate);
+
+ // Test
+ List<Integer> repoIds = new ArrayList<Integer>(1);
+ repoIds.add(created.getId());
+ repoManager.importCandidateRepo(overlord, repoIds);
+
+ // Verify
+ RepoCriteria repoCriteria = new RepoCriteria();
+ repoCriteria.addFilterId(created.getId());
+
+ PageList<Repo> repoList = repoManager.findReposByCriteria(overlord, repoCriteria);
+ assert repoList.size() == 1;
+
+ Repo verify = repoList.get(0);
+ assert verify != null;
+ assert !verify.isCandidate();
+ }
+
+ @Test(enabled = ENABLED)
+ public void importCandidateRepoBadId() throws Exception {
+ // Test
+ try {
+ List<Integer> repoIds = new ArrayList<Integer>(1);
+ repoIds.add(12345);
+ repoManager.importCandidateRepo(overlord, repoIds);
+ assert false;
+ } catch (RepoException e) {
+ // Expected
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void importNonCandidateRepo() throws Exception {
+ // Setup
+ Repo nonCandidate = new Repo("create me");
+ Repo created = repoManager.createRepo(overlord, nonCandidate);
+
+ // Test
+ try {
+ List<Integer> repoIds = new ArrayList<Integer>(1);
+ repoIds.add(created.getId());
+ repoManager.importCandidateRepo(overlord, repoIds);
+ assert false;
+ } catch (RepoException e) {
+ // Expected
+ }
+
+ }
+
+ @Test(enabled = ENABLED)
+ public void deleteCandidatesForContentSource() throws Exception {
+ // Setup
+ ContentSourceType contentSourceType = new ContentSourceType("testSourceType");
+ Set<ContentSourceType> types = new HashSet<ContentSourceType>(1);
+ types.add(contentSourceType);
+ contentSourceMetadataManager.registerTypes(types);
+
+ ContentSource source1 = new ContentSource("testSource1", contentSourceType);
+ source1 = contentSourceManager.simpleCreateContentSource(overlord, source1);
+
+ ContentSource source2 = new ContentSource("testSource2", contentSourceType);
+ source2 = contentSourceManager.simpleCreateContentSource(overlord, source2);
+
+ // -> Only has source to delete, should be deleted
+ Repo repo1 = new Repo("repo1");
+ repo1.setCandidate(true);
+ repo1.addContentSource(source1);
+
+ // -> Has different source, should not be deleted
+ Repo repo2 = new Repo("repo2");
+ repo2.setCandidate(true);
+ repo2.addContentSource(source2);
+
+ // -> Has source to delete and another source, should not be deleted
+ Repo repo3 = new Repo("repo3");
+ repo3.setCandidate(true);
+ repo3.addContentSource(source1);
+ repo3.addContentSource(source2);
+
+ // -> No sources, should not be deleted
+ Repo repo4 = new Repo("repo4");
+ repo4.setCandidate(true);
+
+ repo1 = repoManager.createRepo(overlord, repo1);
+ repo2 = repoManager.createRepo(overlord, repo2);
+ repo3 = repoManager.createRepo(overlord, repo3);
+ repo4 = repoManager.createRepo(overlord, repo4);
+
+ // Test
+ repoManager.deleteCandidatesWithOnlyContentSource(overlord, source1.getId());
+
+ // Verify
+ assert repoManager.getRepo(overlord, repo1.getId()) == null;
+ assert repoManager.getRepo(overlord, repo2.getId()) != null;
+ assert repoManager.getRepo(overlord, repo3.getId()) != null;
+ assert repoManager.getRepo(overlord, repo4.getId()) != null;
+ }
+
+ @Test(enabled = ENABLED)
+ public void updateRepoWithProvider() throws Exception {
+ // See BZ 537216 for more details
+
+ // Setup
+ String newName = "newRepo-" + RandomStringUtils.randomAlphanumeric(6);
+ String oldName = "testRepo-" + RandomStringUtils.randomAlphanumeric(6);
+
+ ContentSourceType contentSourceType = new ContentSourceType("testSourceType");
+
+ Set<ContentSourceType> types = new HashSet<ContentSourceType>(1);
+ types.add(contentSourceType);
+ contentSourceMetadataManager.registerTypes(types);
+
+ ContentSource source = new ContentSource("testSource1", contentSourceType);
+ source = contentSourceManager.simpleCreateContentSource(overlord, source);
+
+ Repo repo = new Repo(oldName);
+ repo = repoManager.createRepo(overlord, repo);
+
+ repoManager.simpleAddContentSourcesToRepo(overlord, repo.getId(), new int[] { source.getId() });
+
+ // Test
+ repo.setName(newName);
+ repoManager.updateRepo(overlord, repo);
+
+ // Verify
+ RepoCriteria byName = new RepoCriteria();
+ byName.addFilterName(newName);
+ PageList<Repo> reposWithNewName = repoManager.findReposByCriteria(overlord, byName);
+
+ assert reposWithNewName.size() == 1;
+
+ byName = new RepoCriteria();
+ byName.addFilterName(oldName);
+ PageList<Repo> reposWithOldName = repoManager.findReposByCriteria(overlord, byName);
+
+ assert reposWithOldName.size() == 0;
+ }
+
+ @Test(enabled = ENABLED)
+ public void updateSyncSchedule() {
+ Repo repo = new Repo("updateSyncSchedule");
+ repo.setSyncSchedule("NOT A VALID CRON");
+ boolean failed = false;
+ try {
+ repo = repoManager.createRepo(overlord, repo);
+ } catch (RepoException e) {
+ failed = true;
+ }
+ assert failed;
+
+ failed = false;
+ repo.setSyncSchedule("0 0 3 * * ?");
+ try {
+ repo = repoManager.createRepo(overlord, repo);
+ } catch (RepoException e) {
+ failed = true;
+ }
+ assert !failed;
+ }
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/RepoSyncingTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/RepoSyncingTest.java
new file mode 100644
index 0000000..cf4006f
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/content/test/RepoSyncingTest.java
@@ -0,0 +1,271 @@
+package org.rhq.enterprise.server.content.test;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import javax.transaction.TransactionManager;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.content.ContentSource;
+import org.rhq.core.domain.content.ContentSourceType;
+import org.rhq.core.domain.content.ContentSyncStatus;
+import org.rhq.core.domain.content.Distribution;
+import org.rhq.core.domain.content.DistributionFile;
+import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.content.RepoDistribution;
+import org.rhq.core.domain.content.RepoSyncResults;
+import org.rhq.enterprise.server.content.ContentManagerHelper;
+import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.content.TestContentProvider;
+import org.rhq.enterprise.server.plugin.pc.content.TestContentServerPluginService;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+public class RepoSyncingTest extends AbstractEJB3Test {
+ private static final boolean ENABLED = false;
+
+ private EntityManager em;
+ private Repo repo;
+ private ContentSource contentSource;
+ private TestContentServerPluginService pluginService;
+ TestContentProvider p1;
+
+ @BeforeMethod
+ public void setupBeforeMethod() throws Exception {
+ TransactionManager tx = getTransactionManager();
+ tx.begin();
+ em = getEntityManager();
+ pluginService = new TestContentServerPluginService(this);
+
+ ContentSourceType type = new ContentSourceType("testGetSyncResultsListCST");
+ em.persist(type);
+ em.flush();
+ contentSource = new ContentSource("testGetSyncResultsListCS", type);
+ em.persist(contentSource);
+ em.flush();
+
+ repo = new Repo(TestContentProvider.EXISTING_IMPORTED_REPO_NAME);
+ p1 = new TestContentProvider();
+ pluginService.associateContentProvider(contentSource, p1);
+ repo.addContentSource(contentSource);
+ em.persist(repo);
+ em.flush();
+ }
+
+ @Test(enabled = ENABLED)
+ public void testSyncResults() throws Exception {
+ // We have to commit because bean has new transaction inside it
+ getTransactionManager().commit();
+
+ boolean synced = pluginService.getContentProviderManager().synchronizeRepo(repo.getId());
+ RepoSyncResults results = getSyncResults(repo.getId());
+ System.out.println("results : " + results.getResults());
+ // Testing that we merged all the results into the RepoSyncReport
+ assert (results.getResults().indexOf("MERGE COMPLETE.") > 0);
+ assert (results.getPercentComplete().equals(new Long(100)));
+ }
+
+ @Test(enabled = ENABLED)
+ public void testMultipleSyncResults() throws Exception {
+ getTransactionManager().commit();
+ // Sync 2x so we get multiple results
+ pluginService.getContentProviderManager().synchronizeRepo(repo.getId());
+ pluginService.getContentProviderManager().synchronizeRepo(repo.getId());
+
+ em.refresh(repo);
+
+ Query q = em.createNamedQuery(RepoSyncResults.QUERY_GET_ALL_BY_REPO_ID);
+ q.setParameter("repoId", repo.getId());
+ List<RepoSyncResults> rlist = q.getResultList(); // will be ordered by start time descending
+ RepoSyncResults r1 = rlist.get(0);
+ RepoSyncResults r2 = rlist.get(1);
+ assert (r1.getId() > r2.getId());
+
+ rlist = repo.getSyncResults();
+ r1 = rlist.get(0);
+ r2 = rlist.get(1);
+ assert (r1.getId() > r2.getId());
+ }
+
+ @Test(enabled = ENABLED)
+ public void testSyncRepos() throws Exception {
+ p1.setLongRunningSynchSleep(5000);
+
+ assert repo.getContentSources().size() == 1;
+ // We have to commit because bean has new transaction inside it
+ getTransactionManager().commit();
+
+ RepoSyncResults results = getSyncResults(repo.getId());
+ assert results == null;
+
+ System.out.println("Starting sync: " + repo.getId());
+ //
+
+ SyncerThread st = new SyncerThread();
+ st.start();
+
+ boolean gotPackageBits = false;
+ boolean gotResults = false;
+ // Run 30 times or until it is synced.
+ for (int i = 0; ((i < 300) && !st.isSynced() && !st.isErrored()); i++) {
+ results = getSyncResults(repo.getId());
+ if (results != null) {
+ if (results.getStatus() == ContentSyncStatus.PACKAGEMETADATA) {
+ gotPackageBits = true;
+ }
+ if (results.getResults() != null) {
+ gotResults = true;
+ }
+ }
+ Thread.sleep(1000);
+ }
+ System.out.println("Finished sync");
+ assert gotPackageBits;
+ assert gotResults;
+
+ assert st.isSynced();
+ results = getSyncResults(repo.getId());
+ assert results != null;
+
+ assert (results.getStatus() == ContentSyncStatus.SUCCESS);
+ assert (results.getResults() != null);
+
+ // Testing that we merged all the results into the RepoSyncReport
+ assert (results.getResults().indexOf("MERGE COMPLETE.") > 0);
+
+ results = LookupUtil.getRepoManagerLocal().getMostRecentSyncResults(
+ LookupUtil.getSubjectManager().getOverlord(), repo.getId());
+ assert results != null;
+
+ }
+
+ @Test(enabled = ENABLED)
+ public void testSyncCount() throws Exception {
+
+ int[] ids = { repo.getId() };
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ getTransactionManager().commit();
+ int syncCount = LookupUtil.getRepoManagerLocal().synchronizeRepos(overlord, ids);
+
+ assert syncCount == 1;
+
+ }
+
+ @Test(enabled = ENABLED)
+ public void testCancelSync() throws Exception {
+ getTransactionManager().commit();
+ p1 = new TestContentProvider();
+ p1.setLongRunningSynchSleep(10000);
+ pluginService.associateContentProvider(contentSource, p1);
+
+ prepareScheduler();
+ ContentServerPluginContainer pc = ContentManagerHelper.getPluginContainer();
+ pc.syncRepoNow(repo);
+
+ for (int i = 0; i < 10; i++) {
+ RepoSyncResults res = getSyncResults(repo.getId());
+ if (res != null) {
+ System.out.println("status: [" + res.getStatus() + "] CTRL+C to exit");
+ if (res.getStatus() == ContentSyncStatus.CANCELLED) {
+ break;
+ }
+ } else {
+ System.out.println("CTRL+C to exit");
+ }
+ Thread.sleep(1000);
+ if (i == 5) {
+ pc.cancelRepoSync(LookupUtil.getSubjectManager().getOverlord(), repo);
+ }
+
+ }
+ RepoSyncResults res = getSyncResults(repo.getId());
+ assert res != null;
+ assert res.getStatus() == ContentSyncStatus.CANCELLED;
+ unprepareScheduler();
+ }
+
+ private RepoSyncResults getSyncResults(int repoId) {
+ Query q = em.createNamedQuery(RepoSyncResults.QUERY_GET_ALL_BY_REPO_ID);
+ q.setParameter("repoId", repoId);
+ List<RepoSyncResults> rlist = q.getResultList(); // will be ordered by start time descending
+ if (rlist != null && rlist.size() > 0) {
+ assert rlist.size() == 1;
+ RepoSyncResults retval = rlist.get(0);
+ em.refresh(retval);
+ return rlist.get(0);
+ } else {
+ return null;
+ }
+ }
+
+ @AfterMethod
+ public void tearDownAfterMethod() throws Exception {
+ unprepareServerPluginService();
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ ContentSource deleteSrc = em.find(ContentSource.class, contentSource.getId());
+ // em.remove(deleteSrc.getContentSourceType());
+ em.remove(deleteSrc);
+
+ Query q = em.createNamedQuery(RepoDistribution.QUERY_FIND_BY_REPO_ID);
+ q.setParameter("repoId", repo.getId());
+ List<RepoDistribution> rds = q.getResultList();
+ for (RepoDistribution rd : rds) {
+ Distribution d = rd.getRepoDistributionPK().getDistribution();
+ List<DistributionFile> dfiles = LookupUtil.getDistributionManagerLocal().getDistributionFilesByDistId(
+ d.getId());
+ for (DistributionFile df : dfiles) {
+ DistributionFile dfl = em.find(DistributionFile.class, df.getId());
+ em.remove(dfl);
+ }
+ em.remove(rd);
+ em.remove(d);
+ }
+
+ Repo delRepo = em.find(Repo.class, repo.getId());
+ em.remove(delRepo);
+
+ TransactionManager tx = getTransactionManager();
+ if (tx != null) {
+ tx.commit();
+ }
+
+ }
+
+ class SyncerThread extends Thread {
+
+ boolean synced = false;
+ boolean errored = false;
+
+ public boolean isErrored() {
+ return errored;
+ }
+
+ @Override
+ public void run() {
+ try {
+ TransactionManager tx = getTransactionManager();
+ tx.begin();
+ System.out.println("SyncerThread :: Starting sync");
+ synced = pluginService.getContentProviderManager().synchronizeRepo(repo.getId());
+ System.out.println("SyncerThread :: Finished sync : " + synced);
+ tx.commit();
+ } catch (Exception e) {
+ errored = true;
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public boolean isSynced() {
+ return synced;
+ }
+
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/core/CoreServerServiceImplTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/core/CoreServerServiceImplTest.java
new file mode 100644
index 0000000..04a68c5
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/core/CoreServerServiceImplTest.java
@@ -0,0 +1,503 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2011, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.core;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.persistence.Query;
+
+import org.testng.annotations.AfterGroups;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.server.core.AgentRegistrationException;
+import org.rhq.core.clientapi.server.core.AgentRegistrationRequest;
+import org.rhq.core.clientapi.server.core.AgentRegistrationResults;
+import org.rhq.core.clientapi.server.core.AgentVersion;
+import org.rhq.core.domain.cloud.Server;
+import org.rhq.core.domain.cloud.Server.OperationMode;
+import org.rhq.core.domain.common.ProductInfo;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.util.exception.ThrowableUtil;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * This tests the core server service. This includes agent registration.
+ *
+ * @author John Mazzitelli
+ */
+
+// These are the agent registration unit test cases.
+// (allowed) means the registration should succeed.
+// (REJECT) means the server should reject that agent registration request.
+// ---
+// A. testNewAgentRegistrationWithOldToken
+// 1) register a new agent with a non-null, unknown security token (allowed)
+// B. testChangeAddressPort
+// 1) register a new agent Z with null security token (allowed)
+// 2) re-register agent Z with its token but change its host (allowed)
+// 3) re-register agent Z with its token but change its port (allowed)
+// 4) re-register agent Z with its token but change its host and port (allowed)
+// 5) re-register agent Z with its token but change nothing (allowed)
+// 6) re-register agent Z with NO token but change its host (REJECT)
+// 7) re-register agent Z with NO token but change its port (REJECT)
+// 8) re-register agent Z with NO token but change its host and port (REJECT)
+// 9) re-register agent Z with NO token but change nothing (REJECT)
+// C. testNormalAgentRegistration
+// 1) register a new agent A with a null security token (allowed, same as B.1)
+// D. testHijackExistingAgentAddressPort
+// 1) register a new agent B with null security token but using A's host/port (REJECT)
+// E. testHijackExistingAgentName
+// 1) register an agent using an already-existing agent name A, and using A's host but a different port with a null token (REJECT - missing the token)
+// 2) register an agent using an already-existing agent name A, and using A's port but a different host with a null token (REJECT - missing the token)
+// 3) register an agent using an already-existing agent name A, and using a different port and host with a null token (REJECT - missing the token)
+// F. testHijackExistingAgentAddressPortWithBogusToken
+// 1) register a new agent B with A's host and port but with a bogus token (REJECT)
+// G. testHijackExistingAgentNameWithBogusToken
+// 1) re-register agent A with its original host and port but with a bogus token (REJECT)
+// 2) re-register agent A with its original host, different port but with bogus token (REJECT)
+// 3) re-register agent A with different host, original port but with bogus token (REJECT)
+// 4) re-register agent A with different host and port but with bogus token (REJECT)
+// H. testHijackExistingAgentNameWithAnotherAgentToken
+// 1) re-register agent A with its original host and port but with Z's security token (REJECT - you cannot authenticate using another agent's token)
+// 2) re-register agent A with different host and original port but with Z's security token (REJECT - you cannot authenticate using another agent's token)
+// 3) re-register agent A with original host and different port but with Z's security token (REJECT - you cannot authenticate using another agent's token)
+// 4) re-register agent A with different host and port but with Z's security token (REJECT - you cannot authenticate using another agent's token)
+// I. testAgentHijackingAnotherAgentAddressPort
+// 1) re-register agent A using A's correct security token but with Z's host and Z's port (REJECT - one agent cannot steal another agent's host/port endpoint) NOTE: this is not D.1 because in D.1, the request doesn't have a token. This I.1 test has a token and it really authenticates the agent A making the request. This also isn't F.1 because F.1, while it has a token, it is not a valid token, thus its agent is not authentic.
+// J. testAttemptToChangeAgentName
+// 1) register agent "newName" but with Z's host/port/token. In effect, this is trying to change the agent's name. (REJECT - you are not allowed to rename agents)
+
+@Test(groups = { "core.agent.registration" })
+public class CoreServerServiceImplTest extends AbstractEJB3Test {
+ private static final String TEST_AGENT_NAME_PREFIX = "CoreServerServiceImplTest.Agent";
+ private static final String RHQ_SERVER_NAME_PROPERTY = "rhq.server.high-availability.name";
+ private AgentVersion agentVersion;
+ private Server server;
+ private String oldServerNamePropertyValue = null;
+ private AgentRegistrationRequest aReq = null;
+ private AgentRegistrationResults aResults = null;
+ private AgentRegistrationRequest zReq = null;
+ private AgentRegistrationResults zResults = null;
+
+ private static final int A_PORT = 11111;
+ private static final String A_HOST = "hostA";
+ private static final int B_PORT = 22222;
+ private static final String B_HOST = "hostB";
+
+ @AfterGroups(groups = { "core.agent.registration" })
+ public void afterGroup() throws Exception {
+ // clean up any agents we might have created
+ Query q = getEntityManager().createQuery(
+ "select a from Agent a where name like '" + TEST_AGENT_NAME_PREFIX + "%'");
+ List<Agent> doomed = (List<Agent>) q.getResultList();
+ for (Agent deleteMe : doomed) {
+ LookupUtil.getAgentManager().deleteAgent(deleteMe);
+ }
+ }
+
+ @BeforeMethod
+ public void prepare() throws Exception {
+ // mock the name of our server via the sysprop (in production, this is normally set in rhq-server.properties)
+ oldServerNamePropertyValue = System.getProperty(RHQ_SERVER_NAME_PROPERTY);
+ String newServerNamePropertyValue = "CoreServerServiceImplTest.Server";
+ System.setProperty(RHQ_SERVER_NAME_PROPERTY, newServerNamePropertyValue);
+
+ // mock up our core server MBean that provides information about where the jboss home dir is
+ MBeanServer mbs = getPlatformMBeanServer();
+ DummyCoreServer mbean = new DummyCoreServer();
+ mbs.registerMBean(mbean, new ObjectName(CoreServerMBean.OBJECT_NAME));
+
+ // in order to register, we need to mock out the agent version file used by the server
+ // to determine the agent version it supports.
+ agentVersion = new AgentVersion("1.2.3", "12345");
+ File agentVersionFile = new File(mbean.getJBossServerHomeDir(),
+ "deploy/rhq.ear/rhq-downloads/rhq-agent/rhq-server-agent-versions.properties");
+ agentVersionFile.getParentFile().mkdirs();
+ agentVersionFile.delete();
+ Properties agentVersionProps = new Properties();
+ agentVersionProps.put("rhq-agent.latest.version", agentVersion.getVersion());
+ agentVersionProps.put("rhq-agent.latest.build-number", agentVersion.getBuild());
+ FileOutputStream fos = new FileOutputStream(agentVersionFile);
+ try {
+ agentVersionProps.store(fos, "This file was created by " + CoreServerServiceImplTest.class.getName());
+ } finally {
+ fos.close();
+ }
+
+ // this mocks out the endpoint ping - the server will think the agent that is registering is up and pingable
+ prepareForTestAgents();
+
+ // mock our server
+ server = new Server();
+ server.setName(newServerNamePropertyValue);
+ server.setAddress("CoreServerServiceImplTest.localhost");
+ server.setPort(12345);
+ server.setSecurePort(12346);
+ server.setOperationMode(OperationMode.NORMAL);
+ int serverId = LookupUtil.getServerManager().create(server);
+ server.setId(serverId);
+ }
+
+ @Override
+ public void afterMethod() throws Exception {
+
+ // cleanup our test server
+ LookupUtil.getCloudManager().updateServerMode(new Integer[] { server.getId() }, OperationMode.DOWN);
+ LookupUtil.getCloudManager().deleteServer(server.getId());
+
+ // shutdown our mock mbean server
+ MBeanServer mbs = getPlatformMBeanServer();
+ mbs.unregisterMBean(new ObjectName(CoreServerMBean.OBJECT_NAME));
+
+ unprepareForTestAgents();
+
+ // in case this was set before our tests, put it back the way it was
+ if (oldServerNamePropertyValue != null) {
+ System.setProperty(RHQ_SERVER_NAME_PROPERTY, oldServerNamePropertyValue);
+ }
+ }
+
+ @Test
+ public void testNewAgentRegistrationWithOldToken() throws Exception {
+ // this tests the case where someone purged an agent from the DB, but then
+ // changed their mind and want to re-run that agent and re-register it again.
+ // In this case, the agent (if not using --cleanallconfig) would still have the old token.
+ // The agent should still be allowed to register again.
+ CoreServerServiceImpl service = new CoreServerServiceImpl();
+ AgentRegistrationRequest request = createRequest(prefixName("old"), "hostOld", 12345, "oldtoken");
+ AgentRegistrationResults results = service.registerAgent(request);
+ assert results != null : "cannot re-register an old agent";
+ Agent agent = LookupUtil.getAgentManager().getAgentByAgentToken(results.getAgentToken());
+ assert agent.getName().equals(request.getName());
+ assert agent.getAddress().equals(request.getAddress());
+ assert agent.getPort() == request.getPort();
+ LookupUtil.getAgentManager().deleteAgent(agent);
+ }
+
+ @Test
+ public void testChangeAddressPort() throws Exception {
+ CoreServerServiceImpl service = new CoreServerServiceImpl();
+ AgentRegistrationRequest request;
+ AgentRegistrationResults results;
+
+ String zName = prefixName("Z");
+
+ // create a new agent Z with host/port of hostZ/55550
+ request = createRequest(zName, "hostZ", 55550, null);
+ results = service.registerAgent(request);
+ assert results != null : "got null results";
+
+ // now change Z's host to hostZprime
+ request = createRequest(zName, "hostZprime", 55550, results.getAgentToken());
+ results = service.registerAgent(request);
+ assert results != null;
+ Agent agent = LookupUtil.getAgentManager().getAgentByAgentToken(results.getAgentToken());
+ assert agent.getName().equals(zName);
+ assert agent.getAddress().equals("hostZprime");
+ assert agent.getPort() == 55550;
+
+ // now change Z's port to 55551
+ request = createRequest(zName, "hostZprime", 55551, results.getAgentToken());
+ results = service.registerAgent(request);
+ assert results != null;
+ agent = LookupUtil.getAgentManager().getAgentByAgentToken(results.getAgentToken());
+ assert agent.getName().equals(zName);
+ assert agent.getAddress().equals("hostZprime");
+ assert agent.getPort() == 55551;
+
+ // now change Z's host/port to hostZdoubleprime/55552
+ request = createRequest(zName, "hostZdoubleprime", 55552, results.getAgentToken());
+ results = service.registerAgent(request);
+ assert results != null;
+ agent = LookupUtil.getAgentManager().getAgentByAgentToken(results.getAgentToken());
+ assert agent.getName().equals(zName);
+ assert agent.getAddress().equals("hostZdoubleprime");
+ assert agent.getPort() == 55552;
+
+ // now don't change Z's host/port but re-register everything the same with its token
+ request = createRequest(zName, "hostZdoubleprime", 55552, results.getAgentToken());
+ results = service.registerAgent(request);
+ assert results != null;
+ agent = LookupUtil.getAgentManager().getAgentByAgentToken(results.getAgentToken());
+ assert agent.getName().equals(zName);
+ assert agent.getAddress().equals("hostZdoubleprime");
+ assert agent.getPort() == 55552;
+
+ // remember this agent so our later tests can use it
+ zReq = request;
+ zResults = results;
+
+ // Try to re-register changes to host and/or port but do not send any token.
+ // Because there is no token, these should fail.
+ request = createRequest(zName, B_HOST, zReq.getPort(), null);
+ try {
+ service.registerAgent(request);
+ assert false : "(1) Should not have been able to register without a token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ request = createRequest(zName, zReq.getAddress(), B_PORT, null);
+ try {
+ service.registerAgent(request);
+ assert false : "(2) Should not have been able to register without a token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ request = createRequest(zName, B_HOST, B_PORT, null);
+ try {
+ service.registerAgent(request);
+ assert false : "(3) Should not have been able to register without a token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ request = createRequest(zName, zReq.getAddress(), zReq.getPort(), null);
+ try {
+ service.registerAgent(request);
+ assert false : "(4) Should not have been able to register without a token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ }
+
+ @Test(dependsOnMethods = "testChangeAddressPort")
+ public void testNormalAgentRegistration() throws Exception {
+ CoreServerServiceImpl service = new CoreServerServiceImpl();
+ aReq = createRequest(prefixName("A"), A_HOST, A_PORT, null);
+ aResults = service.registerAgent(aReq);
+ assert aResults != null : "got null results";
+ }
+
+ @Test(dependsOnMethods = "testNormalAgentRegistration")
+ public void testHijackExistingAgentAddressPort() throws Exception {
+ CoreServerServiceImpl service = new CoreServerServiceImpl();
+ AgentRegistrationRequest request;
+ request = createRequest(prefixName("B"), aReq.getAddress(), aReq.getPort(), null);
+ try {
+ service.registerAgent(request);
+ assert false : "Should not have been able to hijack a used host/port with new agent name";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ }
+
+ @Test(dependsOnMethods = "testNormalAgentRegistration")
+ public void testHijackExistingAgentName() throws Exception {
+ CoreServerServiceImpl service = new CoreServerServiceImpl();
+ AgentRegistrationRequest request;
+ request = createRequest(aReq.getName(), aReq.getAddress(), B_PORT, null);
+ try {
+ service.registerAgent(request);
+ assert false : "Should not have been able to hijack a used agent name without a token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ request = createRequest(aReq.getName(), B_HOST, aReq.getPort(), null);
+ try {
+ service.registerAgent(request);
+ assert false : "Should not have been able to hijack a used agent name without a token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ request = createRequest(aReq.getName(), B_HOST, B_PORT, null);
+ try {
+ service.registerAgent(request);
+ assert false : "Should not have been able to hijack a used agent name without a token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ }
+
+ @Test(dependsOnMethods = "testNormalAgentRegistration")
+ public void testHijackExistingAgentAddressPortWithBogusToken() throws Exception {
+ CoreServerServiceImpl service = new CoreServerServiceImpl();
+ AgentRegistrationRequest request;
+ request = createRequest(prefixName("B"), aReq.getAddress(), aReq.getPort(), "badtoken");
+ try {
+ service.registerAgent(request);
+ assert false : "Should not have been able to hijack a used host/port with new agent name and invalid token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ }
+
+ @Test(dependsOnMethods = "testNormalAgentRegistration")
+ public void testHijackExistingAgentNameWithBogusToken() throws Exception {
+ CoreServerServiceImpl service = new CoreServerServiceImpl();
+ AgentRegistrationRequest request;
+ request = createRequest(aReq.getName(), aReq.getAddress(), aReq.getPort(), "badtoken");
+ try {
+ service.registerAgent(request);
+ assert false : "Should not have been able to hijack a used agent name with an invalid token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ request = createRequest(aReq.getName(), aReq.getAddress(), B_PORT, "badtoken");
+ try {
+ service.registerAgent(request);
+ assert false : "Should not have been able to hijack a used agent name with an invalid token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ request = createRequest(aReq.getName(), B_HOST, aReq.getPort(), "badtoken");
+ try {
+ service.registerAgent(request);
+ assert false : "Should not have been able to hijack a used agent name with an invalid token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ request = createRequest(aReq.getName(), B_HOST, B_PORT, "badtoken");
+ try {
+ service.registerAgent(request);
+ assert false : "Should not have been able to hijack a used agent name with an invalid token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ }
+
+ @Test(dependsOnMethods = "testNormalAgentRegistration")
+ public void testHijackExistingAgentNameWithAnotherAgentToken() throws Exception {
+ CoreServerServiceImpl service = new CoreServerServiceImpl();
+ AgentRegistrationRequest request;
+ request = createRequest(aReq.getName(), aReq.getAddress(), aReq.getPort(), zResults.getAgentToken());
+ try {
+ service.registerAgent(request);
+ assert false : "Should not have been able to hijack agent A using Z's token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ request = createRequest(aReq.getName(), B_HOST, aReq.getPort(), zResults.getAgentToken());
+ try {
+ service.registerAgent(request);
+ assert false : "Should not have been able to hijack agent A using Z's token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ request = createRequest(aReq.getName(), aReq.getAddress(), B_PORT, zResults.getAgentToken());
+ try {
+ service.registerAgent(request);
+ assert false : "Should not have been able to hijack agent A using Z's token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ request = createRequest(aReq.getName(), B_HOST, B_PORT, zResults.getAgentToken());
+ try {
+ service.registerAgent(request);
+ assert false : "Should not have been able to hijack agent A using Z's token";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ }
+
+ @Test(dependsOnMethods = "testNormalAgentRegistration")
+ public void testAgentHijackingAnotherAgentAddressPort() throws Exception {
+ CoreServerServiceImpl service = new CoreServerServiceImpl();
+ AgentRegistrationRequest request;
+ request = createRequest(aReq.getName(), zReq.getAddress(), zReq.getPort(), aResults.getAgentToken());
+ try {
+ service.registerAgent(request);
+ assert false : "An agent should not have been able to hijack another agent's host/port";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ }
+
+ @Test(dependsOnMethods = "testNormalAgentRegistration")
+ public void testAttemptToChangeAgentName() throws Exception {
+ CoreServerServiceImpl service = new CoreServerServiceImpl();
+ AgentRegistrationRequest request;
+ request = createRequest(prefixName("newName"), zReq.getAddress(), zReq.getPort(), zResults.getAgentToken());
+ try {
+ service.registerAgent(request);
+ assert false : "An agent should not be able to change its name";
+ } catch (AgentRegistrationException ok) {
+ debugPrintThrowable(ok);
+ }
+ }
+
+ private AgentRegistrationRequest createRequest(String name, String address, int port, String token) {
+ return new AgentRegistrationRequest(name, address, port, "socket://" + address + ":" + port
+ + "/?rhq.communications.connector.rhqtype=agent", true, token, agentVersion);
+ }
+
+ private String prefixName(String name) {
+ return TEST_AGENT_NAME_PREFIX + name;
+ }
+
+ private void debugPrintThrowable(Throwable t) {
+ if (true) {
+ System.out.println(ThrowableUtil.getAllMessages(t));
+ }
+ }
+
+ interface DummyCoreServerMBean extends CoreServerMBean {
+ };
+
+ class DummyCoreServer implements DummyCoreServerMBean {
+
+ @Override
+ public String getVersion() {
+ return null;
+ }
+
+ @Override
+ public String getBuildNumber() {
+ return null;
+ }
+
+ @Override
+ public Date getBootTime() {
+ return null;
+ }
+
+ @Override
+ public File getInstallDir() {
+ return null;
+ }
+
+ @Override
+ public File getJBossServerHomeDir() {
+ return new File(System.getProperty("java.io.tmpdir"), "CoreServerServiceImplTest");
+ }
+
+ @Override
+ public File getJBossServerDataDir() {
+ return null;
+ }
+
+ @Override
+ public File getJBossServerTempDir() {
+ return null;
+ }
+
+ @Override
+ public ProductInfo getProductInfo() {
+ return null;
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/core/plugin/DatabaseAndFilePluginDeploymentTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/core/plugin/DatabaseAndFilePluginDeploymentTest.java
new file mode 100644
index 0000000..4a6a241
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/core/plugin/DatabaseAndFilePluginDeploymentTest.java
@@ -0,0 +1,605 @@
+/*
+ * 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.enterprise.server.core.plugin;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+import javax.transaction.TransactionManager;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
+import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.resource.metadata.PluginManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+//make sure we run this after the plugins.metadata tests are done so that
+//the db contents don't interfere
+@Test(dependsOnGroups = "plugin.metadata")
+public class DatabaseAndFilePluginDeploymentTest extends AbstractEJB3Test {
+
+ private static final String PLUGIN_NAME = "DeployTest"; // as defined in our test descriptors
+ private static final String DESCRIPTORS_LOCATION = "./target/test-classes/test/deployment/";
+ private static final String JARS_LOCATION = DESCRIPTORS_LOCATION + "jars";
+ private static final String DEPLOY_LOCATION = DESCRIPTORS_LOCATION + "deploy";
+ private static final String TESTPLUGIN_1_0_FEB = "1.0-feb";
+ private static final String TESTPLUGIN_1_0_JUN = "1.0-june";
+ private static final String TESTPLUGIN_1_1_FEB = "1.1-feb";
+ private static final String TESTPLUGIN_1_1_JUN = "1.1-june";
+ private static final String TESTPLUGIN_1_0_FEB2 = "1.0-feb-2";
+ private final Map<String, File> testPluginFiles = new HashMap<String, File>();
+ private final Map<String, Plugin> testPlugins = new HashMap<String, Plugin>();
+ private final Map<String, Date> testTimestamps = new HashMap<String, Date>();
+ private final Map<String, PluginDescriptor> testPluginDescriptors = new HashMap<String, PluginDescriptor>();
+ private PluginManagerLocal pluginMgr;
+ private SubjectManagerLocal subjectManager;
+
+ // Here is a matrix of scenarios we are going to test.
+ // "Winning Plugin" means the plugin considered the most up-to-date (not obsolete).
+ // "Reason" == "exists" means the winning plugin was the only one that existed
+ // "Reason" == "version" means the winning plugin had the newer version
+ // "Reason" == "time" means the winning plugin had the newer/later timestamp
+ // ==========================================================================
+ // | Plugins Deployed In: | Winning | Reason | Side
+ // # | Filesystem | Database | Plugin | | Effects
+ // ==========================================================================
+ // 0 | 1.0-feb | 1.0-feb | N/A | N/A | steady state - all up-to-date
+ // 1 | 1.0-feb | N/A | Filesystem | exists | DB row created
+ // 2 | N/A | 1.0-feb | Database | exists | file created
+ // 3 | 1.0-jun | 1.0-feb | Filesystem | time | DB row updated
+ // 4 | 1.0-feb | 1.0-jun | Database | time | file 1.0-feb deleted, file 1.0-jun created
+ // 5 | 1.1-jun | 1.0-jun | Filesystem | version | DB row updated
+ // 6 | 1.0-jun | 1.1-jun | Database | version | file 1.0-jun deleted, file 1.1-jun created
+ // 7 | 1.1-feb | 1.0-jun | Filesystem | version | DB row updated
+ // 8 | 1.0-jun | 1.1-feb | Database | version | file 1.0-jun deleted, file 1.1-feb created
+ // ------ the tests below have two plugins deployed on the file system ------
+ // 9 | 1.0-feb | 1.0-feb | Filesystem | time | file 1.0-feb deleted,
+ // | 1.0-jun | | | | DB row updated
+ // --------------------------------------------------------------------------
+ // 10| 1.0-feb | 1.0-jun | None | N/A | file 1.0-feb deleted,
+ // | 1.0-jun | | | |
+ // --------------------------------------------------------------------------
+ // 11| 1.0-feb | 1.1-feb | Database | version | files 1.0-feb/jun deleted,
+ // | 1.0-jun | | | | file 1.1-feb created
+ // --------------------------------------------------------------------------
+ // 12| 1.0-feb | 1.0-feb | Filesystem | version | file 1.0-feb deleted,
+ // | 1.1-jun | | | | DB row updated
+ // --------------------------------------------------------------------------
+ // 13| 1.0-feb | 1.1-feb | Filesystem | time | file 1.0-feb deleted,
+ // | 1.1-jun | | | | DB row updated
+ // --------------------------------------------------------------------------
+ // 14| 1.0-feb | 1.0-feb | None | N/A | all files are the same but
+ // | 1.0-feb-2 | | | | one of the files gets deleted
+ // --------------------------------------------------------------------------
+
+ @BeforeClass
+ public void beforeClass() throws Exception {
+ Calendar cal = Calendar.getInstance();
+ cal.set(2009, Calendar.FEBRUARY, 1, 1, 0, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+ Date febDate = cal.getTime();
+ cal.set(2009, Calendar.JUNE, 1, 1, 0, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+ Date juneDate = cal.getTime();
+ testTimestamps.put(TESTPLUGIN_1_0_FEB, febDate);
+ testTimestamps.put(TESTPLUGIN_1_0_JUN, juneDate);
+ testTimestamps.put(TESTPLUGIN_1_1_FEB, febDate);
+ testTimestamps.put(TESTPLUGIN_1_1_JUN, juneDate);
+ testTimestamps.put(TESTPLUGIN_1_0_FEB2, febDate);
+
+ pluginMgr = LookupUtil.getPluginManager();
+ subjectManager = LookupUtil.getSubjectManager();
+
+ File deployDir = new File(DEPLOY_LOCATION);
+ deployDir.mkdirs();
+ assert deployDir.isDirectory();
+
+ File jarsDir = new File(JARS_LOCATION);
+ jarsDir.mkdirs();
+ assert jarsDir.isDirectory();
+
+ testPluginFiles.put(TESTPLUGIN_1_0_FEB, new File(jarsDir, TESTPLUGIN_1_0_FEB + ".jar"));
+ testPluginFiles.put(TESTPLUGIN_1_0_JUN, new File(jarsDir, TESTPLUGIN_1_0_JUN + ".jar"));
+ testPluginFiles.put(TESTPLUGIN_1_1_FEB, new File(jarsDir, TESTPLUGIN_1_1_FEB + ".jar"));
+ testPluginFiles.put(TESTPLUGIN_1_1_JUN, new File(jarsDir, TESTPLUGIN_1_1_JUN + ".jar"));
+ testPluginFiles.put(TESTPLUGIN_1_0_FEB2, new File(jarsDir, TESTPLUGIN_1_0_FEB2 + ".jar"));
+
+ for (Map.Entry<String, File> entry : testPluginFiles.entrySet()) {
+ File descriptorFile = new File(DESCRIPTORS_LOCATION, entry.getKey() + ".xml");
+ File file = entry.getValue();
+ buildPluginJar(descriptorFile, file);
+ assert file.exists();
+
+ PluginDescriptor descriptor = AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(file.toURI().toURL());
+ testPluginDescriptors.put(entry.getKey(), descriptor);
+
+ Plugin pluginPojo = new Plugin(PLUGIN_NAME, file.getName());
+ pluginPojo.setVersion(descriptor.getVersion());
+ pluginPojo.setMd5(MessageDigestGenerator.getDigestString(file));
+ pluginPojo.setMtime(testTimestamps.get(entry.getKey()).getTime());
+ testPlugins.put(entry.getKey(), pluginPojo);
+ }
+
+ return;
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void afterClass() throws Exception {
+ for (Map.Entry<String, File> entry : testPluginFiles.entrySet()) {
+ File doomed = entry.getValue();
+ doomed.delete();
+ }
+ File jarsDir = new File(JARS_LOCATION);
+ jarsDir.delete();
+
+ File deployDir = new File(DEPLOY_LOCATION);
+ emptyDirectory(deployDir);
+ deployDir.delete();
+
+ return;
+ }
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ afterMethod(); // we clean up before and after, just to be sure we're clean
+
+ File deployDir = new File(DEPLOY_LOCATION);
+ deployDir.mkdirs();
+ assert deployDir.isDirectory();
+
+ File jarsDir = new File(JARS_LOCATION);
+ jarsDir.mkdirs();
+ assert jarsDir.isDirectory();
+
+ for (Map.Entry<String, File> entry : testPluginFiles.entrySet()) {
+ File descriptorFile = new File(DESCRIPTORS_LOCATION, entry.getKey() + ".xml");
+ File file = entry.getValue();
+ buildPluginJar(descriptorFile, file);
+ assert file.exists();
+
+ PluginDescriptor descriptor = AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(file.toURI().toURL());
+ testPluginDescriptors.put(entry.getKey(), descriptor);
+
+ Plugin pluginPojo = new Plugin(PLUGIN_NAME, file.getName());
+ pluginPojo.setVersion(descriptor.getVersion());
+ pluginPojo.setMd5(MessageDigestGenerator.getDigestString(file));
+ pluginPojo.setMtime(testTimestamps.get(entry.getKey()).getTime());
+ testPlugins.put(entry.getKey(), pluginPojo);
+ }
+
+ }
+
+ @AfterMethod(alwaysRun = true)
+ @SuppressWarnings("unchecked")
+ public void afterMethod() throws Exception {
+
+ emptyDirectory(new File(DEPLOY_LOCATION));
+
+ TransactionManager tm = getTransactionManager();
+ tm.begin();
+ EntityManager em = getEntityManager();
+ try {
+ Query q = em.createNamedQuery(Plugin.QUERY_FIND_BY_NAME);
+ q.setParameter("name", PLUGIN_NAME);
+ List<Plugin> doomedPlugins = q.getResultList();
+ for (Plugin doomedPlugin : doomedPlugins) {
+ em.remove(em.find(Plugin.class, doomedPlugin.getId()));
+ }
+ } catch (NoResultException ignore) {
+ } finally {
+ tm.commit();
+ em.close();
+ }
+
+ return;
+ }
+
+ public void test0() throws Exception {
+ Plugin plugin10feb = deployPluginJarToFilesystem(TESTPLUGIN_1_0_FEB);
+ deployPluginJarToDatabase(TESTPLUGIN_1_0_FEB);
+
+ createScannerAndScan(TESTPLUGIN_1_0_FEB);
+ assertPluginInDb(plugin10feb);
+ assertPluginOnFilesystem(plugin10feb);
+ return;
+ }
+
+ public void test1() throws Exception {
+ Plugin plugin10feb = deployPluginJarToFilesystem(TESTPLUGIN_1_0_FEB);
+
+ createScannerAndScan(TESTPLUGIN_1_0_FEB);
+ assertPluginInDb(plugin10feb);
+ assertPluginOnFilesystem(plugin10feb);
+ return;
+ }
+
+ public void test2() throws Exception {
+ Plugin plugin10feb = deployPluginJarToDatabase(TESTPLUGIN_1_0_FEB);
+
+ PluginDeploymentScanner scanner = createScanner();
+ scan(scanner, null);
+ assertPluginInDb(plugin10feb);
+ assertPluginOnFilesystem(plugin10feb);
+
+ scan(null, TESTPLUGIN_1_0_FEB);
+ assertPluginInDb(plugin10feb);
+ assertPluginOnFilesystem(plugin10feb);
+ return;
+ }
+
+ public void test3() throws Exception {
+ Plugin plugin10jun = deployPluginJarToFilesystem(TESTPLUGIN_1_0_JUN);
+ deployPluginJarToDatabase(TESTPLUGIN_1_0_FEB);
+
+ createScannerAndScan(TESTPLUGIN_1_0_JUN);
+ assertPluginInDb(plugin10jun);
+ assertPluginOnFilesystem(plugin10jun);
+ return;
+ }
+
+ public void test4() throws Exception {
+ Plugin plugin10feb = deployPluginJarToFilesystem(TESTPLUGIN_1_0_FEB);
+ Plugin plugin10jun = deployPluginJarToDatabase(TESTPLUGIN_1_0_JUN);
+
+ createScannerAndScan(null);
+ assertPluginInDb(plugin10jun);
+ assertPluginOnFilesystem(plugin10jun);
+ assertPluginNotOnFilesystem(plugin10feb);
+
+ scan(null, TESTPLUGIN_1_0_JUN);
+ assertPluginInDb(plugin10jun);
+ assertPluginOnFilesystem(plugin10jun);
+ assertPluginNotOnFilesystem(plugin10feb);
+ return;
+ }
+
+ public void test5() throws Exception {
+ Plugin plugin11jun = deployPluginJarToFilesystem(TESTPLUGIN_1_1_JUN);
+ deployPluginJarToDatabase(TESTPLUGIN_1_0_JUN);
+
+ createScannerAndScan(TESTPLUGIN_1_1_JUN);
+ assertPluginInDb(plugin11jun);
+ assertPluginOnFilesystem(plugin11jun);
+ return;
+ }
+
+ public void test6() throws Exception {
+ Plugin plugin10jun = deployPluginJarToFilesystem(TESTPLUGIN_1_0_JUN);
+ Plugin plugin11jun = deployPluginJarToDatabase(TESTPLUGIN_1_1_JUN);
+
+ createScannerAndScan(null);
+ assertPluginInDb(plugin11jun);
+ assertPluginOnFilesystem(plugin11jun);
+ assertPluginNotOnFilesystem(plugin10jun);
+
+ scan(null, TESTPLUGIN_1_1_JUN);
+ assertPluginInDb(plugin11jun);
+ assertPluginOnFilesystem(plugin11jun);
+ assertPluginNotOnFilesystem(plugin10jun);
+ return;
+ }
+
+ public void test7() throws Exception {
+ Plugin plugin11feb = deployPluginJarToFilesystem(TESTPLUGIN_1_1_FEB);
+ deployPluginJarToDatabase(TESTPLUGIN_1_0_JUN);
+
+ createScannerAndScan(TESTPLUGIN_1_1_FEB);
+ assertPluginInDb(plugin11feb);
+ assertPluginOnFilesystem(plugin11feb);
+ return;
+ }
+
+ public void test8() throws Exception {
+ Plugin plugin10jun = deployPluginJarToFilesystem(TESTPLUGIN_1_0_JUN);
+ Plugin plugin11feb = deployPluginJarToDatabase(TESTPLUGIN_1_1_FEB);
+
+ createScannerAndScan(null);
+ assertPluginInDb(plugin11feb);
+ assertPluginOnFilesystem(plugin11feb);
+ assertPluginNotOnFilesystem(plugin10jun);
+
+ scan(null, TESTPLUGIN_1_1_FEB);
+ assertPluginInDb(plugin11feb);
+ assertPluginOnFilesystem(plugin11feb);
+ assertPluginNotOnFilesystem(plugin10jun);
+ return;
+ }
+
+ public void test9() throws Exception {
+ Plugin plugin10feb = deployPluginJarToFilesystem(TESTPLUGIN_1_0_FEB);
+ Plugin plugin10jun = deployPluginJarToFilesystem(TESTPLUGIN_1_0_JUN);
+ deployPluginJarToDatabase(TESTPLUGIN_1_0_FEB);
+
+ createScannerAndScan(null);
+ assertPluginInDb(plugin10feb); // still the old one, will get updated when the file is deployed
+ assertPluginOnFilesystem(plugin10jun);
+ assertPluginNotOnFilesystem(plugin10feb);
+
+ scan(null, TESTPLUGIN_1_0_JUN);
+ assertPluginInDb(plugin10jun); // bingo - file scan brought the plugin on filesystem into db
+ assertPluginOnFilesystem(plugin10jun);
+ assertPluginNotOnFilesystem(plugin10feb);
+ return;
+ }
+
+ public void test10() throws Exception {
+ Plugin plugin10feb = deployPluginJarToFilesystem(TESTPLUGIN_1_0_FEB);
+ Plugin plugin10jun = deployPluginJarToFilesystem(TESTPLUGIN_1_0_JUN);
+ deployPluginJarToDatabase(TESTPLUGIN_1_0_JUN);
+
+ createScannerAndScan(null);
+ assertPluginInDb(plugin10jun); // no change
+ assertPluginOnFilesystem(plugin10jun); // no change
+ assertPluginNotOnFilesystem(plugin10feb); // shows that the old duplicate is gone now
+
+ scan(null, TESTPLUGIN_1_0_JUN);
+ assertPluginInDb(plugin10jun); // bingo - file scan brought the plugin on filesystem into db
+ assertPluginOnFilesystem(plugin10jun);
+ assertPluginNotOnFilesystem(plugin10feb);
+ return;
+ }
+
+ public void test11() throws Exception {
+ Plugin plugin10feb = deployPluginJarToFilesystem(TESTPLUGIN_1_0_FEB);
+ Plugin plugin10jun = deployPluginJarToFilesystem(TESTPLUGIN_1_0_JUN);
+ Plugin plugin11feb = deployPluginJarToDatabase(TESTPLUGIN_1_1_FEB);
+
+ createScannerAndScan(null);
+ assertPluginInDb(plugin11feb);
+ assertPluginOnFilesystem(plugin11feb);
+ assertPluginNotOnFilesystem(plugin10feb);
+ assertPluginNotOnFilesystem(plugin10jun);
+
+ scan(null, TESTPLUGIN_1_1_FEB);
+ assertPluginInDb(plugin11feb);
+ assertPluginOnFilesystem(plugin11feb);
+ assertPluginNotOnFilesystem(plugin10feb);
+ assertPluginNotOnFilesystem(plugin10jun);
+ return;
+ }
+
+ public void test12() throws Exception {
+ Plugin plugin10feb = deployPluginJarToFilesystem(TESTPLUGIN_1_0_FEB);
+ Plugin plugin11jun = deployPluginJarToFilesystem(TESTPLUGIN_1_1_JUN);
+ deployPluginJarToDatabase(TESTPLUGIN_1_0_FEB);
+
+ createScannerAndScan(null);
+ assertPluginInDb(plugin10feb); // still the old one, will get updated when the file is deployed
+ assertPluginOnFilesystem(plugin11jun);
+ assertPluginNotOnFilesystem(plugin10feb);
+
+ scan(null, TESTPLUGIN_1_1_JUN);
+ assertPluginInDb(plugin11jun);
+ assertPluginOnFilesystem(plugin11jun);
+ assertPluginNotOnFilesystem(plugin10feb);
+ return;
+ }
+
+ public void test13() throws Exception {
+ Plugin plugin10feb = deployPluginJarToFilesystem(TESTPLUGIN_1_0_FEB);
+ Plugin plugin11jun = deployPluginJarToFilesystem(TESTPLUGIN_1_1_JUN);
+ Plugin plugin11feb = deployPluginJarToDatabase(TESTPLUGIN_1_1_FEB);
+
+ createScannerAndScan(null);
+ assertPluginInDb(plugin11feb); // still the old one, will get updated when the file is deployed
+ assertPluginOnFilesystem(plugin11jun);
+ assertPluginNotOnFilesystem(plugin10feb);
+
+ scan(null, TESTPLUGIN_1_1_JUN);
+ assertPluginInDb(plugin11jun);
+ assertPluginOnFilesystem(plugin11jun);
+ assertPluginNotOnFilesystem(plugin10feb);
+ return;
+ }
+
+ public void test14() throws Exception {
+ Plugin plugin10feb = deployPluginJarToFilesystem(TESTPLUGIN_1_0_FEB);
+ Plugin plugin10feb2 = deployPluginJarToFilesystem(TESTPLUGIN_1_0_FEB2);
+ deployPluginJarToDatabase(TESTPLUGIN_1_0_FEB);
+
+ createScannerAndScan(null);
+ assertPluginInDb(plugin10feb);
+ boolean plugin10febExists = !isPluginNotOnFilesystem(plugin10feb);
+ boolean plugin10feb2Exists = !isPluginNotOnFilesystem(plugin10feb2);
+ assert plugin10febExists ^ plugin10feb2Exists; // one must exist, but only one (we aren't guaranteed which, they are identical)
+
+ scan(null, TESTPLUGIN_1_0_FEB);
+ assertPluginInDb(plugin10feb);
+ plugin10febExists = !isPluginNotOnFilesystem(plugin10feb);
+ plugin10feb2Exists = !isPluginNotOnFilesystem(plugin10feb2);
+ assert plugin10febExists ^ plugin10feb2Exists; // one must exist, but only one (we aren't guaranteed which, they are identical)
+ return;
+ }
+
+ private void assertSamePlugin(Plugin p1, Plugin p2) throws Exception {
+ assert p1.getName().equals(p2.getName()) : "NAME: " + p1 + "!=" + p2;
+ assert p1.getMd5().equals(p2.getMd5()) : "MD5: " + p1 + "!=" + p2;
+ assert p1.getMtime() == p2.getMtime() : "MTIME: " + p1 + "!=" + p2;
+ assert p1.getVersion().equals(p2.getVersion()) : "VERSION: " + p1 + "!=" + p2;
+ }
+
+ private void assertPluginOnFilesystem(Plugin plugin) throws Exception {
+ File file = new File(DEPLOY_LOCATION, plugin.getPath());
+ String version = AgentPluginDescriptorUtil.getPluginVersion(file, null).toString();
+ String md5 = MessageDigestGenerator.getDigestString(file);
+ long mtime = file.lastModified();
+ Plugin filePlugin = new Plugin(PLUGIN_NAME, file.getName());
+ filePlugin.setMd5(md5);
+ filePlugin.setVersion(version);
+ filePlugin.setMtime(mtime);
+ assertSamePlugin(plugin, filePlugin);
+ }
+
+ private void assertPluginInDb(Plugin plugin) throws Exception {
+ Plugin dbPlugin;
+
+ TransactionManager tm = getTransactionManager();
+ tm.begin();
+ EntityManager em = getEntityManager();
+ try {
+ Query q = em.createNamedQuery(Plugin.QUERY_FIND_BY_NAME);
+ q.setParameter("name", PLUGIN_NAME);
+ dbPlugin = (Plugin) q.getSingleResult();
+ } finally {
+ tm.rollback();
+ em.close();
+ }
+
+ assertSamePlugin(plugin, dbPlugin);
+ }
+
+ private void assertPluginNotOnFilesystem(Plugin plugin) throws Exception {
+ assert isPluginNotOnFilesystem(plugin);
+ }
+
+ private boolean isPluginNotOnFilesystem(Plugin plugin) {
+ File file = new File(DEPLOY_LOCATION, plugin.getPath());
+ return !file.exists();
+ }
+
+ private PluginDeploymentScanner createScannerAndScan(String pluginId) throws Exception {
+ PluginDeploymentScanner scanner = createScanner();
+ scan(scanner, pluginId); // see comments in scan() for what pluginId is
+ return scanner;
+ }
+
+ private PluginDeploymentScanner createScanner() throws Exception {
+ PluginDeploymentScanner scanner = new PluginDeploymentScanner();
+ File pluginDirectoryFile = new File(DEPLOY_LOCATION);
+ scanner.setAgentPluginDir(pluginDirectoryFile.getAbsolutePath());
+ return scanner;
+ }
+
+ /**
+ * Scans in both directions - first asks the db scanner to scan the database.
+ * Then it tries to register the plugin found on the filesystem.
+ * pluginId identifies the plugin on the filesystem that is to be scanned up to DB (if appropriate).
+ *
+ * @param scanner if not-null, uses this to perform a db scan first
+ * @param pluginId if not-null, this is registered (i.e. a file scan registering this plugin)
+ * @throws Exception
+ */
+ private void scan(PluginDeploymentScanner scanner, String pluginId) throws Exception {
+ if (scanner != null) {
+ scanner.scan();
+ }
+
+ if (pluginId != null) {
+ Plugin plugin = this.testPlugins.get(pluginId);
+ Plugin pluginDup = new Plugin(plugin.getName(), plugin.getPath(), plugin.getMd5());
+ pluginDup.setMtime(plugin.getMtime());
+ pluginDup.setVersion(plugin.getVersion());
+ PluginDescriptor pluginDescriptor = this.testPluginDescriptors.get(pluginId);
+ File localPluginFile = this.testPluginFiles.get(pluginId);
+ pluginMgr.registerPlugin(pluginDup, pluginDescriptor, localPluginFile, false);
+ }
+ return;
+ }
+
+ private Plugin deployPluginJarToDatabase(String pluginId) throws Exception {
+ Plugin plugin = testPlugins.get(pluginId);
+
+ // make our own copy since we will be persisting it and populating content in it
+ Plugin pluginPojo = new Plugin(plugin.getName(), plugin.getPath(), plugin.getMd5());
+ pluginPojo.setId(0);
+ pluginPojo.setDisplayName(plugin.getName());
+ pluginPojo.setVersion(plugin.getVersion());
+ pluginPojo.setMtime(plugin.getMtime());
+ pluginPojo.setContent(StreamUtil.slurp(new FileInputStream(testPluginFiles.get(pluginId))));
+
+ TransactionManager tm = getTransactionManager();
+ tm.begin();
+ EntityManager em = getEntityManager();
+ try {
+ em.persist(pluginPojo);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ tm.commit();
+ em.close();
+ }
+
+ return plugin; // do not return the persisted pojo, let GC collect the larger pojo with the file content
+ }
+
+ private Plugin deployPluginJarToFilesystem(String pluginId) throws Exception {
+ File pluginJar = testPluginFiles.get(pluginId);
+ File deployedPluginJar = new File(DEPLOY_LOCATION, pluginJar.getName());
+ FileOutputStream out = new FileOutputStream(deployedPluginJar);
+ FileInputStream in = new FileInputStream(pluginJar);
+ StreamUtil.copy(in, out);
+ timestampPluginJar(deployedPluginJar, pluginId); // make sure its last-mod time is correct
+
+ return testPlugins.get(pluginId);
+ }
+
+ private void timestampPluginJar(File pluginJar, String pluginId) throws Exception {
+ pluginJar.setLastModified(testTimestamps.get(pluginId).getTime());
+ }
+
+ private void buildPluginJar(File descriptor, File pluginJar) throws Exception {
+ FileOutputStream fos = new FileOutputStream(pluginJar);
+ ZipOutputStream zip = new ZipOutputStream(fos);
+ try {
+ ZipEntry zipEntry = new ZipEntry("META-INF/rhq-plugin.xml");
+ zip.putNextEntry(zipEntry);
+ InputStream input = new FileInputStream(descriptor);
+ try {
+ StreamUtil.copy(input, zip, false);
+ } finally {
+ input.close();
+ }
+ } finally {
+ zip.close();
+ }
+ }
+
+ private void emptyDirectory(File dirToEmpty) {
+ if (!dirToEmpty.isDirectory()) {
+ return;
+ }
+ File[] doomedFiles = dirToEmpty.listFiles();
+ for (File doomedFile : doomedFiles) {
+ doomedFile.delete();
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/db/DbSetupTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/db/DbSetupTest.java
new file mode 100644
index 0000000..c21bb72
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/db/DbSetupTest.java
@@ -0,0 +1,70 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2012 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.db;
+
+import java.util.Set;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.authz.Role;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.authz.RoleManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.DbSetupUtility;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Test that dbsetup initializes the data in the RHQ schema as intended (e.g. test that the Superuser and All Resources
+ * are created and have the correct permissions and users assigned to them.
+ *
+ * @author Ian Springer
+ */
+@Test(groups = "db", singleThreaded = true)
+public class DbSetupTest extends AbstractEJB3Test {
+
+ @BeforeClass(groups = "db")
+ public void setUp() throws Exception {
+ // Recreate a fresh JON DB with the latest schema.
+ DbSetupUtility.dbreset();
+ DbSetupUtility.dbsetup();
+ }
+
+ public void testRoles() throws Exception {
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ RoleManagerLocal roleManager = LookupUtil.getRoleManager();
+ Subject overlord = subjectManager.getOverlord();
+
+ Role superuserRole = roleManager.getRole(overlord, 1);
+ Set<Permission> superuserRoleOriginalPermissions = superuserRole.getPermissions();
+ assertTrue("[Superuser] role does not have all global permissions.",
+ superuserRoleOriginalPermissions.containsAll(Permission.GLOBAL_ALL));
+ assertTrue("[Superuser] role does not have all Resource permissions.",
+ superuserRoleOriginalPermissions.containsAll(Permission.RESOURCE_ALL));
+
+ Role allResourcesRole = roleManager.getRole(overlord, 2);
+ Set<Permission> allResourcesRoleOriginalPermissions = allResourcesRole.getPermissions();
+ assertTrue("[All Resources] role does not have MANAGE_INVENTORY permission.",
+ allResourcesRoleOriginalPermissions.contains(Permission.MANAGE_INVENTORY));
+ assertTrue("[All Resources] role does not have all Resource permissions.",
+ allResourcesRoleOriginalPermissions.containsAll(Permission.RESOURCE_ALL));
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/db/DbUpgradeTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/db/DbUpgradeTest.java
new file mode 100644
index 0000000..8883419
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/db/DbUpgradeTest.java
@@ -0,0 +1,98 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2012 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.db;
+
+import java.util.Set;
+import java.util.UUID;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.authz.Role;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.authz.RoleManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.DbSetupUtility;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Test that various dbupgrade schema versions update the data model as intended.
+ *
+ * @author Ian Springer
+ */
+@Test(groups = "db", singleThreaded = true)
+public class DbUpgradeTest extends AbstractEJB3Test {
+
+ @BeforeClass(groups = "db")
+ public void setUp() throws Exception {
+ // Recreate a fresh JON DB with the JON 2.3.1 schema, then upgrade it to the JON 3.0.0 schema.
+ DbSetupUtility.dbreset();
+ DbSetupUtility.dbsetup("2.3.1");
+ DbSetupUtility.dbupgrade(DbSetupUtility.JON300_SCHEMA_VERSION);
+ }
+
+ @AfterClass(groups = "db")
+ public void tearDown() throws Exception {
+ // Upgrade to the latest schema version so the DB is left in a state usable by other tests.
+ DbSetupUtility.dbupgrade("LATEST");
+ }
+
+ public void testUpgradeToV2_119() throws Exception {
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ RoleManagerLocal roleManager = LookupUtil.getRoleManager();
+ Subject overlord = subjectManager.getOverlord();
+
+ Role customRole = new Role("role" + UUID.randomUUID());
+ customRole.addPermission(Permission.MANAGE_REPOSITORIES);
+ customRole.addPermission(Permission.MANAGE_MEASUREMENTS);
+ customRole = roleManager.createRole(overlord, customRole);
+ Set<Permission> customRoleOriginalPermissions = customRole.getPermissions();
+ assertFalse(customRoleOriginalPermissions.contains(Permission.VIEW_USERS));
+
+ Role superuserRole = roleManager.getRole(overlord, 1);
+ Set<Permission> superuserRoleOriginalPermissions = superuserRole.getPermissions();
+ assertFalse(superuserRoleOriginalPermissions.contains(Permission.VIEW_USERS));
+
+ Role allResourcesRole = roleManager.getRole(overlord, 2);
+ Set<Permission> allResourcesRoleOriginalPermissions = allResourcesRole.getPermissions();
+ assertFalse(allResourcesRoleOriginalPermissions.contains(Permission.VIEW_USERS));
+
+ // Now upgrade the DB schema to v2.119, which introduces the VIEW_USERS global permission and adds it to any
+ // existing roles.
+ DbSetupUtility.dbupgrade("2.119");
+
+ customRole = roleManager.getRole(overlord, customRole.getId());
+ Set<Permission> customRoleNewPermissions = customRole.getPermissions();
+ customRoleOriginalPermissions.add(Permission.VIEW_USERS);
+ assertEquals(customRoleOriginalPermissions, customRoleNewPermissions);
+
+ superuserRole = roleManager.getRole(overlord, 1);
+ Set<Permission> superuserRoleNewPermissions = superuserRole.getPermissions();
+ superuserRoleOriginalPermissions.add(Permission.VIEW_USERS);
+ assertEquals(superuserRoleOriginalPermissions, superuserRoleNewPermissions);
+
+ allResourcesRole = roleManager.getRole(overlord, 2);
+ Set<Permission> allResourcesRoleNewPermissions = allResourcesRole.getPermissions();
+ allResourcesRoleOriginalPermissions.add(Permission.VIEW_USERS);
+ assertEquals(allResourcesRoleOriginalPermissions, allResourcesRoleNewPermissions);
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/discovery/DeletedResourceTypeFilterTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/discovery/DeletedResourceTypeFilterTest.java
new file mode 100644
index 0000000..1c3dc7d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/discovery/DeletedResourceTypeFilterTest.java
@@ -0,0 +1,190 @@
+package org.rhq.enterprise.server.discovery;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.jmock.Expectations;
+
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.server.discovery.InventoryReport;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.criteria.ResourceTypeCriteria;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.shared.ResourceBuilder;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.shared.ResourceTypeBuilder;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
+import org.rhq.enterprise.server.resource.metadata.PluginManagerLocal;
+import org.rhq.test.JMockTest;
+
+import static org.testng.Assert.*;
+
+public class DeletedResourceTypeFilterTest extends JMockTest {
+
+ SubjectManagerLocal subjectMgr;
+
+ ResourceTypeManagerLocal resourceTypeMgr;
+
+ PluginManagerLocal pluginMgr;
+
+ DeletedResourceTypeFilter filter;
+
+ @BeforeMethod
+ public void init() {
+ subjectMgr = context.mock(SubjectManagerLocal.class);
+ resourceTypeMgr = context.mock(ResourceTypeManagerLocal.class);
+ pluginMgr = context.mock(PluginManagerLocal.class);
+ }
+
+ @Test
+ public void acceptReportWithNoDeletedTypes() {
+ InventoryReport report = createReport();
+ report.addAddedRoot(new ResourceBuilder()
+ .createRandomServer()
+ .with(2).randomChildServices()
+ .build());
+ report.addAddedRoot(new ResourceBuilder()
+ .createRandomService()
+ .with(2).randomChildServices()
+ .build());
+
+ final List<Plugin> plugins = new ArrayList<Plugin>(getPluginsInReport(report.getAddedRoots()));
+
+ context.checking(new Expectations() {{
+ allowing(subjectMgr).getOverlord();
+ will(returnValue(new Subject("overlord", true, true)));
+
+ allowing(resourceTypeMgr).findResourceTypesByCriteria(with(aNonNull(Subject.class)),
+ with(aNonNull(ResourceTypeCriteria.class)));
+ will(returnValue(new PageList<ResourceType>()));
+
+ allowing(pluginMgr).getInstalledPlugins();
+ will(returnValue(plugins));
+ }});
+
+ filter = new DeletedResourceTypeFilter(subjectMgr, resourceTypeMgr, pluginMgr);
+
+ assertTrue(filter.accept(report), "Expected report to be accepted when it does not contain any deleted " +
+ "resource types");
+ }
+
+ @Test
+ public void rejectReportWithDeletedTypes() {
+ ResourceType deletedServiceType = new ResourceTypeBuilder()
+ .createServiceResourceType()
+ .withName("TestService")
+ .withPlugin("TestPlugin")
+ .thatIsDeleted()
+ .build();
+
+ final PageList<ResourceType> deletedTypes = new PageList<ResourceType>();
+ deletedTypes.add(deletedServiceType);
+
+ InventoryReport report = createReport();
+ report.addAddedRoot(new ResourceBuilder()
+ .createRandomServer()
+ .withChildService()
+ .withName("ChildService")
+ .withUuid("c1")
+ .withResourceType(new ResourceTypeBuilder()
+ .createServiceResourceType()
+ .withName("TestService")
+ .withPlugin("TestPlugin")
+ .build())
+ .included()
+ .build());
+
+ final List<Plugin> plugins = new ArrayList<Plugin>(getPluginsInReport(report.getAddedRoots()));
+
+ context.checking(new Expectations() {{
+ allowing(subjectMgr).getOverlord();
+ will(returnValue(new Subject("overlord", true, true)));
+
+ allowing(resourceTypeMgr).findResourceTypesByCriteria(with(aNonNull(Subject.class)),
+ with(aNonNull(ResourceTypeCriteria.class)));
+ will(returnValue(deletedTypes));
+
+ allowing(pluginMgr).getInstalledPlugins();
+ will(returnValue(plugins));
+ }});
+
+ filter = new DeletedResourceTypeFilter(subjectMgr, resourceTypeMgr, pluginMgr);
+
+ assertFalse(filter.accept(report), "Expected report to be rejected since it contains deleted resource types");
+ }
+
+ @Test
+ public void rejectReportWithPluginThatIsNotInstalled() {
+ InventoryReport report = createReport();
+ report.addAddedRoot(new ResourceBuilder()
+ .createRandomServer()
+ .with(2).randomChildServices()
+ .build());
+ report.addAddedRoot(new ResourceBuilder()
+ .createRandomService()
+ .withResourceType(new ResourceTypeBuilder()
+ .createServerResourceType()
+ .withName("StaleServer")
+ .withPlugin("DeletedPlugin")
+ .build())
+ .with(2).randomChildServices()
+ .build());
+
+ List<Plugin> plugins = new ArrayList<Plugin>(getPluginsInReport(report.getAddedRoots()));
+ final List<Plugin> installedPlugins = removePlugins(plugins, "DeletedPlugin");
+
+ context.checking(new Expectations() {{
+ allowing(subjectMgr).getOverlord();
+ will(returnValue(new Subject("overlord", true, true)));
+
+ allowing(resourceTypeMgr).findResourceTypesByCriteria(with(aNonNull(Subject.class)),
+ with(aNonNull(ResourceTypeCriteria.class)));
+ will(returnValue(new PageList<ResourceType>()));
+
+ allowing(pluginMgr).getInstalledPlugins();
+ will(returnValue(installedPlugins));
+ }});
+
+ filter = new DeletedResourceTypeFilter(subjectMgr, resourceTypeMgr, pluginMgr);
+
+ assertFalse(filter.accept(report), "Expected report to be rejected since it contains a deleted plugin");
+ }
+
+ InventoryReport createReport() {
+ Agent agent = new Agent("localhost", "localhost", 1234, "1234", "test-token");
+ return new InventoryReport(agent);
+ }
+
+ private Set<Plugin> getPluginsInReport(Set<Resource> resources) {
+ Set<Plugin> plugins = new HashSet<Plugin>();
+ for (Resource resource : resources) {
+ String name = resource.getResourceType().getPlugin();
+ plugins.add(new Plugin(name, "/plugins/" + name));
+ plugins.addAll(getPluginsInReport(resource.getChildResources()));
+ }
+ return plugins;
+ }
+
+ private List<Plugin> removePlugins(List<Plugin> plugins, String... pluginsToRemove) {
+ Set<String> removedPlugins = new HashSet<String>(Arrays.asList(pluginsToRemove));
+ List<Plugin> filteredPlugins = new ArrayList<Plugin>();
+
+ for (Plugin plugin : plugins) {
+ if (!removedPlugins.contains(plugin.getName())) {
+ filteredPlugins.add(plugin);
+ }
+ }
+ return filteredPlugins;
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.java
new file mode 100644
index 0000000..d4d9cbf
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.java
@@ -0,0 +1,361 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.discovery;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.sql.Connection;
+import java.util.List;
+import java.util.Random;
+import java.util.UUID;
+
+import javax.ejb.EJBException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.dbunit.database.DatabaseConfig;
+import org.dbunit.database.DatabaseConnection;
+import org.dbunit.database.IDatabaseConnection;
+import org.dbunit.dataset.IDataSet;
+import org.dbunit.dataset.datatype.IDataTypeFactory;
+import org.dbunit.dataset.xml.FlatXmlDataSet;
+import org.dbunit.dataset.xml.FlatXmlProducer;
+import org.dbunit.ext.oracle.Oracle10DataTypeFactory;
+import org.dbunit.ext.oracle.OracleDataTypeFactory;
+import org.dbunit.ext.postgresql.PostgresqlDataTypeFactory;
+import org.dbunit.operation.DatabaseOperation;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.xml.sax.InputSource;
+
+import org.jboss.mx.util.MBeanServerLocator;
+
+import org.rhq.core.clientapi.agent.discovery.DiscoveryAgentService;
+import org.rhq.core.clientapi.server.discovery.InventoryReport;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.discovery.MergeResourceResponse;
+import org.rhq.core.domain.discovery.ResourceSyncInfo;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.core.comm.ServerCommunicationsService;
+import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceMBean;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.ResourceTreeHelper;
+
+/**
+ * A unit test for {@link DiscoveryBossBean}.
+ */
+public class DiscoveryBossBeanTest extends AbstractEJB3Test {
+
+ private DiscoveryBossLocal discoveryBoss;
+
+ private SubjectManagerLocal subjectManager;
+
+ private ResourceManagerLocal resourceManager;
+
+ private MBeanServer dummyJBossMBeanServer;
+
+ private ResourceType platformType;
+
+ private ResourceType serverType;
+
+ private ResourceType serviceType1;
+
+ private ResourceType serviceType2;
+
+ private Agent agent;
+
+ private TestServerCommunicationsService agentServiceContainer;
+
+ @BeforeClass
+ public void beforeClass() throws Exception {
+ discoveryBoss = LookupUtil.getDiscoveryBoss();
+ subjectManager = LookupUtil.getSubjectManager();
+ resourceManager = LookupUtil.getResourceManager();
+ }
+
+ @BeforeMethod
+ public void setupTestData() throws Exception {
+ dummyJBossMBeanServer = MBeanServerFactory.createMBeanServer("jboss");
+ MBeanServerLocator.setJBoss(dummyJBossMBeanServer);
+ dummyJBossMBeanServer.registerMBean(new ServerCommunicationsService(),
+ ServerCommunicationsServiceMBean.OBJECT_NAME);
+
+ initDB();
+
+ platformType = getEntityManager().find(ResourceType.class, 1);
+ serverType = getEntityManager().find(ResourceType.class, 2);
+ serviceType1 = getEntityManager().find(ResourceType.class, 3);
+ serviceType2 = getEntityManager().find(ResourceType.class, 4);
+ agent = getEntityManager().find(Agent.class, 1);
+
+ agentServiceContainer = prepareForTestAgents();
+ agentServiceContainer.discoveryService = Mockito.mock(DiscoveryAgentService.class);
+ when(
+ agentServiceContainer.discoveryService.manuallyAddResource(any(ResourceType.class), anyInt(),
+ any(Configuration.class), anyInt())).thenAnswer(new Answer<MergeResourceResponse>() {
+ public MergeResourceResponse answer(InvocationOnMock invocation) throws Throwable {
+ Resource resource = new Resource(1000000);
+ resource.setUuid(UUID.randomUUID().toString());
+ ResourceType resourceType = (ResourceType) invocation.getArguments()[0];
+ resource.setResourceType(resourceType);
+ long randomLong = UUID.randomUUID().getLeastSignificantBits();
+ resource.setResourceKey(String.valueOf("key-" + randomLong));
+ resource.setName("name-" + randomLong);
+ int parentResourceId = (Integer) invocation.getArguments()[1];
+ Resource parentResource = resourceManager.getResource(subjectManager.getOverlord(), parentResourceId);
+ resource.setParentResource(parentResource);
+ Integer ownerSubjectId = (Integer) invocation.getArguments()[3];
+ return discoveryBoss.addResource(resource, ownerSubjectId);
+ }
+ });
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ try {
+ MBeanServerFactory.releaseMBeanServer(dummyJBossMBeanServer);
+
+ cleanDB();
+ } finally {
+ unprepareForTestAgents();
+ }
+ }
+
+ @Test(groups = "integration.ejb3")
+ public void testBasicInventoryReport() throws Exception {
+ InventoryReport inventoryReport = new InventoryReport(agent);
+
+ Resource platform = new Resource("alpha", "platform", platformType);
+ Resource server = new Resource("bravo", "server", serverType);
+ platform.addChildResource(server);
+ Resource service1 = new Resource("charlie", "service 1", serviceType1);
+ Resource service2 = new Resource("delta", "service 2", serviceType2);
+ server.addChildResource(service1);
+ server.addChildResource(service2);
+
+ platform.setUuid("" + new Random().nextInt());
+ server.setUuid("" + new Random().nextInt());
+ service1.setUuid("" + new Random().nextInt());
+ service2.setUuid("" + new Random().nextInt());
+
+ inventoryReport.addAddedRoot(platform);
+
+ ResourceSyncInfo syncInfo = discoveryBoss.mergeInventoryReport(serialize(inventoryReport));
+ assert syncInfo != null;
+ }
+
+ @Test(groups = "integration.ejb3")
+ public void testUpdateInventoryReport() throws Exception {
+ // First just submit the platform
+ InventoryReport inventoryReport = new InventoryReport(agent);
+ Resource platform = new Resource("alpha", "platform", platformType);
+ platform.setUuid("" + new Random().nextInt());
+ inventoryReport.addAddedRoot(platform);
+ ResourceSyncInfo syncInfo = discoveryBoss.mergeInventoryReport(serialize(inventoryReport));
+ assert syncInfo != null;
+
+ platform.setId(syncInfo.getId());
+
+ // Now submit the server and its children as an update report
+ inventoryReport = new InventoryReport(agent);
+ Resource server = new Resource("bravo", "server", serverType);
+ platform.addChildResource(server);
+ Resource service1 = new Resource("charlie", "service 1", serviceType1);
+ Resource service2 = new Resource("delta", "service 2", serviceType2);
+ server.addChildResource(service1);
+ server.addChildResource(service2);
+
+ server.setUuid("" + new Random().nextInt());
+ service1.setUuid("" + new Random().nextInt());
+ service2.setUuid("" + new Random().nextInt());
+
+ inventoryReport.addAddedRoot(server);
+
+ syncInfo = discoveryBoss.mergeInventoryReport(serialize(inventoryReport));
+ assert syncInfo != null;
+ }
+
+ @Test(groups = "integration.ejb3")
+ public void testManuallyAddResource() throws Exception {
+ InventoryReport inventoryReport = new InventoryReport(agent);
+
+ Resource platform = new Resource("alpha", "platform", platformType);
+ Resource server = new Resource("bravo", "server", serverType);
+ platform.addChildResource(server);
+ Resource service2 = new Resource("delta", "service 2", serviceType2);
+ server.addChildResource(service2);
+
+ platform.setUuid("" + new Random().nextInt());
+ server.setUuid("" + new Random().nextInt());
+ service2.setUuid("" + new Random().nextInt());
+
+ inventoryReport.addAddedRoot(platform);
+
+ ResourceSyncInfo syncInfo = discoveryBoss.mergeInventoryReport(serialize(inventoryReport));
+ assert syncInfo != null;
+
+ ResourceSyncInfo serverSyncInfo = syncInfo.getChildSyncInfos().iterator().next();
+ Resource resource1 = discoveryBoss.manuallyAddResource(subjectManager.getOverlord(), serviceType2.getId(),
+ serverSyncInfo.getId(), new Configuration());
+
+ try {
+ Resource resource2 = discoveryBoss.manuallyAddResource(subjectManager.getOverlord(), serviceType2.getId(),
+ serverSyncInfo.getId(), new Configuration());
+ fail("Manually adding a singleton that already existed succeeded: " + resource2);
+ } catch (EJBException e) {
+ assertEquals(String.valueOf(e.getCause()), RuntimeException.class, e.getCause().getClass());
+ assertTrue(String.valueOf(e.getCause()), e.getCause().getMessage().contains("singleton"));
+ }
+ }
+
+ /**
+ * Use this to fake like your remoting objects. Can be used to keep your own copy of objects locally transient.
+ *
+ * @param object
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ private static <T> T serialize(T object) {
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(10000);
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(object);
+ System.out.println("****** Size of serialized object: " + baos.size());
+
+ ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
+ Object transfered = ois.readObject();
+
+ return (T) transfered;
+ } catch (Exception e) {
+ throw new RuntimeException("Failed serializing and deserializing object: " + object);
+ }
+ }
+
+ public void initDB() throws Exception {
+ Connection connection = null;
+
+ try {
+ connection = getConnection();
+ IDatabaseConnection dbUnitConnection = new DatabaseConnection(connection);
+ setDbType(dbUnitConnection);
+ DatabaseOperation.REFRESH.execute(dbUnitConnection, getDataSet());
+ } finally {
+ if (connection != null) {
+ connection.close();
+ }
+ }
+ }
+
+ public void cleanDB() throws Exception {
+ Connection connection = null;
+ EntityManager em = null;
+
+ try {
+ getTransactionManager().begin();
+ em = getEntityManager();
+
+ Query q;
+ List<?> doomed;
+ q = em.createQuery("SELECT r FROM Resource r WHERE r.resourceType.id <= 4 ORDER BY r.id DESC");
+ doomed = q.getResultList();
+ for (Object removeMe : doomed) {
+ Resource res = em.getReference(Resource.class, ((Resource) removeMe).getId());
+ ResourceTreeHelper.deleteResource(em, res);
+ }
+ em.flush();
+ getTransactionManager().commit();
+ em.close();
+ em = null;
+ } catch (Exception e) {
+ try {
+ System.out.println("CANNOT CLEAN UP TEST: Cause: " + e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+ } finally {
+ if (null != em) {
+ em.close();
+ }
+ }
+
+ try {
+ connection = getConnection();
+
+ IDatabaseConnection dbUnitConnection = new DatabaseConnection(connection);
+ setDbType(dbUnitConnection);
+ DatabaseOperation.DELETE.execute(dbUnitConnection, getDataSet());
+ } finally {
+ if (connection != null) {
+ connection.close();
+ }
+ }
+ }
+
+ void setDbType(IDatabaseConnection connection) throws Exception {
+ DatabaseConfig dbConfig = connection.getConfig();
+ String name = connection.getConnection().getMetaData().getDatabaseProductName().toLowerCase();
+ int major = connection.getConnection().getMetaData().getDatabaseMajorVersion();
+ IDataTypeFactory type = null;
+
+ if (name.contains("postgres")) {
+ type = new PostgresqlDataTypeFactory();
+ } else if (name.contains("oracle")) {
+ if (major >= 10) {
+ type = new Oracle10DataTypeFactory();
+ } else {
+ type = new OracleDataTypeFactory();
+ }
+ }
+
+ if (type != null) {
+ dbConfig.setProperty("http://www.dbunit.org/properties/datatypeFactory", type);
+ }
+ }
+
+ IDataSet getDataSet() throws Exception {
+ FlatXmlProducer xmlProducer = new FlatXmlProducer(new InputSource(getClass().getResourceAsStream(
+ getDataSetFile())));
+ xmlProducer.setColumnSensing(true);
+ return new FlatXmlDataSet(xmlProducer);
+ }
+
+ String getDataSetFile() {
+ return getClass().getSimpleName() + ".xml";
+ }
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/DriftManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/DriftManagerBeanTest.java
new file mode 100644
index 0000000..6b4b356
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/DriftManagerBeanTest.java
@@ -0,0 +1,426 @@
+/*
+ * 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.enterprise.server.drift;
+
+import static org.apache.commons.io.FileUtils.deleteDirectory;
+import static org.apache.commons.io.FileUtils.toFile;
+import static org.rhq.common.drift.FileEntry.addedFileEntry;
+import static org.rhq.common.drift.FileEntry.changedFileEntry;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.DRIFT;
+
+import java.io.File;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.common.drift.ChangeSetWriter;
+import org.rhq.common.drift.ChangeSetWriterImpl;
+import org.rhq.common.drift.Headers;
+import org.rhq.core.clientapi.server.drift.DriftServerService;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.common.EntityContext;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.criteria.JPADriftChangeSetCriteria;
+import org.rhq.core.domain.criteria.ResourceCriteria;
+import org.rhq.core.domain.drift.Drift;
+import org.rhq.core.domain.drift.DriftCategory;
+import org.rhq.core.domain.drift.DriftChangeSet;
+import org.rhq.core.domain.drift.DriftConfigurationDefinition.BaseDirValueContext;
+import org.rhq.core.domain.drift.DriftDefinition;
+import org.rhq.core.domain.drift.DriftDefinition.BaseDirectory;
+import org.rhq.core.domain.drift.DriftDefinitionTemplate;
+import org.rhq.core.domain.drift.DriftFile;
+import org.rhq.core.domain.drift.DriftFileStatus;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.InventoryStatus;
+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.domain.util.PageOrdering;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.core.util.ZipUtil;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Test for {@link DriftManagerBean} SLSB.
+ *
+ * !!! Actually, this is really testing only the JPA impl, it does not actually go through the
+ * !!! configured drift server plugin. To enhance this to do that then you may need to model this
+ * !!! mode like BundleManagerBeanTest
+ */
+public class DriftManagerBeanTest extends AbstractEJB3Test {
+
+ private JPADriftServerLocal jpaDriftServer;
+ private DriftManagerLocal driftManager;
+ private Subject overlord;
+ private Resource newResource;
+ @SuppressWarnings("unused")
+ private DriftServerService driftServerService;
+
+ MessageDigestGenerator digestGenerator;
+
+ /**
+ * Prepares things for the entire test class.
+ */
+ @BeforeClass
+ public void beforeClass() throws Exception {
+ digestGenerator = new MessageDigestGenerator(MessageDigestGenerator.SHA_256);
+ jpaDriftServer = LookupUtil.getJPADriftServer();
+ driftManager = LookupUtil.getDriftManager();
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ driftServerService = new DriftServerServiceImpl();
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void afterClass() {
+ driftServerService = null;
+ }
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ TestServerCommunicationsService agentServiceContainer = prepareForTestAgents();
+ agentServiceContainer.driftService = new TestDefService();
+
+ prepareScheduler();
+
+ deleteDriftFiles();
+
+ newResource = createNewResource();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ try {
+ deleteNewResource(newResource);
+ } finally {
+ unprepareForTestAgents();
+ unprepareScheduler();
+ }
+ }
+
+ @Test
+ public void testStoreChangeSet() throws Exception {
+ File rootDir = toFile(getClass().getResource("."));
+ File changeSetsDir = new File(rootDir, "changesets");
+ deleteDirectory(changeSetsDir);
+ changeSetsDir.mkdirs();
+
+ Headers headers = new Headers();
+ headers.setResourceId(newResource.getId());
+ headers.setDriftDefinitionId(1);
+ headers.setDriftDefinitionName("test-1");
+ headers.setBasedir(rootDir.getAbsolutePath());
+ headers.setType(COVERAGE);
+ headers.setVersion(0);
+
+ String file1Hash = sha256("test-1-file-1");
+
+ File changeSet1 = new File(changeSetsDir, "changeset-1.txt");
+ ChangeSetWriter writer = new ChangeSetWriterImpl(changeSet1, headers);
+ writer.write(addedFileEntry("test/file-1", file1Hash, 56789L, 1024L));
+ writer.close();
+
+ File changeSet1Zip = new File(changeSetsDir, "changeset-1.zip");
+ ZipUtil.zipFileOrDirectory(changeSet1, changeSet1Zip);
+
+ assertTrue("Expected to find change set zip file: " + changeSet1Zip.getPath(), changeSet1Zip.exists());
+
+ jpaDriftServer.storeChangeSet(overlord, newResource.getId(), changeSet1Zip);
+
+ JPADriftChangeSetCriteria c = new JPADriftChangeSetCriteria();
+ c.addFilterResourceId(newResource.getId());
+ c.fetchDrifts(true);
+ List<? extends DriftChangeSet<?>> changeSets = jpaDriftServer.findDriftChangeSetsByCriteria(overlord, c);
+ assertEquals(1, changeSets.size());
+ DriftChangeSet<?> changeSet = changeSets.get(0);
+ assertEquals(0, changeSet.getVersion());
+ assertEquals("Expected to find one entry in change set", 1, changeSet.getDrifts().size());
+
+ DriftFile driftFile = jpaDriftServer.getDriftFile(overlord, file1Hash);
+ assertNotNull(driftFile);
+ assertEquals(DriftFileStatus.REQUESTED, driftFile.getStatus());
+
+ // the second change set should report drift
+ String modifiedFile1Hash = sha256("test-2-file-1-modified");
+ headers.setType(DRIFT);
+ headers.setVersion(1);
+ File changeSet2 = new File(changeSetsDir, "changeset-2.txt");
+
+ writer = new ChangeSetWriterImpl(changeSet2, headers);
+ writer.write(changedFileEntry("test/file-1", file1Hash, modifiedFile1Hash, 56789L, 1024L));
+ writer.close();
+
+ File changeSet2Zip = new File(changeSetsDir, "changeset-2.zip");
+ ZipUtil.zipFileOrDirectory(changeSet2, changeSet2Zip);
+
+ assertTrue("Expected to find change set file: " + changeSet2Zip.getPath(), changeSet2Zip.exists());
+
+ jpaDriftServer.storeChangeSet(overlord, newResource.getId(), changeSet2Zip);
+ c.addSortVersion(PageOrdering.ASC);
+ c.addFilterCategory(DRIFT);
+ changeSets = jpaDriftServer.findDriftChangeSetsByCriteria(overlord, c);
+ assertEquals(1, changeSets.size());
+ changeSet = changeSets.get(0);
+ assertEquals("The change set version is wrong", 1, changeSet.getVersion());
+ assertEquals("Expected to find one entry in change set", 1, changeSet.getDrifts().size());
+ changeSet = changeSets.get(0);
+ assertEquals(1, changeSet.getVersion());
+ assertEquals(1, changeSet.getDrifts().size());
+ Drift<?, ?> drift = changeSet.getDrifts().iterator().next();
+ assertEquals("test/file-1", drift.getPath());
+ assertEquals(file1Hash, drift.getOldDriftFile().getHashId());
+ assertEquals(modifiedFile1Hash, drift.getNewDriftFile().getHashId());
+ assertEquals(DriftCategory.FILE_CHANGED, drift.getCategory());
+
+ driftFile = jpaDriftServer.getDriftFile(overlord, modifiedFile1Hash);
+ assertNotNull(driftFile);
+ assertEquals(DriftFileStatus.REQUESTED, driftFile.getStatus());
+ }
+
+ @Test
+ public void testDriftDef() throws Exception {
+ Configuration config = new Configuration();
+ DriftDefinition driftDefPojo = new DriftDefinition(config);
+ driftDefPojo.setName("testDriftDef");
+ driftDefPojo.setInterval(60L);
+ driftDefPojo.setBasedir(new BaseDirectory(BaseDirValueContext.fileSystem, "foo/bar"));
+
+ driftManager.updateDriftDefinition(overlord, EntityContext.forResource(newResource.getId()), driftDefPojo);
+
+ ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+ ResourceCriteria c = new ResourceCriteria();
+ c.addFilterId(newResource.getId());
+ c.fetchDriftDefinitions(true);
+ List<Resource> resources = resourceManager.findResourcesByCriteria(overlord, c);
+ assertEquals(1, resources.size());
+ Set<DriftDefinition> driftDefs = resources.get(0).getDriftDefinitions();
+ assertNotNull(driftDefs);
+ assertEquals(3, driftDefs.size());
+ DriftDefinition driftDef = null;
+ for (Iterator<DriftDefinition> i = driftDefs.iterator(); i.hasNext();) {
+ driftDef = i.next();
+ if (driftDefPojo.getName().equals(driftDef.getName()))
+ break;
+ }
+ assertTrue(driftDef.getConfiguration().getId() > 0); // persisted
+ assertEquals(driftDefPojo.getName(), driftDef.getName());
+ assertEquals(driftDefPojo.getBasedir(), driftDef.getBasedir());
+ assertEquals(driftDefPojo.getInterval(), driftDef.getInterval());
+
+ driftDefPojo.setInterval(120L);
+ driftManager.updateDriftDefinition(overlord, EntityContext.forResource(newResource.getId()), driftDefPojo);
+
+ resources = resourceManager.findResourcesByCriteria(overlord, c);
+ assertEquals(1, resources.size());
+ driftDefs = resources.get(0).getDriftDefinitions();
+ assertNotNull(driftDefs);
+ assertEquals(3, driftDefs.size());
+ driftDef = null;
+ for (Iterator<DriftDefinition> i = driftDefs.iterator(); i.hasNext();) {
+ driftDef = i.next();
+ if (driftDefPojo.getName().equals(driftDef.getName()))
+ break;
+ }
+ assertEquals(driftDefPojo.getName(), driftDef.getName());
+ assertTrue(driftDef.getConfiguration().getId() > 0); // persisted
+ assertEquals(driftDefPojo.getBasedir(), driftDef.getBasedir());
+ assertEquals(120L, driftDef.getInterval());
+
+ driftDefPojo = new DriftDefinition(driftDef.getConfiguration().deepCopyWithoutProxies());
+ driftDefPojo.setName("testDriftDef-2");
+ driftDefPojo.setInterval(30L);
+ driftDefPojo.setBasedir(new BaseDirectory(BaseDirValueContext.fileSystem, "foo/baz"));
+
+ driftManager.updateDriftDefinition(overlord, EntityContext.forResource(newResource.getId()), driftDefPojo);
+
+ resources = resourceManager.findResourcesByCriteria(overlord, c);
+ assertEquals(1, resources.size());
+ driftDefs = resources.get(0).getDriftDefinitions();
+ assertNotNull(driftDefs);
+ assertEquals(4, driftDefs.size());
+ for (Iterator<DriftDefinition> i = driftDefs.iterator(); i.hasNext();) {
+ driftDef = i.next();
+ if ("testDriftDef".equals(driftDef.getName())) {
+ assertTrue(driftDef.getConfiguration().getId() > 0); // persisted
+ assertEquals("foo/bar", driftDef.getBasedir().getValueName());
+ assertEquals(BaseDirValueContext.fileSystem, driftDef.getBasedir().getValueContext());
+ assertEquals(120L, driftDef.getInterval());
+ } else if ("testDriftDef-2".equals(driftDef.getName())) {
+ assertTrue(driftDef.getConfiguration().getId() > 0); // persisted
+ assertEquals(driftDefPojo.getBasedir(), driftDef.getBasedir());
+ assertEquals(driftDefPojo.getInterval(), driftDef.getInterval());
+ } else if (!"test-1".equals(driftDef.getName()) && !"test-2".equals(driftDef.getName())) {
+ fail("Unexpected drift def name: " + driftDef.getName());
+ }
+ }
+
+ driftManager.deleteDriftDefinition(overlord, EntityContext.forResource(newResource.getId()), "testDriftDef");
+ resources = resourceManager.findResourcesByCriteria(overlord, c);
+ assertEquals(1, resources.size());
+ driftDefs = resources.get(0).getDriftDefinitions();
+ assertNotNull(driftDefs);
+ assertEquals(3, driftDefs.size());
+ for (Iterator<DriftDefinition> i = driftDefs.iterator(); i.hasNext();) {
+ driftDef = i.next();
+ if (driftDefPojo.getName().equals(driftDef.getName()))
+ break;
+ }
+ assertTrue(driftDef.getConfiguration().getId() > 0); // persisted
+ assertEquals(driftDefPojo.getName(), driftDef.getName());
+ assertEquals(driftDefPojo.getBasedir(), driftDef.getBasedir());
+ assertEquals(driftDefPojo.getInterval(), driftDef.getInterval());
+ }
+
+ private void deleteDriftFiles() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ try {
+ // wipe out any test DriftFiles (the test files have sha256 0,1,...)
+ for (int i = 0, numDeleted = 1; (numDeleted > 0); ++i) {
+ numDeleted = getEntityManager().createQuery("delete from JPADriftFile where hash_id = '" + i + "'")
+ .executeUpdate();
+ }
+ } catch (Exception e) {
+ System.out.println("CANNOT PREPARE TEST: " + e);
+ getTransactionManager().rollback();
+ throw e;
+ }
+
+ em.flush();
+ getTransactionManager().commit();
+ } finally {
+ em.close();
+ }
+ }
+
+ private Resource createNewResource() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ Resource resource;
+
+ try {
+ try {
+ ResourceType resourceType = new ResourceType("plat" + System.currentTimeMillis(), "test",
+ ResourceCategory.PLATFORM, null);
+ DriftDefinitionTemplate template = new DriftDefinitionTemplate();
+ template.setName("test-template");
+ DriftDefinition templateDef = new DriftDefinition(new Configuration());
+ templateDef.setName("test-template-def");
+ template.setTemplateDefinition(templateDef);
+ template.setUserDefined(true);
+ resourceType.addDriftDefinitionTemplate(template);
+ em.persist(resourceType);
+
+ Agent agent = new Agent("testagent", "testaddress", 1, "", "testtoken");
+ em.persist(agent);
+ em.flush();
+
+ DriftDefinition test1Def = new DriftDefinition(new Configuration());
+ test1Def.setName("test-1");
+
+ DriftDefinition test2Def = new DriftDefinition(new Configuration());
+ test2Def.setName("test-2");
+
+ resource = new Resource("reskey" + System.currentTimeMillis(), "resname", resourceType);
+ resource.setUuid("" + new Random().nextInt());
+ resource.setAgent(agent);
+ resource.setInventoryStatus(InventoryStatus.COMMITTED);
+ resource.addDriftDefinition(test1Def);
+ resource.addDriftDefinition(test2Def);
+ em.persist(resource);
+
+ } catch (Exception e) {
+ System.out.println("CANNOT PREPARE TEST: " + e);
+ getTransactionManager().rollback();
+ throw e;
+ }
+
+ em.flush();
+ getTransactionManager().commit();
+ } finally {
+ em.close();
+ }
+
+ return resource;
+ }
+
+ private void deleteNewResource(Resource resource) throws Exception {
+ if (null != resource) {
+ EntityManager em = null;
+
+ try {
+ ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+
+ // invoke bulk delete on the resource to remove any dependencies not defined in the hibernate entity model
+ // perform in-band and out-of-band work in quick succession
+ List<Integer> deletedIds = resourceManager.uninventoryResource(overlord, resource.getId());
+ for (Integer deletedResourceId : deletedIds) {
+ resourceManager.uninventoryResourceAsyncWork(overlord, deletedResourceId);
+ }
+
+ // now dispose of other hibernate entities
+ getTransactionManager().begin();
+ em = getEntityManager();
+
+ ResourceType type = em.find(ResourceType.class, resource.getResourceType().getId());
+ Agent agent = em.find(Agent.class, resource.getAgent().getId());
+ if (null != agent) {
+ em.remove(agent);
+ }
+ if (null != type) {
+ em.remove(type);
+ }
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ System.out.println("CANNOT CLEAN UP TEST (" + this.getClass().getSimpleName() + ") Cause: " + e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+ } finally {
+ if (null != em) {
+ em.close();
+ }
+ }
+ }
+ }
+
+ String sha256(String s) throws Exception {
+ return digestGenerator.calcDigestString(s);
+ }
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/TestDefService.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/TestDefService.java
new file mode 100644
index 0000000..49e783c
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/TestDefService.java
@@ -0,0 +1,72 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 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.drift;
+
+import java.util.List;
+
+import org.rhq.common.drift.Headers;
+import org.rhq.core.clientapi.agent.drift.DriftAgentService;
+import org.rhq.core.domain.drift.DriftDefinition;
+import org.rhq.core.domain.drift.DriftFile;
+import org.rhq.core.domain.drift.DriftSnapshot;
+
+class TestDefService implements DriftAgentService {
+
+ public TestDefService() {
+ }
+
+ @Override
+ public boolean requestDriftFiles(int resourceId, Headers headers, List<? extends DriftFile> driftFiles) {
+ return true;
+ }
+
+ @Override
+ public void scheduleDriftDetection(int resourceId, DriftDefinition DriftDefinition) {
+
+ }
+
+ @Override
+ public void detectDrift(int resourceId, DriftDefinition DriftDefinition) {
+ }
+
+ @Override
+ public void unscheduleDriftDetection(int resourceId, DriftDefinition DriftDefinition) {
+ }
+
+ @Override
+ public void updateDriftDetection(int resourceId, DriftDefinition DriftDefinition) {
+ }
+
+ @Override
+ public void updateDriftDetection(int resourceId, DriftDefinition driftDef, DriftSnapshot driftSnapshot) {
+ }
+
+ @Override
+ public void ackChangeSet(int resourceId, String driftDefName) {
+ }
+
+ @Override
+ public void ackChangeSetContent(int resourceId, String driftDefName, String token) {
+ }
+
+ @Override
+ public void pinSnapshot(int resourceId, String configName, DriftSnapshot snapshot) {
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/event/test/EventManagerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/event/test/EventManagerTest.java
new file mode 100644
index 0000000..ad390d4
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/event/test/EventManagerTest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.enterprise.server.event.test;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.common.EntityContext;
+import org.rhq.core.domain.event.Event;
+import org.rhq.core.domain.event.EventDefinition;
+import org.rhq.core.domain.event.EventSeverity;
+import org.rhq.core.domain.event.EventSource;
+import org.rhq.core.domain.event.composite.EventComposite;
+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.domain.util.PageControl;
+import org.rhq.enterprise.server.event.EventManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Tests around the event subsystem
+ * @author Heiko W. Rupp
+ */
+public class EventManagerTest extends AbstractEJB3Test {
+
+ EventManagerLocal eventManager;
+ EntityManager em;
+
+ @BeforeMethod
+ public void init() {
+ try {
+ eventManager = LookupUtil.getEventManager();
+ } catch (Throwable t) {
+ // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
+ // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testEventsSimple() throws Exception {
+
+ try {
+ getTransactionManager().begin();
+ em = getEntityManager();
+ Resource resource = setUpResource(em);
+
+ EventDefinition eDef = new EventDefinition(resource.getResourceType(), "My definition is this ..");
+ em.persist(eDef);
+
+ long now = System.currentTimeMillis();
+ EventSource evSrc = new EventSource("ESource", eDef, resource);
+ Event ev = new Event("EType", "ESource", now, EventSeverity.INFO, "This is a test", evSrc);
+ //Set<Event> eventSet = new HashSet<Event>();
+ //eventSet.add(ev);
+ //Map<EventSource, Set<Event>> events = new HashMap<EventSource, Set<Event>>();
+ //events.put(evSrc, eventSet);
+ em.persist(evSrc);
+ em.persist(ev);
+ em.flush();
+
+ /*
+ * do NOT use addEventData method until this test is refactored to support the fact that
+ * insertions made via direct SQL won't be visible to the entity manager in this xaction
+ */
+ //eventManager.addEventData(events);
+ int resourceId = resource.getId();
+ Query queryByTime = em.createNamedQuery(Event.FIND_EVENTS_FOR_RESOURCE_ID_AND_TIME);
+ long t1 = now - 1000L;
+ long t2 = now + 1000L;
+ queryByTime.setParameter("resourceId", resourceId);
+ queryByTime.setParameter("start", t1);
+ queryByTime.setParameter("end", t2);
+ List resultsByTime = queryByTime.getResultList();
+ assert resultsByTime.size() == 1 : "Expected 1 Event, got " + resultsByTime.size();
+
+ Query queryBySeverity = em.createNamedQuery(Event.FIND_EVENTS_FOR_RESOURCE_ID_AND_TIME_SEVERITY);
+ queryBySeverity.setParameter("severity", EventSeverity.INFO);
+ queryBySeverity.setParameter("resourceId", resourceId);
+ queryBySeverity.setParameter("start", t1);
+ queryBySeverity.setParameter("end", t2);
+ List resultsBySeverity = queryBySeverity.getResultList();
+ assert resultsBySeverity.size() == 1 : "Expected 1 Event, got " + resultsBySeverity.size();
+
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ @Test
+ public void testEventManager() throws Exception {
+
+ try {
+ getTransactionManager().begin();
+ em = getEntityManager();
+ Resource resource = setUpResource(em);
+
+ EventDefinition eDef = new EventDefinition(resource.getResourceType(), "My definition is this ..");
+ em.persist(eDef);
+ em.flush();
+
+ long now = System.currentTimeMillis();
+ EventSource evSrc = new EventSource("ESource", eDef, resource);
+ Event ev = new Event("EType", "ESource", now, EventSeverity.INFO, "This is a 2nd test", evSrc);
+ Set<Event> eventSet = new HashSet<Event>();
+ eventSet.add(ev);
+ Map<EventSource, Set<Event>> events = new HashMap<EventSource, Set<Event>>();
+ events.put(evSrc, eventSet);
+ //em.persist(evSrc);
+ //em.persist(ev);
+ //em.flush();
+
+ /*
+ * do NOT use addEventData method until this test is refactored to support the fact that
+ * insertions made via direct SQL won't be visible to the entity manager in this xaction
+ */
+ eventManager.addEventData(events);
+ int resourceId = resource.getId();
+ long t1 = now - 1000L;
+ long t2 = now + 1000L;
+
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ int[] buckets = eventManager.getEventCounts(overlord, resourceId, t1, t2, 3);
+ assert buckets != null : "Buckets should not be null, but were null";
+ assert buckets.length == 3 : "Expected 3 buckets, but got " + buckets.length;
+
+ boolean bucketCounts = buckets[0] == 0 && buckets[1] == 1 && buckets[2] == 0;
+ assert bucketCounts : "Expected bucket counts were [0 1 0] Received [" + buckets[0] + " " + buckets[1]
+ + " " + buckets[2] + "]";
+
+ PageControl pc = PageControl.getUnlimitedInstance();
+ EntityContext context = EntityContext.forResource(resourceId);
+
+ List<EventComposite> res = eventManager
+ .findEventComposites(overlord, context, t1, t2, null, null, null, pc);
+ assert res.size() == 1 : "Expected 1 Event, got " + res.size();
+ res = eventManager.findEventComposites(overlord, context, t1, t2,
+ new EventSeverity[] { EventSeverity.INFO }, null, null, pc);
+ assert res.size() == 1 : "Expected 1 Event, got " + res.size();
+ res = eventManager.findEventComposites(overlord, context, t1, t2,
+ new EventSeverity[] { EventSeverity.WARN }, null, null, pc);
+ assert res.size() == 0 : "Expected 0 Events, got " + res.size();
+
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ private Resource setUpResource(EntityManager em) {
+ ResourceType resourceType = new ResourceType("fake platform", "fake plugin", ResourceCategory.PLATFORM, null);
+ em.persist(resourceType);
+ Resource platform = new Resource("org.jboss.on.TestPlatform", "Fake Platform", resourceType);
+ platform.setUuid("" + new Random().nextInt());
+ em.persist(platform);
+ em.flush();
+
+ return platform;
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/inventory/InventoryManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/inventory/InventoryManagerBeanTest.java
new file mode 100644
index 0000000..dcf83fe
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/inventory/InventoryManagerBeanTest.java
@@ -0,0 +1,187 @@
+package org.rhq.enterprise.server.inventory;
+
+import static java.util.Arrays.asList;
+
+import java.sql.Connection;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dbunit.database.DatabaseConfig;
+import org.dbunit.database.DatabaseConnection;
+import org.dbunit.database.IDatabaseConnection;
+import org.dbunit.dataset.IDataSet;
+import org.dbunit.dataset.datatype.IDataTypeFactory;
+import org.dbunit.dataset.xml.FlatXmlDataSet;
+import org.dbunit.dataset.xml.FlatXmlProducer;
+import org.dbunit.ext.oracle.Oracle10DataTypeFactory;
+import org.dbunit.ext.oracle.OracleDataTypeFactory;
+import org.dbunit.ext.postgresql.PostgresqlDataTypeFactory;
+import org.dbunit.operation.DatabaseOperation;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.xml.sax.InputSource;
+
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+public class InventoryManagerBeanTest extends AbstractEJB3Test {
+
+ private static List<Integer> deletedTypeIds = asList(1, 2, 3, 4, 5);
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ initDB();
+
+ getTransactionManager().begin();
+
+ InventoryManagerLocal inventoryMgr = LookupUtil.getInventoryManager();
+ inventoryMgr.markTypesDeleted(deletedTypeIds);
+ getTransactionManager().commit();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ cleanDB();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void markTypesAndTheirChildTypesForDeletion() {
+ List<ResourceType> resourceTypes = getEntityManager()
+ .createQuery("from ResourceType t where t.id in (:resourceTypeIds)")
+ .setParameter("resourceTypeIds", deletedTypeIds).getResultList();
+
+ assertEquals("Failed to retrieve all resource types", 5, resourceTypes.size());
+
+ List<Integer> typesNotDeleted = new ArrayList<Integer>();
+ for (ResourceType type : resourceTypes) {
+ if (!type.isDeleted()) {
+ typesNotDeleted.add(type.getId());
+ }
+ }
+
+ assertEquals("Failed to mark for deletion resource types with the following ids: " + typesNotDeleted + ".", 0,
+ typesNotDeleted.size());
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void uninventoryResourcesOfTypesMarkedForDeletion() {
+ List<Resource> resources = getEntityManager().createQuery("from Resource r where r.id in (:resourceIds)")
+ .setParameter("resourceIds", asList(1, 2)).getResultList();
+
+ assertEquals("Failed to retrieve all resources", 2, resources.size());
+
+ List<Integer> resourcesNotDeleted = new ArrayList<Integer>();
+ for (Resource resource : resources) {
+ if (resource.getInventoryStatus() != InventoryStatus.UNINVENTORIED) {
+ resourcesNotDeleted.add(resource.getId());
+ }
+ }
+
+ assertEquals(
+ "Resources of types marked for deletion should be uninventoried. Resources with the following ids "
+ + "should have been uninventoried: " + resourcesNotDeleted + ".", 0, resourcesNotDeleted.size());
+ }
+
+ @Test
+ public void getDeletedTypes() {
+ InventoryManagerLocal inventoryMgr = LookupUtil.getInventoryManager();
+ List<ResourceType> deletedTypes = inventoryMgr.getDeletedTypes();
+
+ // protect against other db detritus, just look for the ones we expect
+ int resultSize = deletedTypes.size();
+ assertTrue("Expected at least five deleted types", resultSize >= 5);
+ List<Integer> resultIds = new ArrayList(resultSize);
+ for (ResourceType rt : deletedTypes) {
+ resultIds.add(rt.getId());
+ }
+ for (Integer id : deletedTypeIds) {
+ assert (resultIds.contains(id));
+ }
+ }
+
+ @Test
+ public void deletedTypeIsReadyForRemovalWhenThereResourcesOfThatType() {
+ InventoryManagerLocal inventoryMgr = LookupUtil.getInventoryManager();
+ ResourceType deletedType = getEntityManager().find(ResourceType.class, 4);
+
+ assertTrue(deletedType + " should be ready for removal", inventoryMgr.isReadyForPermanentRemoval(deletedType));
+ }
+
+ @Test
+ public void typeThatIsNotDeletedIsNotReadyForRemoval() {
+ InventoryManagerLocal inventoryMgr = LookupUtil.getInventoryManager();
+ ResourceType resourceType = getEntityManager().find(ResourceType.class, 6);
+
+ assertFalse(resourceType + " is not ready for removal because it is not deleted.",
+ inventoryMgr.isReadyForPermanentRemoval(resourceType));
+ }
+
+ public void initDB() throws Exception {
+ Connection connection = null;
+
+ try {
+ connection = getConnection();
+ IDatabaseConnection conn = new DatabaseConnection(connection);
+ setDbType(conn);
+ DatabaseOperation.REFRESH.execute(conn, getDataSet());
+ } finally {
+ if (connection != null) {
+ connection.close();
+ }
+ }
+ }
+
+ public void cleanDB() throws Exception {
+ Connection connection = null;
+
+ try {
+ connection = getConnection();
+ IDatabaseConnection conn = new DatabaseConnection(connection);
+ setDbType(conn);
+ DatabaseOperation.DELETE.execute(conn, getDataSet());
+ } finally {
+ if (connection != null) {
+ connection.close();
+ }
+ }
+ }
+
+ void setDbType(IDatabaseConnection connection) throws Exception {
+ DatabaseConfig dbConfig = connection.getConfig();
+ String name = connection.getConnection().getMetaData().getDatabaseProductName().toLowerCase();
+ int major = connection.getConnection().getMetaData().getDatabaseMajorVersion();
+ IDataTypeFactory type = null;
+
+ if (name.contains("postgres")) {
+ type = new PostgresqlDataTypeFactory();
+ } else if (name.contains("oracle")) {
+ if (major >= 10) {
+ type = new Oracle10DataTypeFactory();
+ } else {
+ type = new OracleDataTypeFactory();
+ }
+ }
+
+ if (type != null) {
+ dbConfig.setProperty("http://www.dbunit.org/properties/datatypeFactory", type);
+ }
+ }
+
+ IDataSet getDataSet() throws Exception {
+ FlatXmlProducer xmlProducer = new FlatXmlProducer(new InputSource(getClass().getResourceAsStream(
+ getDataSetFile())));
+ xmlProducer.setColumnSensing(true);
+ return new FlatXmlDataSet(xmlProducer);
+ }
+
+ String getDataSetFile() {
+ return getClass().getSimpleName() + ".xml";
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/inventory/UninventoryTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/inventory/UninventoryTest.java
new file mode 100644
index 0000000..c0e041d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/inventory/UninventoryTest.java
@@ -0,0 +1,216 @@
+/*
+ * 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.enterprise.server.inventory;
+
+import java.util.List;
+import java.util.Random;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.drift.DriftConfigurationDefinition.BaseDirValueContext;
+import org.rhq.core.domain.drift.DriftDefinition;
+import org.rhq.core.domain.drift.DriftDefinition.BaseDirectory;
+import org.rhq.core.domain.drift.DriftDefinitionTemplate;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Test to see that uninventorying works.
+ */
+@Test
+public class UninventoryTest extends AbstractEJB3Test {
+ private Resource newResource;
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ if (newResource != null) {
+ deleteNewResource(newResource);
+ newResource = null;
+ }
+ }
+
+ public void testDriftDefRemoval() throws Exception {
+ ResourceTypeCreator rtCreator = new ResourceTypeCreator() {
+ public void modifyResourceTypeToPersist(ResourceType resourceType, EntityManager em) {
+ DriftDefinitionTemplate template = new DriftDefinitionTemplate();
+ template.setName("drift1");
+ template.setDescription("drift def template");
+ Configuration config = new Configuration();
+ DriftDefinition driftDef = new DriftDefinition(config);
+ driftDef.setBasedir(new BaseDirectory(BaseDirValueContext.fileSystem, "/"));
+ driftDef.setName("drift1");
+ template.setTemplateDefinition(driftDef);
+ resourceType.addDriftDefinitionTemplate(template);
+ }
+ };
+ ResourceCreator rCreator = new ResourceCreator() {
+ public void modifyResourceToPersist(Resource resource, EntityManager em) {
+ Configuration config = new Configuration();
+ DriftDefinition driftDef = new DriftDefinition(config);
+ driftDef.setBasedir(new BaseDirectory(BaseDirValueContext.fileSystem, "/boo"));
+ driftDef.setName("drift-def-name");
+ resource.addDriftDefinition(driftDef);
+ }
+ };
+
+ Resource resource = createNewResource(rtCreator, rCreator);
+
+ int templateId = resource.getResourceType().getDriftDefinitionTemplates().iterator().next().getId();
+ int driftDefId = resource.getDriftDefinitions().iterator().next().getId();
+
+ // sanity check, make sure things are in the DB now
+ Query qTemplate;
+ Query qDef;
+ String qTemplateString = "select t from DriftDefinitionTemplate t where t.id = :id";
+ String qDefString = "select dc from DriftDefinition dc where dc.id = :id";
+
+ getTransactionManager().begin();
+ try {
+ qTemplate = getEntityManager().createQuery(qTemplateString).setParameter("id", templateId);
+ qDef = getEntityManager().createQuery(qDefString).setParameter("id", driftDefId);
+ assertEquals("drift template didn't get added", 1, qTemplate.getResultList().size());
+ assertEquals("drift template def didn't get added", 1, qDef.getResultList().size());
+ } finally {
+ getTransactionManager().commit();
+ }
+
+ // uninventory the resource
+ deleteNewResource(resource);
+
+ // make sure things purged
+ getTransactionManager().begin();
+ try {
+ qTemplate = getEntityManager().createQuery(qTemplateString).setParameter("id", templateId);
+ qDef = getEntityManager().createQuery(qDefString).setParameter("id", driftDefId);
+ assertEquals("drift template didn't get purged", 0, qTemplate.getResultList().size());
+ assertEquals("drift template def didn't get purged", 0, qDef.getResultList().size());
+ } finally {
+ getTransactionManager().commit();
+ }
+ }
+
+ private Resource createNewResource(ResourceTypeCreator rtCreator, ResourceCreator rCreator) throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ Resource resource;
+
+ try {
+ try {
+ ResourceType resourceType = new ResourceType("plat" + System.currentTimeMillis(), "test",
+ ResourceCategory.PLATFORM, null);
+
+ if (rtCreator != null) {
+ rtCreator.modifyResourceTypeToPersist(resourceType, em);
+ }
+
+ em.persist(resourceType);
+
+ Agent agent = new Agent("testagent", "testaddress", 1, "", "testtoken");
+ em.persist(agent);
+ em.flush();
+
+ resource = new Resource("reskey" + System.currentTimeMillis(), "resname", resourceType);
+ resource.setUuid("" + new Random().nextInt());
+ resource.setAgent(agent);
+ resource.setInventoryStatus(InventoryStatus.COMMITTED);
+ if (rCreator != null) {
+ rCreator.modifyResourceToPersist(resource, em);
+ }
+ em.persist(resource);
+
+ } catch (Exception e) {
+ System.out.println("CANNOT PREPARE TEST: " + e);
+ getTransactionManager().rollback();
+ throw e;
+ }
+
+ em.flush();
+ getTransactionManager().commit();
+ newResource = resource;
+ } finally {
+ em.close();
+ }
+
+ return resource;
+ }
+
+ private void deleteNewResource(Resource resource) throws Exception {
+ if (null != resource) {
+ EntityManager em = null;
+
+ try {
+ ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+
+ // invoke bulk delete on the resource to remove any dependencies not defined in the hibernate entity model
+ // perform in-band and out-of-band work in quick succession
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ List<Integer> deletedIds = resourceManager.uninventoryResource(overlord, resource.getId());
+ for (Integer deletedResourceId : deletedIds) {
+ resourceManager.uninventoryResourceAsyncWork(overlord, deletedResourceId);
+ }
+
+ // now dispose of other hibernate entities
+ getTransactionManager().begin();
+ em = getEntityManager();
+
+ ResourceType type = em.find(ResourceType.class, resource.getResourceType().getId());
+ Agent agent = em.find(Agent.class, resource.getAgent().getId());
+ if (null != agent) {
+ em.remove(agent);
+ }
+ if (null != type) {
+ em.remove(type);
+ }
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ System.out.println("CANNOT CLEAN UP TEST (" + this.getClass().getSimpleName() + ") Cause: " + e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+ } finally {
+ if (null != em) {
+ em.close();
+ }
+ }
+ }
+ }
+
+ private interface ResourceTypeCreator {
+ void modifyResourceTypeToPersist(ResourceType resourceType, EntityManager em);
+ }
+
+ private interface ResourceCreator {
+ void modifyResourceToPersist(Resource resource, EntityManager em);
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/legacy/rss/DownloadPatchTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/legacy/rss/DownloadPatchTest.java
new file mode 100644
index 0000000..5ba53a1
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/legacy/rss/DownloadPatchTest.java
@@ -0,0 +1,159 @@
+/*
+ * 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.enterprise.server.legacy.rss;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * [class description]
+ *
+ * @author <a href="mailto:jessica.sant@jboss.com">Jessica Sant</a>
+ * @deprecated
+ */
+@Deprecated
+public class DownloadPatchTest //extends TestCase
+{
+ private Log log = LogFactory.getLog(DownloadPatchTest.class.getName());
+ private static final String URL = "https://network.staging.jboss.com/jbossnetwork/secureDownload.html";
+ private HttpClient client;
+
+ //@Override
+ protected void setUp() throws Exception {
+ client = new HttpClient();
+ }
+
+ //@Override
+ protected void tearDown() throws Exception {
+ client = null;
+ }
+
+ private void assertEquals(Object o1, Object o2) {
+ }
+
+ public void testAccessDownloadsNoUser() throws Exception {
+ int statusCode = accessDownload("", "", "");
+ assertEquals(HttpStatus.SC_FORBIDDEN, statusCode);
+ }
+
+ public void testAccessDownloadsNoPassword() throws Exception {
+ int statusCode = accessDownload("fmerenda(a)jboss.org", "", "");
+ assertEquals(HttpStatus.SC_FORBIDDEN, statusCode);
+ }
+
+ public void testAccessDownloadsInvalidPassword() throws Exception {
+ int statusCode = accessDownload("fmerenda(a)jboss.org", "xxxxx", "");
+ assertEquals(HttpStatus.SC_FORBIDDEN, statusCode);
+ }
+
+ public void testAccessDownloadsNoSoftware() throws Exception {
+ int statusCode = accessDownload("fmerenda(a)jboss.org", "password", "");
+ assertEquals(HttpStatus.SC_NOT_FOUND, statusCode);
+ }
+
+ public void testAccessDownloadsInvalidSoftware() throws Exception {
+ int statusCode = accessDownload("fmerenda(a)jboss.org", "password", "xxxx");
+ assertEquals(HttpStatus.SC_NOT_FOUND, statusCode);
+ }
+
+ public void testAccessDownloadsValidSoftware() throws Exception {
+ int fileSize = accessDownloadGetFileSize("fmerenda(a)jboss.org", "password", "a0450000005izHvAAI");
+ assertEquals(330322, fileSize);
+ }
+
+ private int accessDownload(String username, String password, String softwareId) throws Exception {
+ GetMethod method = new GetMethod(URL);
+ method.addRequestHeader("username", username);
+ method.addRequestHeader("password", password);
+ method.setFollowRedirects(true);
+
+ NameValuePair softwarePair = new NameValuePair("softwareId", softwareId);
+ method.setQueryString(new NameValuePair[] { softwarePair });
+
+ try {
+ int statusCode = client.executeMethod(method);
+ log.debug("Method status: " + method.getStatusLine());
+ if (HttpStatus.SC_OK == statusCode) {
+ String content = readContent(method);
+ log.debug("file length: " + content.length());
+ }
+
+ return statusCode;
+ } catch (Exception e) {
+ log.error(e.toString());
+ throw e;
+ } finally {
+ method.releaseConnection();
+ }
+ }
+
+ private int accessDownloadGetFileSize(String username, String password, String softwareId) throws Exception {
+ GetMethod method = new GetMethod(URL);
+ method.addRequestHeader("username", username);
+ method.addRequestHeader("password", password);
+ method.setFollowRedirects(true);
+
+ NameValuePair softwarePair = new NameValuePair("softwareId", softwareId);
+ method.setQueryString(new NameValuePair[] { softwarePair });
+
+ try {
+ int contentLength = 0;
+ int statusCode = client.executeMethod(method);
+ log.debug("Method status: " + method.getStatusLine());
+ if (HttpStatus.SC_OK == statusCode) {
+ String content = readContent(method);
+ contentLength = content.length();
+ }
+
+ return contentLength;
+ } catch (Exception e) {
+ log.error(e.toString());
+ throw e;
+ } finally {
+ method.releaseConnection();
+ }
+ }
+
+ private String readContent(GetMethod get) throws IOException {
+ StringBuffer result = new StringBuffer();
+ try {
+ Reader input = new InputStreamReader(get.getResponseBodyAsStream(), get.getResponseCharSet());
+ BufferedReader bufferedReader = (input instanceof BufferedReader) ? (BufferedReader) input
+ : new BufferedReader(input);
+ char[] buffer = new char[4 * 1024];
+ int charsRead;
+ while ((charsRead = bufferedReader.read(buffer)) != -1) {
+ result.append(buffer, 0, charsRead);
+ }
+ } catch (UnsupportedEncodingException e) {
+ result.append(get.getResponseBodyAsString());
+ }
+
+ return result.toString();
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/legacy/rss/RssFeedJobTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/legacy/rss/RssFeedJobTest.java
new file mode 100644
index 0000000..9035555
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/legacy/rss/RssFeedJobTest.java
@@ -0,0 +1,218 @@
+/*
+ * 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.enterprise.server.legacy.rss;
+
+/**
+ * [class description]
+ *
+ * @author <a href="mailto:jessica.sant@jboss.com">Jessica Sant</a>
+ * @deprecated
+ */
+@Deprecated
+public class RssFeedJobTest //extends TestCase
+{
+ /*
+ * //TODO: get this to test locally with username/password public static final String GOOD_PATCH_FEED_URL =
+ * "https://network.jboss.com/jbossnetwork/restricted/feed/software.html?" +
+ * "product=hibernate&downloadType=all&flavor=rss&version="; public static final String GOOD_RSS_URL = ""; public
+ * static final String BAD_URL = "https://network.jboss.com/jbossnetwork/badURL"; public static final String
+ * LOCAL_URL_NO_AUTH = "http://127.0.0.1:7080/test-feed/jbossNetworkFeed.xml"; public static final String
+ * GOOD_USERNAME = "jessica.sant(a)jboss.com"; public static final String GOOD_PASSWORD = "four11"; public static
+ * final String BAD_USERNAME_PASSWORD = "bad";
+ *
+ * private RssFeedJob feedJob;
+ *
+ * public void setUp() { this.feedJob = new RssFeedJob(); }
+ *
+ */
+
+ /** test extractTitle with no JIRA ID */
+ /*
+ * public void testExtractTitle_nullJira() { String itemTitle = "DISTRIBUTION: Hibernate 3.1 - binary (zip)";
+ * String jiraId = null; String softwareType = "DISTRIBUTION"; String rawTitle = null;
+ *
+ * String expected = "Hibernate 3.1 - binary (zip)"; String actual = feedJob.extractTitle( itemTitle,
+ * softwareType, jiraId, rawTitle );
+ *
+ * TestCase.assertEquals( actual, expected ); }
+ *
+ */
+ /** tests extractTitle with a blank Jira ID as opposed to a null jira ID */
+ /*
+ * public void testExtractTitle_blankJira() { String itemTitle = "DISTRIBUTION: Hibernate 3.1 - binary (zip)";
+ * String jiraId = ""; String softwareType = "DISTRIBUTION"; String rawTitle = null;
+ *
+ * String expected = "Hibernate 3.1 - binary (zip)"; String actual = feedJob.extractTitle( itemTitle,
+ * softwareType, jiraId, rawTitle );
+ *
+ * TestCase.assertEquals( actual, expected ); }
+ *
+ */
+ /** tests extractTitle with the rawTitle provided */
+ /*
+ * public void testExtractTitle_hasRawTitle() { String itemTitle = "DISTRIBUTION: Hibernate 3.1 - binary
+ * (zip)"; String jiraId = null; String softwareType = "DISTRIBUTION"; String rawTitle = "Hibernate 3.1
+ * - binary (zip)";
+ *
+ * String expected = "Hibernate 3.1 - binary (zip)"; String actual = feedJob.extractTitle( itemTitle,
+ * softwareType, jiraId, rawTitle );
+ *
+ * TestCase.assertEquals( actual, expected ); }
+ *
+ */
+ /** tests extractTitel with the JIRA ID provided */
+ /*
+ * public void testExtractTtile_withJira() { String itemTitle = "ENHANCEMENT: JBAS-2375 - Backport the
+ * BarrierController service"; String jiraId = "JBAS-2375"; String softwareType = "ENHANCEMENT"; String
+ * rawTitle = null;
+ *
+ * String expected = "Backport the BarrierController service"; String actual = feedJob.extractTitle(
+ * itemTitle, softwareType, jiraId, rawTitle );
+ *
+ * TestCase.assertEquals( actual, expected ); }
+ *
+ */
+ /** tests the feed with a good URL, Username and Password */
+ /*
+ * public void testFeed_goodUrlUsernamePassword() { JobDetail jobDetail = loadJobDetail( GOOD_PATCH_FEED_URL,
+ * GOOD_USERNAME, GOOD_PASSWORD ); try { this.feedJob.testFeed( jobDetail ); } catch (
+ * RssFeedException e ) { // should not fail e.printStackTrace(); TestCase.fail(
+ * e.getMessage() ); } }
+ *
+ */
+ /** tests the feed with a good URL but a bud username/password combo */
+ /*
+ * public void testFeed_goodUrl_badUsernamePassword() { JobDetail jobDetail = loadJobDetail(
+ * GOOD_PATCH_FEED_URL, BAD_USERNAME_PASSWORD, BAD_USERNAME_PASSWORD ); try { this.feedJob.testFeed(
+ * jobDetail ); TestCase.fail( "an exception should have been thrown, a bad username/password was sent" );
+ * } catch ( RssFeedException e ) { String expected = "Status was [401 - Unauthorized]";
+ * String actual = e.getMessage(); TestCase.assertTrue( "should have started with [" + expected + "], but
+ * was [" + actual + "]", actual.startsWith( expected ) ); } }
+ */
+ /** tests feed with a bad URL but a good username/password */
+ /*
+ * public void testFeed_badUrl_goodUsernamePassword() { JobDetail jobDetail = loadJobDetail( BAD_URL,
+ * GOOD_USERNAME, GOOD_PASSWORD ); try { this.feedJob.testFeed( jobDetail ); TestCase.fail(
+ * "an exception should have been thrown, a bad username/password was sent" ); } catch ( RssFeedException e
+ * ) { String expected = "Status was [404 - "; String actual = e.getMessage();
+ * TestCase.assertTrue( "should have started with [" + expected + "], but was [" + actual + "]",
+ * actual.startsWith( expected ) ); } }
+ */
+ /** tests feed with a good url and a blank username/password -- it should fail because it expects a username/password */
+ /*
+ * public void testFeed_goodUrl_blankUsernamePassword_fails() { JobDetail jobDetail = loadJobDetail(
+ * GOOD_PATCH_FEED_URL, "", "" ); try { this.feedJob.testFeed( jobDetail ); TestCase.fail(
+ * "an exception should have been thrown, a bad username/password was sent" ); } catch ( RssFeedException e
+ * ) { String expected = "Status was [401 - Unauthorized]"; String actual = e.getMessage();
+ * TestCase.assertTrue( "should have started with [" + expected + "], but was [" + actual + "]",
+ * actual.startsWith( expected ) ); } }
+ *
+ */
+ /** tests feed with a good url and a blank username/password -- it should pass because it does not need a username/password */
+ /*
+ * public void testFeed_goodUrl_blankUsernamePassword_passes() { JobDetail jobDetail = loadJobDetail(
+ * LOCAL_URL_NO_AUTH, "", "" ); try { this.feedJob.testFeed( jobDetail ); } catch (
+ * Exception e ) { // should not fail e.printStackTrace(); TestCase.fail( e.getMessage()
+ * ); } }
+ *
+ *
+ */
+ /**
+ * TODO Currently this test fails when comparing the createdOn field if not run in the EST timezone.
+ *
+ * make sure we can store the feed successfully, without exception
+ */
+ /*
+ * public void test2375FromLocallyLoadedFeed() { JobDetail jobDetail = loadJobDetail( LOCAL_URL_NO_AUTH, "", "" );
+ * try { RssDocument parsedFeed = this.feedJob.testFeed( jobDetail ); this.feedJob.storeFeed(
+ * parsedFeed, LOCAL_URL_NO_AUTH, "JBoss Network" ); SoftwareLocalHome softwareLocalHome =
+ * SoftwareUtil.getLocalHome(); SoftwareValue actual = softwareLocalHome.findByReference(
+ * "https://network.staging.jboss.com/jbossnetwork/restricted/softwareDetail...."
+ * ).getSoftwareValue(); SoftwareValue expected = createJBAS_2375();
+ *
+ * compare( expected, actual ); } catch ( Exception e ) { // should not fail
+ * e.printStackTrace(); TestCase.fail( e.getMessage() ); } }
+ *
+ * private void compare( SoftwareValue expected, SoftwareValue actual ) { TestCase.assertEquals(
+ * expected.getAutomatedDownloadUrl(), actual.getAutomatedDownloadUrl() ); // test that the
+ * getAutomatedInstalltionForThisVersion() works TestCase.assertEquals(
+ * expected.getAutomatedInstallation().trim(), actual.getAutomatedInstallationForThisVersion().trim() );
+ * TestCase.assertEquals( expected.getCreatedBy(), actual.getCreatedBy() ); TestCase.assertEquals(
+ * expected.getCreatedOn(), actual.getCreatedOn() ); TestCase.assertEquals( expected.getDistributionStatus(),
+ * actual.getDistributionStatus() ); TestCase.assertEquals( expected.getDownloadUrl(), actual.getDownloadUrl() );
+ * TestCase.assertEquals( expected.getFilename(), actual.getFilename() ); TestCase.assertEquals(
+ * expected.getFileSize(), actual.getFileSize()); TestCase.assertEquals( expected.getIssueReference(),
+ * actual.getIssueReference() ); TestCase.assertEquals( expected.getLongDescription(), actual.getLongDescription()
+ * ); TestCase.assertEquals( expected.getManualInstallation(), actual.getManualInstallation() );
+ * TestCase.assertEquals( expected.getMD5(), actual.getMD5() ); TestCase.assertEquals( expected.getReferenceURL(),
+ * actual.getReferenceURL() ); TestCase.assertEquals( expected.getSHA256(), actual.getSHA256() );
+ * TestCase.assertEquals( expected.getShortDescription(), actual.getShortDescription() ); TestCase.assertEquals(
+ * expected.getSoftwareType(), actual.getSoftwareType() ); TestCase.assertEquals( expected.getTitle(),
+ * actual.getTitle() );
+ *
+ * compare( expected.getProductLightValues(), actual.getProductLightValues() ); }
+ *
+ * private void compare( ProductLightValue[] expected, ProductLightValue[] actual ) { TestCase.assertEquals(
+ * expected.length, actual.length );
+ *
+ * for( int i = 0; i < expected.length; i++ ) { TestCase.assertEquals( "item " + i, expected[i].getName(),
+ * actual[i].getName() ); TestCase.assertEquals( "item " + i, expected[i].getVersion(), actual[i].getVersion()
+ * ); TestCase.assertEquals( "item " + i, expected[i].getJonResourceType(), actual[i].getJonResourceType() );
+ * TestCase.assertEquals( "item " + i, expected[i].getJonResourceVersion(), actual[i].getJonResourceVersion() );
+ * } }
+ *
+ * private SoftwareValue createJBAS_2375() { JonSoftware expected = new JonSoftware();
+ * expected.setAutomatedDownloadUrl(
+ * "https://network.staging.jboss.com/jbossnetwork/secureDownload.html?softwa..." );
+ * expected.setAutomatedInstallation( "<someElement attribute=\"value\">\n" + "<someInnerElement
+ * attribute1=\"value1\"/>\n" + "<someInnerElement2>\n" + "text here\n"+
+ * "</someInnerElement2>\n" + "</someElement>" ); expected.setCreatedBy( "Dimitris Andreadis" );
+ * expected.setCreatedOn( new Long( 1153151520000L ) ); expected.setDistributionStatusType(
+ * DistributionStatusType.AVAILABLE ); expected.setDownloadUrl(
+ * "https://network.staging.jboss.com/jbossnetwork/restricted/softwareDownloa..."
+ * ); expected.setFileName( "JBAS-2375.jar" ); expected.setFileSize( new Long( 330322L ) );
+ * expected.setIssueReference( "JBAS-2375" ); expected.setLastModified( new Long( 1154286720000L ) );
+ * expected.setLongDescription( "Allows the user to create complex startup dependencies; backported the
+ * BarrierController service to 4.0.0; made Tomcat5 emit the missing \"jboss.tomcat.connectors.started\"
+ * notification, so it is known when the tomcat connectors are started.<br><br>\n" + "\n" + "MD5's
+ * of included files:<br>\n" + " 5318F937B4CB3725B43E52F7A05F80C4 jboss-system.jar<br>\n" +
+ * " F8A78409C10E7F8C1E95B0E54EFEEE5E tomcat50-service.jar<br>\n" + "
+ * 5D43EEACCA668DC59A017ED2E1CB499B barrier-example-service.xml" ); expected.setManualInstallation( "Download and
+ * unzip the attached JBAS-2375.jar<br>\n" + "<br>\n" + "Copy the included jar files to the
+ * following locations:<br>\n" + " jboss-4.0.0/libjboss-system.jar <br>\n" + "
+ * jboss-4.0.0/server/<configuration>/deploy/jbossweb-tomcat50.sar/tomcat50-service.jar<br>\n" +
+ * "<br>\n" + "The patch was tested with the included barrier-example-service.xml that starts an additional
+ * JNDIView service, but it is not necessary in order to use this patch normally.<br><br>" ); expected.setMd5(
+ * "5507D3880F33B5D53310D9C87F060F7D" ); expected.setReferenceURL(
+ * "https://network.staging.jboss.com/jbossnetwork/restricted/softwareDetail...." );
+ * expected.setSha256( "ac70fb11dbf635e622f52d2237507e8eaa0e265e5c9176c0b51bfb6cda6ea4fb" );
+ * expected.setShortDescription( "Backport the BarrierController service introduced in JBoss 4.0.2 to 4.0.0" );
+ * expected.setSoftwareType( SoftwareType.BUG_FIX ); expected.setTitle( "test for download from staging -- 2375"
+ * ); expected.addProduct( new JonProduct( null,
+ * "https://network.staging.jboss.com/jbossnetwork/rss/product#SOFT-0101", "Application Server", "4.0.1",
+ * "jon App server", "jon 4.0.1" )); return expected; }
+ *
+ * private JobDetail loadJobDetail( String url, String username, String password ) { JobDetail jobDetail = new
+ * JobDetail(); JobDataMap dataMap = new JobDataMap(); dataMap.put( RssFeedJob.ID, "0" ); dataMap.put(
+ * RssFeedJob.URL, url ); dataMap.put( RssFeedJob.USERNAME, username ); dataMap.put( RssFeedJob.PASSWORD,
+ * password ); dataMap.put( RssFeedJob.FEED_NAME, "name" );
+ *
+ * jobDetail.setJobDataMap( dataMap ); return jobDetail; }
+ */
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/AbstractMeasurementScheduleManagerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/AbstractMeasurementScheduleManagerTest.java
new file mode 100644
index 0000000..b11102e
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/AbstractMeasurementScheduleManagerTest.java
@@ -0,0 +1,129 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.measurement.test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javax.management.MBeanServer;
+
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.domain.measurement.ResourceMeasurementScheduleRequest;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.enterprise.server.agentclient.AgentClient;
+import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceMBean;
+import org.rhq.enterprise.server.measurement.MeasurementConstants;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestAgentClient;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+
+/**
+ * @author Jay Shaughnessy
+ *
+ */
+public class AbstractMeasurementScheduleManagerTest extends AbstractEJB3Test {
+
+ @Override
+ public TestServerCommunicationsService prepareForTestAgents() {
+ try {
+ MBeanServer mbs = getPlatformMBeanServer();
+ if (mbs.isRegistered(ServerCommunicationsServiceMBean.OBJECT_NAME)) {
+ mbs.unregisterMBean(ServerCommunicationsServiceMBean.OBJECT_NAME);
+ }
+ TestServerCommunicationsService testAgentContainer = new MeasurementScheduleTestServerCommunicationsService();
+ mbs.registerMBean(testAgentContainer, ServerCommunicationsServiceMBean.OBJECT_NAME);
+ return testAgentContainer;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static class MeasurementScheduleTestServerCommunicationsService extends TestServerCommunicationsService {
+
+ private long expectedInterval = MeasurementConstants.MINIMUM_COLLECTION_INTERVAL_MILLIS;
+ private boolean expectedIsEnabled = false;
+ private boolean isTested = false;
+ private List<String> failures = new ArrayList<String>();
+
+ @Override
+ public AgentClient getKnownAgentClient(Agent agent) {
+ AgentClient testClient = new MeasurementScheduleTestAgentClient(agent, this);
+ agentClients.put(agent, testClient);
+
+ return testClient;
+ }
+
+ public void init() {
+ expectedInterval = MeasurementConstants.MINIMUM_COLLECTION_INTERVAL_MILLIS;
+ expectedIsEnabled = false;
+ isTested = false;
+ failures.clear();
+ }
+
+ public void setExpectedInterval(long expectedInterval) {
+ this.expectedInterval = expectedInterval;
+ }
+
+ public void setExpectedIsEnabled(boolean expectedIsEnabled) {
+ this.expectedIsEnabled = expectedIsEnabled;
+ }
+
+ public boolean isTested() {
+ return isTested;
+ }
+
+ public boolean hasFailures() {
+ return !failures.isEmpty();
+ }
+
+ public List<String> getFailures() {
+ return failures;
+ }
+
+ public class MeasurementScheduleTestAgentClient extends TestAgentClient {
+
+ public MeasurementScheduleTestAgentClient(Agent agent, TestServerCommunicationsService commService) {
+ super(agent, commService);
+ }
+
+ @Override
+ public void updateCollection(Set<ResourceMeasurementScheduleRequest> resourceSchedules) {
+ for (ResourceMeasurementScheduleRequest rmsr : resourceSchedules) {
+ for (MeasurementScheduleRequest msr : rmsr.getMeasurementSchedules()) {
+ isTested = true;
+
+ if (msr.getInterval() != expectedInterval) {
+ String msg = "Illegal Schedule Interval, expected " + expectedInterval + ", got: " + msr;
+ failures.add(msg);
+ }
+ if (msr.isEnabled() != expectedIsEnabled) {
+ String msg = "Illegal Schedule isEnabled, expected " + expectedIsEnabled + ", got: " + msr;
+ failures.add(msg);
+ }
+ }
+ }
+ }
+
+ }
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/AvailabilityManagerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/AvailabilityManagerTest.java
new file mode 100644
index 0000000..7298914
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/AvailabilityManagerTest.java
@@ -0,0 +1,1409 @@
+/*
+ * 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.enterprise.server.measurement.test;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Random;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import javax.transaction.TransactionManager;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.criteria.AvailabilityCriteria;
+import org.rhq.core.domain.discovery.AvailabilityReport;
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.ResourceAvailability;
+import org.rhq.core.domain.resource.Agent;
+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.domain.util.PageOrdering;
+import org.rhq.enterprise.server.measurement.AvailabilityManagerLocal;
+import org.rhq.enterprise.server.measurement.AvailabilityPoint;
+import org.rhq.enterprise.server.resource.ResourceAvailabilityManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestServerPluginService;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Test the functionality of the AvailabilityManager
+ *
+ * @author Heiko W. Rupp
+ * @author John Mazzitelli
+ */
+public class AvailabilityManagerTest extends AbstractEJB3Test {
+ private static final boolean ENABLE_TESTS = true;
+
+ private static final AvailabilityType UP = AvailabilityType.UP;
+ private static final AvailabilityType DOWN = AvailabilityType.DOWN;
+ private static final AvailabilityType DISABLED = AvailabilityType.DISABLED;
+ private static final AvailabilityType UNKNOWN = AvailabilityType.UNKNOWN;
+
+ private AvailabilityManagerLocal availabilityManager;
+ private ResourceAvailabilityManagerLocal resourceAvailabilityManager;
+ private ResourceManagerLocal resourceManager;
+
+ private Subject overlord;
+ private Agent theAgent;
+ private Resource theResource;
+ private ResourceType theResourceType;
+ private List<Resource> additionalResources;
+ private Availability availability1;
+ private Availability availability2;
+ private Availability availability3;
+
+ private TestServerPluginService testServerPluginService;
+
+ @BeforeMethod
+ public void beforeMethod() {
+ try {
+ prepareScheduler();
+
+ this.availabilityManager = LookupUtil.getAvailabilityManager();
+ this.resourceAvailabilityManager = LookupUtil.getResourceAvailabilityManager();
+ this.resourceManager = LookupUtil.getResourceManager();
+ this.overlord = LookupUtil.getSubjectManager().getOverlord();
+ additionalResources = new ArrayList<Resource>();
+
+ testServerPluginService = new TestServerPluginService();
+ prepareCustomServerPluginService(testServerPluginService);
+ testServerPluginService.masterConfig.getPluginDirectory().mkdirs();
+ testServerPluginService.startMasterPluginContainer();
+ } catch (Throwable t) {
+ // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
+ // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+
+ @AfterMethod
+ public void afterMethod() throws Exception {
+ try {
+ if (theResource != null) {
+ // perform in-band and out-of-band work in quick succession
+ // this also deletes our attached agent
+ resourceManager.uninventoryResource(overlord, theResource.getId());
+ resourceManager.uninventoryResourceAsyncWork(overlord, theResource.getId());
+ theResource = null;
+ }
+
+ if (additionalResources != null) {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ for (Resource res : additionalResources) {
+ Resource res2 = em.find(Resource.class, res.getId());
+ resourceManager.uninventoryResource(overlord, res2.getId());
+ resourceManager.uninventoryResourceAsyncWork(overlord, res2.getId());
+
+ }
+ getTransactionManager().commit();
+ }
+
+ if (theResourceType != null) {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ em.remove(em.find(ResourceType.class, theResourceType.getId()));
+ theResourceType = null;
+
+ getTransactionManager().commit();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ }
+
+ finally {
+ unprepareScheduler();
+ unprepareServerPluginService();
+ testServerPluginService.stopMasterPluginContainer();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test(enabled = ENABLE_TESTS)
+ public void testInsertPastAvailabilities() throws Exception {
+ Long now = System.currentTimeMillis();
+ Long middle = now - 30000; // 30s ago
+ Long then = now - 60000; // 60s ago
+
+ EntityManager em = beginTx();
+
+ try {
+ setupResource(em);
+ commitAndClose(em);
+
+ Availability aThen = new Availability(theResource, then, UP);
+ aThen.setEndTime(middle);
+
+ Availability aMiddle = new Availability(theResource, middle, DOWN);
+ aMiddle.setEndTime(now);
+
+ Availability aNow = new Availability(theResource, now, UP);
+
+ /*
+ * Simulate a report (aMiddle) that came in late (e.g. because of sorting
+ * issues on the agent or because of a network blip anyway. Expectation is
+ * that it gets just inserted in the middle.
+ */
+ // UNKNOWN(0) -->
+ persistAvailability(aThen);
+ // UNKNOWN(0) --> UP(-60000) -->
+ persistAvailability(aNow);
+ // no change, already at UP
+ // UNKNOWN(0) --> UP(-60000) -->
+ persistAvailability(aMiddle);
+ // UNKNOWN(0) --> UP(-60000) --> DOWN(-30000)
+
+ em = beginTx();
+ Query q = em.createNamedQuery(Availability.FIND_BY_RESOURCE);
+ q.setParameter("resourceId", theResource.getId());
+ List<Availability> avails = q.getResultList();
+
+ assert avails.size() == 3 : "Did not get 3 availabilities but " + avails.size();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ if (em != null) {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test(enabled = ENABLE_TESTS)
+ public void testPurgeAvailabilities() throws Exception {
+ Long now = System.currentTimeMillis();
+ Long middle = now - 30000; // 30s ago
+ Long then = now - 60000; // 60s ago
+
+ EntityManager em = beginTx();
+
+ try {
+ setupResource(em);
+ commitAndClose(em);
+
+ Availability aThen = new Availability(theResource, then, UP);
+
+ Availability aMiddle = new Availability(theResource, middle, DOWN);
+ aMiddle.setEndTime(now);
+
+ Availability aNow = new Availability(theResource, now, UP);
+
+ // UNKNOWN(0) -->
+ persistAvailability(aThen);
+ // UNKNOWN(0) --> UP(-60000) -->
+ persistAvailability(aMiddle);
+ // UNKNOWN(0) --> UP(-60000) --> DOWN(-30000) -->
+ persistAvailability(aNow);
+ // UNKNOWN(0) --> UP(-60000) --> DOWN(-30000) --> UP(NOW) -->
+
+ em = beginTx();
+
+ int purged = availabilityManager.purgeAvailabilities(now - 29999); // keeps aMiddle and aNow
+ assert purged == 2 : "Didn't purge 2 --> " + purged;
+
+ Query q = em.createNamedQuery(Availability.FIND_BY_RESOURCE);
+ q.setParameter("resourceId", theResource.getId());
+ List<Availability> avails = q.getResultList();
+
+ assert avails.size() == 2;
+ assert avails.get(0).getAvailabilityType() == DOWN;
+ assert avails.get(0).getStartTime().equals(middle);
+ assert avails.get(0).getEndTime().equals(now);
+ assert avails.get(1).getAvailabilityType() == UP;
+ assert avails.get(1).getStartTime().equals(now);
+ assert avails.get(1).getEndTime() == null;
+
+ // try to delete them all - but we never should delete the latest
+ purged = availabilityManager.purgeAvailabilities(now + 12345);
+ assert purged == 1 : "Didn't purge 1 --> " + purged;
+ purged = availabilityManager.purgeAvailabilities(now + 12345);
+ assert purged == 0 : "Didn't purge 0 --> " + purged;
+
+ q = em.createNamedQuery(Availability.FIND_BY_RESOURCE);
+ q.setParameter("resourceId", theResource.getId());
+ avails = q.getResultList();
+
+ assert avails.size() == 1;
+ assert avails.get(0).getAvailabilityType() == UP;
+ assert avails.get(0).getStartTime().equals(now);
+ assert avails.get(0).getEndTime() == null;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ if (em != null) {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetAvailabilities() throws Exception {
+ EntityManager em = beginTx();
+
+ try {
+ List<AvailabilityPoint> availPoints;
+ Availability avail;
+
+ setupResource(em);
+ // platform: UNKNOWN(0) -->
+ commitAndClose(em);
+ em = null;
+
+ AvailabilityReport report = new AvailabilityReport(false, theAgent.getName());
+
+ availPoints = availabilityManager.findAvailabilitiesForResource(overlord, theResource.getId(), 1,
+ System.currentTimeMillis(), 3, false);
+ assert availPoints.size() == 3 : "There is no avail data, but should still get 3 availability points";
+ assert availPoints.get(0).getAvailabilityType() == UNKNOWN;
+ assert availPoints.get(1).getAvailabilityType() == UNKNOWN;
+ assert availPoints.get(2).getAvailabilityType() == UNKNOWN;
+
+ Long startMillis = 60000L;
+ avail = new Availability(theResource, startMillis, UP);
+ report.addAvailability(avail);
+ availabilityManager.mergeAvailabilityReport(report);
+ // platform: UNKNOWN(0) --> UP(60000) -->
+
+ // our avail data point is right on the start edge
+ availPoints = availabilityManager.findAvailabilitiesForResource(overlord, theResource.getId(), startMillis,
+ startMillis + 10000, 3, false);
+ assert availPoints.size() == 3 : "There is 1 avail data, but should still get 3 availability points";
+ assert availPoints.get(0).getAvailabilityType() == UP;
+ assert availPoints.get(1).getAvailabilityType() == UP;
+ assert availPoints.get(2).getAvailabilityType() == UP;
+
+ // our avail data point is right on the end edge
+ availPoints = availabilityManager.findAvailabilitiesForResource(overlord, theResource.getId(),
+ startMillis - 3, startMillis, 3, false);
+ assert availPoints.size() == 3 : "There is 1 avail data, but should still get 3 availability points";
+ assert availPoints.get(0).getAvailabilityType() == UNKNOWN;
+ assert !availPoints.get(0).isKnown() : availPoints;
+ assert availPoints.get(1).getAvailabilityType() == UNKNOWN;
+ assert !availPoints.get(1).isKnown() : availPoints;
+ assert availPoints.get(2).getAvailabilityType() == UNKNOWN;
+ assert !availPoints.get(2).isKnown() : availPoints;
+
+ availPoints = availabilityManager.findAvailabilitiesForResource(overlord, theResource.getId(),
+ startMillis - 20000, startMillis + 10000, 3, false);
+ assert availPoints.size() == 3 : "There is 1 avail data, but should still get 3 availability points";
+ assert availPoints.get(0).getAvailabilityType() == UNKNOWN;
+ assert !availPoints.get(0).isKnown() : availPoints;
+ assert availPoints.get(1).getAvailabilityType() == UNKNOWN;
+ assert !availPoints.get(1).isKnown() : availPoints;
+ assert availPoints.get(2).getAvailabilityType() == UP : availPoints;
+
+ availPoints = availabilityManager.findAvailabilitiesForResource(overlord, theResource.getId(),
+ startMillis - 10000, startMillis + 20000, 3, false);
+ assert availPoints.size() == 3 : "There is 1 avail data, but should still get 3 availability points";
+ assert availPoints.get(0).getAvailabilityType() == UNKNOWN;
+ assert !availPoints.get(0).isKnown() : availPoints;
+ assert availPoints.get(1).getAvailabilityType() == UP;
+ assert availPoints.get(1).isKnown() : availPoints;
+ assert availPoints.get(2).getAvailabilityType() == UP;
+
+ availPoints = availabilityManager.findAvailabilitiesForResource(overlord, theResource.getId(),
+ startMillis - 20000, startMillis + 20000, 10, false);
+ assert availPoints.size() == 10 : "There is 1 avail data, but should still get 10 availability points";
+ assert availPoints.get(0).getAvailabilityType() == UNKNOWN : availPoints;
+ assert !availPoints.get(0).isKnown() : availPoints;
+ assert availPoints.get(1).getAvailabilityType() == UNKNOWN : availPoints;
+ assert !availPoints.get(1).isKnown() : availPoints;
+ assert availPoints.get(2).getAvailabilityType() == UNKNOWN : availPoints;
+ assert !availPoints.get(2).isKnown() : availPoints;
+ assert availPoints.get(3).getAvailabilityType() == UNKNOWN : availPoints;
+ assert !availPoints.get(3).isKnown() : availPoints;
+ assert availPoints.get(4).getAvailabilityType() == UNKNOWN : availPoints;
+ assert !availPoints.get(4).isKnown() : availPoints;
+ assert availPoints.get(5).getAvailabilityType() == UP : availPoints;
+ assert availPoints.get(5).isKnown() : availPoints;
+ assert availPoints.get(6).getAvailabilityType() == UP : availPoints;
+ assert availPoints.get(7).getAvailabilityType() == UP : availPoints;
+ assert availPoints.get(8).getAvailabilityType() == UP : availPoints;
+ assert availPoints.get(9).getAvailabilityType() == UP : availPoints;
+
+ report = new AvailabilityReport(false, theAgent.getName()); // 70000
+ report.setEnablementReport(true); // simulate a real disable
+ report.addAvailability(new Availability(theResource, (startMillis + 10000L), DISABLED));
+ availabilityManager.mergeAvailabilityReport(report);
+ // UNKNOWN(0) --> UP(60000) --> DISABLED(70000) -->
+
+ // before setting other avails, must end disable with enablement report to unknown
+ report = new AvailabilityReport(false, theAgent.getName()); // 75000
+ report.setEnablementReport(true);
+ report.addAvailability(new Availability(theResource, (startMillis + 15000L), UNKNOWN));
+ availabilityManager.mergeAvailabilityReport(report);
+ // UNKNOWN(0) --> UP(60000) --> DISABLED(70000) --> UNKNOWN(75000) -->
+
+ report = new AvailabilityReport(false, theAgent.getName()); // 80000
+ report.addAvailability(new Availability(theResource, (startMillis + 20000L), UP));
+ availabilityManager.mergeAvailabilityReport(report);
+ // UNKNOWN(0) --> UP(60000) --> DISABLED(70000) --> UNKNOWN(75000) --> UP(80000)
+
+ report = new AvailabilityReport(false, theAgent.getName()); // 90000
+ report.addAvailability(new Availability(theResource, (startMillis + 30000L), DOWN));
+ availabilityManager.mergeAvailabilityReport(report);
+ // UNKNOWN(0) --> UP(60000) --> DISABLED(70000) --> UNKNOWN(75000) --> UP(80000) --> DOWN(90000) -->
+
+ availPoints = availabilityManager.findAvailabilitiesForResource(overlord, theResource.getId(),
+ startMillis - 15000, startMillis + 35000, 5, false); // 45000 - 95000
+
+ // 45-55 == unknown
+ assert availPoints.size() == 5 : "should get 5 availability points";
+ assert availPoints.get(0).getAvailabilityType() == UNKNOWN : availPoints;
+ assert !availPoints.get(0).isKnown() : availPoints;
+
+ // 55-65 == 55-60=unknown, 60-65=up
+ // because part of it was UNKNOWN, we consider the data point UNKNOWN
+ assert availPoints.get(1).getAvailabilityType() == UNKNOWN : availPoints;
+ assert !availPoints.get(1).isKnown() : availPoints;
+
+ // 65-75 == 65-70=up, 70-75=disabled
+ assert availPoints.get(2).getAvailabilityType() == DISABLED : availPoints;
+
+ // 75-85 == 75-80=unknown, 80-85=up
+ assert availPoints.get(3).getAvailabilityType() == UNKNOWN : availPoints;
+
+ // 85-95, == 85-90=up, 90-95=down
+ assert availPoints.get(4).getAvailabilityType() == DOWN : availPoints;
+
+ // 30000 - 90000
+ availPoints = availabilityManager.findAvailabilitiesForResource(overlord, theResource.getId(),
+ startMillis - 30000, startMillis + 30000, 10, false);
+
+ assert availPoints.size() == 10 : "should get 10 availability points";
+ assert availPoints.get(0).getAvailabilityType() == UNKNOWN : availPoints; // 30-36
+ assert availPoints.get(1).getAvailabilityType() == UNKNOWN : availPoints; // 36-42
+ assert availPoints.get(2).getAvailabilityType() == UNKNOWN : availPoints; // 42-48
+ assert availPoints.get(3).getAvailabilityType() == UNKNOWN : availPoints; // 58-54
+ assert availPoints.get(4).getAvailabilityType() == UNKNOWN : availPoints; // 54-60
+ assert availPoints.get(5).getAvailabilityType() == UP : availPoints; // 60-66
+ assert availPoints.get(6).getAvailabilityType() == DISABLED : availPoints; // 66-72
+ assert availPoints.get(7).getAvailabilityType() == DISABLED : availPoints; // 72-78
+ assert availPoints.get(8).getAvailabilityType() == UNKNOWN : availPoints; // 78-84
+ assert availPoints.get(9).getAvailabilityType() == UP : availPoints; // 84-90
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ if (em != null) {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testSetAllAgentResourceAvailabilities() throws Exception {
+ EntityManager em = beginTx();
+
+ try {
+ setupResource(em);
+ commitAndClose(em);
+ em = null;
+
+ // setAllAgentResourceAvails will only operate on those that have at least 1 avail row
+ Availability avail = new Availability(theResource, UNKNOWN);
+ persistAvailability(avail);
+
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == UNKNOWN;
+ availabilityManager.updateAgentResourceAvailabilities(theAgent.getId(), UP, UP);
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == UP;
+ availabilityManager.updateAgentResourceAvailabilities(theAgent.getId(), DOWN, DOWN);
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == DOWN;
+ availabilityManager.updateAgentResourceAvailabilities(theAgent.getId(), DOWN, DOWN); // extend it
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == DOWN;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ if (em != null) {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testAgentBackfillNewResource() throws Exception {
+ EntityManager em = beginTx();
+
+ try {
+ setupResource(em);
+ commitAndClose(em);
+ em = null;
+
+ // have never heard from the new agent yet - we do not backfill anything in this case
+ LookupUtil.getAgentManager().checkForSuspectAgents();
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == UNKNOWN;
+
+ em = beginTx();
+ Resource resource = em.find(Resource.class, theResource.getId());
+ List<Availability> avails = resource.getAvailability();
+ assert avails != null;
+ assert avails.size() == 1; // the initial avail on resource persist
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ if (em != null) {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testAgentBackfill() throws Exception {
+ EntityManager em = beginTx();
+
+ try {
+ prepareForTestAgents();
+
+ setupResource(em);
+ commitAndClose(em);
+ em = null;
+
+ // add a report that says the resource was up 20 minutes ago
+ Availability avail = new Availability(theResource, (System.currentTimeMillis() - 12000000), UP);
+ AvailabilityReport report = new AvailabilityReport(false, theAgent.getName());
+ report.addAvailability(avail);
+ // UNKNOWN(0) -->
+ availabilityManager.mergeAvailabilityReport(report);
+ // UNKNOWN(0) --> UP(-12000000) -->
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == UP;
+
+ // let's pretend we haven't heard from the agent in a few minutes
+ em = beginTx();
+ Agent agent = em.find(Agent.class, theAgent.getId());
+ agent.setLastAvailabilityPing(System.currentTimeMillis() - (1000 * 60 * 18)); // 18 mins
+ commitAndClose(em);
+ em = null;
+
+ // the agent should be suspect and will be considered down, the platform resource should be down
+ // (although children should be UNKNOWN)
+ LookupUtil.getAgentManager().checkForSuspectAgents(); // checks for 5 mins !!
+ // UNKNOWN(0) --> UP(-12000000) -->DOWN(now) -->
+ AvailabilityType curAvail;
+ curAvail = availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId());
+ assert curAvail == DOWN : curAvail;
+
+ // make sure our resource's new availabilities are consistent (first (UNKNOWN) , second (UP), third (DOWN))
+ em = beginTx();
+ Resource resource = em.find(Resource.class, theResource.getId());
+ List<Availability> allAvails = resource.getAvailability();
+ assert allAvails.size() == 3;
+ commitAndClose(em);
+ em = null;
+
+ Availability a1 = allAvails.get(0);
+ Availability a2 = allAvails.get(1);
+ Availability a3 = allAvails.get(2);
+ assert a1.getAvailabilityType() == UNKNOWN;
+ assert a2.getAvailabilityType() == UP : a2.getAvailabilityType();
+ assert a3.getAvailabilityType() == DOWN : a3.getAvailabilityType();
+ assert a1.getEndTime() != null;
+ assert a2.getEndTime() != null;
+ assert a3.getEndTime() == null;
+ assert a1.getEndTime() > a1.getStartTime();
+ assert a2.getEndTime() > a2.getStartTime();
+ assert a2.getStartTime().equals(a1.getEndTime());
+ assert a3.getStartTime().equals(a2.getEndTime());
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ unprepareForTestAgents();
+
+ if (em != null) {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+ }
+
+ @Test(enabled = true)
+ //ENABLE_TESTS)
+ public void testAgentBackfillPerformance() throws Exception {
+ EntityManager em = beginTx();
+ List<Resource> allResources = new ArrayList<Resource>();
+
+ try {
+ prepareForTestAgents();
+
+ setupResource(em); // setup theResource
+
+ allResources.add(theResource);
+
+ // now create a bunch more resources
+ for (int i = 0; i < 99; i++) {
+ allResources.add(setupAnotherResource(em, i, theResource));
+ }
+ em.flush();
+
+ commitAndClose(em);
+ em = null;
+
+ for (Resource res : allResources) {
+ int resId = res.getId();
+ Availability currentAvailability = availabilityManager.getCurrentAvailabilityForResource(overlord,
+ resId);
+ assert currentAvailability != null : "Current Availability was null for " + resId;
+ assert currentAvailability.getAvailabilityType() == UNKNOWN : "Current AvailabilityType should have been UNKNOWN for "
+ + resId;
+
+ AvailabilityCriteria c = new AvailabilityCriteria();
+ c.addFilterResourceId(resId);
+ c.addFilterInterval(0L, Long.MAX_VALUE);
+ c.addSortStartTime(PageOrdering.ASC);
+ List<Availability> allData = availabilityManager.findAvailabilityByCriteria(overlord, c);
+ assert allData != null : "All availabilities was null for " + resId;
+ assert allData.size() == 1 : "All availabilities size was " + allData.size() + " for " + resId;
+
+ ResourceAvailability currentResAvail = resourceAvailabilityManager.getLatestAvailability(resId);
+ assert currentResAvail != null : "Current ResourceAvailability was null for " + resId;
+ assert currentResAvail.getAvailabilityType() == UNKNOWN : "Current ResourceAvailabilityType should have been UNKNOWN for "
+ + resId;
+ }
+
+ // let's pretend we haven't heard from the agent in a few minutes
+ em = beginTx();
+ Agent agent = em.find(Agent.class, theAgent.getId());
+ agent.setLastAvailabilityPing(System.currentTimeMillis() - (1000 * 60 * 18)); // 18 mins
+ commitAndClose(em);
+ em = null;
+
+ // the agent should be suspect and will be considered down. the resources have their initial
+ // UNKNOWN avails. The platform should get a new DOWN Availability row. The rest should remain
+ // as is since they are already UNKNOWN.
+ long start = System.currentTimeMillis();
+ LookupUtil.getAgentManager().checkForSuspectAgents();
+
+ System.out.println("testAgentBackfillPerformance: checkForSuspectAgents run 1 took "
+ + (System.currentTimeMillis() - start) + "ms");
+
+ // add a report that says the resources are now up or disabled- the report will add one avail for each
+ // resource
+ Thread.sleep(500);
+ AvailabilityReport upReport = new AvailabilityReport(false, theAgent.getName());
+ AvailabilityReport disabledReport = new AvailabilityReport(false, theAgent.getName());
+ disabledReport.setEnablementReport(true);
+ int resNum = 0;
+ for (Resource resource : allResources) {
+ if (resNum++ <= 80) {
+ upReport.addAvailability(new Availability(resource, UP));
+ } else {
+ disabledReport.addAvailability(new Availability(resource, DISABLED));
+ }
+ }
+
+ start = System.currentTimeMillis();
+ availabilityManager.mergeAvailabilityReport(upReport);
+ availabilityManager.mergeAvailabilityReport(disabledReport);
+
+ System.out.println("testAgentBackfillPerformance: mergeAvailabilityReport run took "
+ + (System.currentTimeMillis() - start) + "ms");
+
+ // sanity check - make sure the merge at least appeared to work
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == UP;
+
+ // let's again pretend we haven't heard from the agent in a few minutes
+ em = beginTx();
+ agent = em.find(Agent.class, theAgent.getId());
+ agent.setLastAvailabilityPing(System.currentTimeMillis() - (1000 * 60 * 18));
+ commitAndClose(em);
+ em = null;
+
+ // the agent should be suspect and will be considered down
+ // all of the resources have availabilities now, so another row will be added to them if they are not disabled
+ start = System.currentTimeMillis();
+ LookupUtil.getAgentManager().checkForSuspectAgents();
+
+ System.out.println("testAgentBackfillPerformance: checkForSuspectAgents run 2 took "
+ + (System.currentTimeMillis() - start) + "ms");
+
+ AvailabilityType curAvail;
+ start = System.currentTimeMillis();
+ resNum = 0;
+
+ for (Resource resource : allResources) {
+ curAvail = availabilityManager.getCurrentAvailabilityTypeForResource(overlord, resource.getId());
+ AvailabilityType expected = (0 == resNum) ? DOWN : ((resNum > 80) ? DISABLED : UNKNOWN);
+ ++resNum;
+ assert curAvail == expected : "Expected " + expected.name() + " but got " + curAvail.name() + " for "
+ + resource;
+
+ // make sure our resources' new availabilities are consistent
+ // the first time we backfilled everything was unknown, only the platform was updated.
+ // later we went UP/DISABLED then DOWN so we'll have 2, 3 or 4 rows)
+ em = beginTx();
+ resource = em.find(Resource.class, resource.getId());
+ List<Availability> allAvails = resource.getAvailability();
+ assert allAvails.size() == ((expected == DOWN) ? 4 : ((expected == DISABLED) ? 2 : 3)) : allAvails;
+ commitAndClose(em);
+ em = null;
+
+ Availability a0 = allAvails.get(0);
+ Availability a1 = allAvails.get(1);
+ Availability a2 = null;
+ Availability a3 = null;
+ assert a0.getAvailabilityType() == UNKNOWN : allAvails;
+ switch (expected) {
+ case DOWN:
+ // platform
+ a2 = allAvails.get(2);
+ a3 = allAvails.get(3);
+ assert a1.getAvailabilityType() == DOWN : allAvails;
+ assert a2.getAvailabilityType() == UP : allAvails;
+ assert a3.getAvailabilityType() == DOWN : allAvails;
+ assert a0.getEndTime() != null : allAvails;
+ assert a1.getEndTime() != null : allAvails;
+ assert a2.getEndTime() != null : allAvails;
+ assert a3.getEndTime() == null : allAvails;
+ assert a0.getEndTime() > a0.getStartTime() : allAvails;
+ assert a0.getEndTime().equals(a1.getStartTime()) : allAvails;
+ assert a1.getEndTime().equals(a2.getStartTime()) : allAvails;
+ assert a2.getEndTime().equals(a3.getStartTime()) : allAvails;
+ break;
+ case DISABLED:
+ assert a1.getAvailabilityType() == DISABLED : allAvails;
+ assert a0.getEndTime() != null : allAvails;
+ assert a1.getEndTime() == null : allAvails;
+ assert a0.getEndTime() > a0.getStartTime() : allAvails;
+ assert a0.getEndTime().equals(a1.getStartTime()) : allAvails;
+ break;
+ default:
+ a2 = allAvails.get(2);
+ assert a1.getAvailabilityType() == UP : allAvails;
+ assert allAvails.get(2).getAvailabilityType() == UNKNOWN : allAvails;
+ assert a0.getEndTime() != null : allAvails;
+ assert a1.getEndTime() != null : allAvails;
+ assert a2.getEndTime() == null : allAvails;
+ assert a0.getEndTime() > a0.getStartTime() : allAvails;
+ assert a0.getEndTime().equals(a1.getStartTime()) : allAvails;
+ assert a1.getEndTime().equals(a2.getStartTime()) : allAvails;
+ }
+ }
+
+ System.out.println("testAgentBackfillPerformance: checking validity of data took "
+ + (System.currentTimeMillis() - start) + "ms");
+
+ em = null;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ unprepareForTestAgents();
+
+ if (em != null) {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testAgentOldReport() throws Exception {
+ EntityManager em = beginTx();
+
+ try {
+ setupResource(em); // inserts initial UNKNOWN Availability at epoch
+ commitAndClose(em);
+ em = null;
+
+ Availability avail;
+ long now = System.currentTimeMillis();
+
+ // add a report that says the resource is down
+ avail = new Availability(theResource, DOWN);
+ AvailabilityReport report = new AvailabilityReport(false, theAgent.getName());
+ report.addAvailability(avail);
+ availabilityManager.mergeAvailabilityReport(report);
+
+ // now pretend the agent sent us a report from a previous time period - should insert this in the past
+ avail = new Availability(theResource, (now - 600000), UP);
+ report = new AvailabilityReport(false, theAgent.getName());
+ report.addAvailability(avail);
+ availabilityManager.mergeAvailabilityReport(report);
+ assert getPointInTime(new Date(avail.getStartTime() - 2)) == UNKNOWN;
+ assert getPointInTime(new Date(avail.getStartTime())) == UP;
+ assert getPointInTime(new Date(avail.getStartTime() + 2)) == UP;
+
+ // it's still down though - since we've received a more recent report saying it was down
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == DOWN;
+
+ // now pretend the agent sent us reports from inbetween our existing time periods
+ // this UP record combines with the UP we added previously
+ avail = new Availability(theResource, (now - 300000), UP);
+ report = new AvailabilityReport(false, theAgent.getName());
+ report.addAvailability(avail);
+ availabilityManager.mergeAvailabilityReport(report);
+ assert getPointInTime(new Date(avail.getStartTime() - 2)) == UP;
+ assert getPointInTime(new Date(avail.getStartTime())) == UP;
+ assert getPointInTime(new Date(avail.getStartTime() + 2)) == UP;
+
+ // its still down though - since we've received a more recent report saying it was down
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == DOWN;
+
+ // this DOWN record combines with the current DOWN
+ avail = new Availability(theResource, (now - 100000), DOWN);
+ report = new AvailabilityReport(false, theAgent.getName());
+ report.addAvailability(avail);
+ availabilityManager.mergeAvailabilityReport(report);
+ assert getPointInTime(new Date(avail.getStartTime() - 2)) == UP;
+ assert getPointInTime(new Date(avail.getStartTime())) == DOWN;
+ assert getPointInTime(new Date(avail.getStartTime() + 2)) == DOWN;
+
+ // this DOWN record is between the two UPs we added earlier. However, because we are RLE,
+ // we actually lost the information that we had an UP at both -60000 and -30000. We just
+ // have a RLE interval of UP starting at -60000. This new DOWN record will add a new row
+ // that will indicate we were only UP from -60000 to -45000 and DOWN thereafter. This is
+ // an odd test and probably will never occur in the wild (why would an agent tell us
+ // we were one status in the past but another status further back in the past?)
+ avail = new Availability(theResource, (now - 450000), DOWN);
+ report = new AvailabilityReport(false, theAgent.getName());
+ report.addAvailability(avail);
+ availabilityManager.mergeAvailabilityReport(report);
+ assert getPointInTime(new Date(avail.getStartTime() - 2)) == UP;
+ assert getPointInTime(new Date(avail.getStartTime())) == DOWN;
+ assert getPointInTime(new Date(avail.getStartTime() + 2)) == DOWN;
+
+ // its still down
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == DOWN;
+
+ // let's insert one in the very beginning that is the same type as the current first interval
+ avail = new Availability(theResource, (now - 700000), UP);
+ report = new AvailabilityReport(false, theAgent.getName());
+ report.addAvailability(avail);
+ availabilityManager.mergeAvailabilityReport(report);
+ assert getPointInTime(new Date(avail.getStartTime() - 2)) == UNKNOWN;
+ assert getPointInTime(new Date(avail.getStartTime())) == UP;
+ assert getPointInTime(new Date(avail.getStartTime() + 2)) == UP;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ if (em != null) {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testAgentOldReport2() throws Exception {
+ EntityManager em = beginTx();
+
+ try {
+ setupResource(em);
+ commitAndClose(em);
+ em = null;
+
+ long now = System.currentTimeMillis();
+
+ // add a report that says the resource is down - reports can't have the same resource in it twice,
+ // so just create a size=1 report multiple times
+ persistAvailability(new Availability(theResource, (now - 1000000), UP));
+ persistAvailability(new Availability(theResource, (now - 900000), DOWN));
+ persistAvailability(new Availability(theResource, (now - 800000), UP));
+ persistAvailability(new Availability(theResource, (now - 50000), DOWN));
+ persistAvailability(new Availability(theResource, (now - 30000), UP));
+ persistAvailability(new Availability(theResource, (now), DOWN));
+
+ // now pretend the agent sent us a report from a previous time period - should insert this in the past
+ persistAvailability(new Availability(theResource, (now - 600000), UP));
+
+ // its still down though - since we've received a more recent report saying it was down
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == DOWN;
+
+ // now pretend the agent sent us reports from in between our existing time periods
+ // this UP record combines with the UP we added previously
+ persistAvailability(new Availability(theResource, (now - 300000), UP));
+
+ // its still down though - since we've received a more recent report saying it was down
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == DOWN;
+
+ // this DOWN record combines with the current DOWN
+ persistAvailability(new Availability(theResource, (now - 100000), DOWN));
+
+ // this DOWN record is between the two UPs we added earlier. However, because we are RLE,
+ // we actually lost the information that we had an UP at both -60000 and -30000. We just
+ // have a RLE interval of UP starting at -60000. This new DOWN record will add a new row
+ // that will indicate we were only UP fro -60000 to -45000 and DOWN thereafter. This is
+ // an odd test and probably will never occur in the wild (why would an agent tell us
+ // we were one status in the past but another status further back in the past?)
+ persistAvailability(new Availability(theResource, (now - 450000), DOWN));
+
+ // its still down
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == DOWN;
+
+ // let's insert one in the very beginning that is the same type as the current first interval
+ persistAvailability(new Availability(theResource, (now - 700000), UP));
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ if (em != null) {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetAvailabilities2() throws Exception {
+ EntityManager em = beginTx();
+
+ try {
+ Availability avail;
+
+ setupResource(em);
+ commitAndClose(em);
+ em = null;
+
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.YEAR, 2000);
+ cal.set(Calendar.MONTH, 0);
+ cal.set(Calendar.DAY_OF_MONTH, 1);
+ cal.set(Calendar.HOUR, 1);
+ cal.set(Calendar.MINUTE, 0);
+ cal.set(Calendar.SECOND, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+ Date date1 = cal.getTime();
+
+ cal.set(Calendar.HOUR, 1);
+ cal.set(Calendar.MINUTE, 30);
+ Date date2 = cal.getTime();
+
+ cal.set(Calendar.HOUR, 2);
+ cal.set(Calendar.MINUTE, 0);
+ Date date3 = cal.getTime();
+
+ cal.set(Calendar.HOUR, 2);
+ cal.set(Calendar.MINUTE, 30);
+ Date date4 = cal.getTime();
+
+ cal.set(Calendar.HOUR, 3);
+ cal.set(Calendar.MINUTE, 0);
+ Date date5 = cal.getTime();
+
+ cal.set(Calendar.HOUR, 3);
+ cal.set(Calendar.MINUTE, 30);
+ Date date6 = cal.getTime();
+
+ avail = new Availability(theResource, date1.getTime(), UP);
+ avail.setEndTime(date2.getTime());
+ persistAvailability(avail);
+
+ avail = new Availability(theResource, date2.getTime(), DOWN);
+ avail.setEndTime(date3.getTime());
+ persistAvailability(avail);
+
+ avail = new Availability(theResource, date3.getTime(), UP);
+ avail.setEndTime(date4.getTime());
+ persistAvailability(avail);
+
+ avail = new Availability(theResource, date4.getTime(), DOWN);
+ avail.setEndTime(date5.getTime());
+ persistAvailability(avail);
+
+ avail = new Availability(theResource, date5.getTime(), UP);
+ avail.setEndTime(date6.getTime());
+ persistAvailability(avail);
+
+ avail = new Availability(theResource, date6.getTime(), DOWN);
+ persistAvailability(avail);
+
+ List<AvailabilityPoint> points = availabilityManager.findAvailabilitiesForResource(overlord,
+ theResource.getId(), date1.getTime(), date6.getTime(), 5, false);
+ assert points.size() == 5;
+ assert points.get(0).getAvailabilityType() == UP;
+ assert points.get(1).getAvailabilityType() == DOWN;
+ assert points.get(2).getAvailabilityType() == UP;
+ assert points.get(3).getAvailabilityType() == DOWN;
+ assert points.get(4).getAvailabilityType() == UP;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ if (em != null) {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+ }
+
+ /**
+ * See if merging in AvailabilityReports from the agent work.
+ *
+ * @throws Exception in case of error
+ */
+ @Test(enabled = ENABLE_TESTS)
+ public void testMergeReport() throws Exception {
+ EntityManager em = beginTx();
+
+ try {
+ Availability avail;
+ AvailabilityReport report;
+
+ setupResource(em);
+ commitAndClose(em);
+ em = null;
+
+ long allAvailCount = setUpAvailabilities(em);
+
+ // we now have 1:00 UP, 1:20 DOWN, 1:40 UP
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ avail = availabilityManager.getCurrentAvailabilityForResource(overlord, theResource.getId());
+ assert avail.getAvailabilityType() == UP;
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == UP;
+
+ // add something after the start of last, but still be UP (result: nothing added)
+ Long currentStartTime = avail.getStartTime();
+ avail = new Availability(theResource, (currentStartTime + 3600000), UP);
+ report = new AvailabilityReport(false, theAgent.getName());
+ report.addAvailability(avail);
+ Thread.sleep(1000);
+ availabilityManager.mergeAvailabilityReport(report);
+
+ // the agent should have been updated, but no new rows in availability were added
+ Agent agent = LookupUtil.getAgentManager().getAgentByName(theAgent.getName());
+ Date lastReport = new Date(agent.getLastAvailabilityReport());
+ assert lastReport != null;
+ assert countAvailabilitiesInDB(null) == allAvailCount;
+ avail = availabilityManager.getCurrentAvailabilityForResource(overlord, theResource.getId());
+
+ // should have returned availability3
+ // NOTE: availability3 never got an ID assigned, so we can't compare by id
+ // assert avail.getId() == availability3.getId();
+ assert avail.getStartTime().equals(availability3.getStartTime());
+ assert avail.getAvailabilityType() == availability3.getAvailabilityType();
+ assert Math.abs(avail.getStartTime() - availability3.getStartTime()) < 1000;
+ assert avail.getEndTime() == null;
+ assert availability3.getEndTime() == null;
+
+ // change start after the start of last (result: add new avail row)
+ avail = new Availability(theResource, (currentStartTime + 7200000), DOWN);
+ report = new AvailabilityReport(false, theAgent.getName());
+ report.addAvailability(avail);
+ Thread.sleep(1000);
+ availabilityManager.mergeAvailabilityReport(report);
+
+ // the agent should have been updated and a new row in availability was added (resource is now DOWN)
+ agent = LookupUtil.getAgentManager().getAgentByName(theAgent.getName());
+ assert new Date(agent.getLastAvailabilityReport()).after(lastReport);
+ assert countAvailabilitiesInDB(null) == (allAvailCount + 1);
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == DOWN;
+ Availability queriedAvail = availabilityManager.getCurrentAvailabilityForResource(overlord,
+ theResource.getId());
+ assert queriedAvail.getId() > 0;
+ assert queriedAvail.getAvailabilityType() == avail.getAvailabilityType();
+ assert Math.abs(queriedAvail.getStartTime() - avail.getStartTime()) < 1000;
+ assert queriedAvail.getEndTime() == null;
+ assert avail.getEndTime() == null;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ if (em != null) {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+ }
+
+ /**
+ * See if merging in AvailabilityReports from the agent work if it includes a stale resource
+ *
+ * @throws Exception in case of error
+ */
+ @Test(enabled = ENABLE_TESTS)
+ public void testMergeReportWithStaleResource() throws Exception {
+ EntityManager em = beginTx();
+
+ try {
+ Availability avail;
+ AvailabilityReport report;
+
+ setupResource(em);
+ commitAndClose(em);
+ em = null;
+
+ long allAvailCount = setUpAvailabilities(em);
+
+ // we now have 1:00 UP, 1:20 DOWN, 1:40 UP
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ avail = availabilityManager.getCurrentAvailabilityForResource(overlord, theResource.getId());
+ assert avail.getAvailabilityType() == UP;
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == UP;
+
+ // add something after the start of last, but still be UP (result: nothing added)
+ Long currentStartTime = avail.getStartTime();
+ avail = new Availability(theResource, (currentStartTime + 3600000), UP);
+ report = new AvailabilityReport(false, theAgent.getName());
+ report.addAvailability(avail);
+
+ // add something with a stale, non-existent resource. It should be ignored, logging a message,
+ // and the rest of the report should be processed.
+ avail = new Availability(new Resource(898989), (currentStartTime + 3600000), UP);
+ report.addAvailability(avail);
+
+ Thread.sleep(1000);
+ availabilityManager.mergeAvailabilityReport(report);
+
+ // the agent should have been updated, but no new rows in availability were added
+ Agent agent = LookupUtil.getAgentManager().getAgentByName(theAgent.getName());
+ Date lastReport = new Date(agent.getLastAvailabilityReport());
+ assert lastReport != null;
+ assert countAvailabilitiesInDB(null) == allAvailCount;
+ avail = availabilityManager.getCurrentAvailabilityForResource(overlord, theResource.getId());
+
+ // should have returned availability3
+ // NOTE: availability3 never got an ID assigned, so we can't compare by id
+ // assert avail.getId() == availability3.getId();
+ assert avail.getStartTime().equals(availability3.getStartTime());
+ assert avail.getAvailabilityType() == availability3.getAvailabilityType();
+ assert Math.abs(avail.getStartTime() - availability3.getStartTime()) < 1000;
+ assert avail.getEndTime() == null;
+ assert availability3.getEndTime() == null;
+
+ // change start after the start of last (result: add new avail row)
+ avail = new Availability(theResource, (currentStartTime + 7200000), DOWN);
+ report = new AvailabilityReport(false, theAgent.getName());
+ report.addAvailability(avail);
+ Thread.sleep(1000);
+ availabilityManager.mergeAvailabilityReport(report);
+
+ // the agent should have been updated and a new row in availability was added (resource is now DOWN)
+ agent = LookupUtil.getAgentManager().getAgentByName(theAgent.getName());
+ assert new Date(agent.getLastAvailabilityReport()).after(lastReport);
+ assert countAvailabilitiesInDB(null) == (allAvailCount + 1);
+ assert availabilityManager.getCurrentAvailabilityTypeForResource(overlord, theResource.getId()) == DOWN;
+ Availability queriedAvail = availabilityManager.getCurrentAvailabilityForResource(overlord,
+ theResource.getId());
+ assert queriedAvail.getId() > 0;
+ assert queriedAvail.getAvailabilityType() == avail.getAvailabilityType();
+ assert Math.abs(queriedAvail.getStartTime() - avail.getStartTime()) < 1000;
+ assert queriedAvail.getEndTime() == null;
+ assert avail.getEndTime() == null;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ if (em != null) {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testMergeReportPerformance() throws Exception {
+ EntityManager em = beginTx();
+ List<Resource> allResources = new ArrayList<Resource>();
+
+ try {
+ setupResource(em); // setup theResource
+
+ allResources.add(theResource);
+
+ // now create a bunch more resources
+ for (int i = 0; i < 100; i++) {
+ allResources.add(setupAnotherResource(em, i, theResource));
+ }
+ em.flush();
+
+ commitAndClose(em);
+ em = null;
+
+ // add a report that says the resources are now up - the report will add one avail for each resource
+ // at this point, the resources do not yet have a row in availability - after the merge they will have 1
+ AvailabilityReport report = new AvailabilityReport(false, theAgent.getName());
+ for (Resource resource : allResources) {
+ Availability avail = new Availability(resource, UP);
+ report.addAvailability(avail);
+ }
+
+ long start = System.currentTimeMillis();
+ availabilityManager.mergeAvailabilityReport(report);
+
+ System.out.println("testMergeReportPerformance: mergeAvailabilityReport run 1 took "
+ + (System.currentTimeMillis() - start) + "ms");
+
+ AvailabilityType curAvail;
+ start = System.currentTimeMillis();
+
+ for (Resource resource : allResources) {
+ curAvail = availabilityManager.getCurrentAvailabilityTypeForResource(overlord, resource.getId());
+ assert curAvail == UP : curAvail;
+ }
+
+ System.out.println("testMergeReportPerformance: checking validity of data 1 took "
+ + (System.currentTimeMillis() - start) + "ms");
+
+ // add a report that says the resources are now down - the report will add one avail for each resource
+ // at this point, the resources have 1 row in availability - after the merge they will have 2
+ report = new AvailabilityReport(false, theAgent.getName());
+ for (Resource resource : allResources) {
+ Availability avail = new Availability(resource, DOWN);
+ report.addAvailability(avail);
+ }
+
+ start = System.currentTimeMillis();
+ availabilityManager.mergeAvailabilityReport(report);
+
+ System.out.println("testMergeReportPerformance: mergeAvailabilityReport run 2 took "
+ + (System.currentTimeMillis() - start) + "ms");
+
+ start = System.currentTimeMillis();
+
+ for (Resource resource : allResources) {
+ curAvail = availabilityManager.getCurrentAvailabilityTypeForResource(overlord, resource.getId());
+ assert curAvail == DOWN : curAvail;
+ }
+
+ System.out.println("testMergeReportPerformance: checking validity of data 2 took "
+ + (System.currentTimeMillis() - start) + "ms");
+
+ // add a report that says the resources are now unknown - the report will add one avail for each resource
+ // at this point, the resources have 2 rows in availability - after the merge they will have 3
+ report = new AvailabilityReport(false, theAgent.getName());
+ for (Resource resource : allResources) {
+ Availability avail = new Availability(resource, UNKNOWN);
+ report.addAvailability(avail);
+ }
+
+ start = System.currentTimeMillis();
+ availabilityManager.mergeAvailabilityReport(report);
+
+ System.out.println("testMergeReportPerformance: mergeAvailabilityReport run 3 took "
+ + (System.currentTimeMillis() - start) + "ms");
+
+ start = System.currentTimeMillis();
+
+ for (Resource resource : allResources) {
+ curAvail = availabilityManager.getCurrentAvailabilityTypeForResource(overlord, resource.getId());
+ assert curAvail == UNKNOWN : curAvail;
+ }
+
+ System.out.println("testMergeReportPerformance: checking validity of data 3 took "
+ + (System.currentTimeMillis() - start) + "ms");
+
+ em = null;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ if (em != null) {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+ }
+
+ private EntityManager beginTx() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ return em;
+ }
+
+ private void commitAndClose(EntityManager em) throws Exception {
+ getTransactionManager().commit();
+ em.close();
+ }
+
+ /**
+ * @param time The point in time will span 1 millisecond from the time provided to time+1
+ * @return
+ */
+ private AvailabilityType getPointInTime(Date time) {
+ List<AvailabilityPoint> list = availabilityManager.findAvailabilitiesForResource(overlord, theResource.getId(),
+ time.getTime(), time.getTime() + 1, 1, false);
+ assert list != null;
+ assert list.size() == 1 : "Should have returned a single point";
+ AvailabilityType type = list.get(0).getAvailabilityType();
+
+ switch (type) {
+ case UP:
+ case DOWN:
+ case DISABLED:
+ case UNKNOWN:
+ return type;
+
+ default:
+ assert false : "AvailabilityType enum has some additional values not known to this test: " + type;
+ }
+
+ return null;
+ }
+
+ /**
+ * See how many rows we have in the availability table
+ *
+ * @param em EntityManager to use
+ *
+ * @return the rowcount
+ *
+ * @throws Exception
+ */
+ private long countAvailabilitiesInDB(EntityManager em) throws Exception {
+ TransactionManager tx = null;
+
+ if (em == null) {
+ tx = getTransactionManager();
+ tx.begin();
+ em = getEntityManager();
+ }
+
+ try {
+ Query q = em.createQuery("SELECT count(a) FROM Availability a");
+ long count = (Long) q.getSingleResult();
+ return count;
+ } finally {
+ if (tx != null) {
+ tx.rollback();
+ em.close();
+ }
+ }
+ }
+
+ /**
+ * Just set up a resource where we can attach the availabilities to
+ *
+ * @param em The EntityManager to use
+ *
+ * @return A Resource ready to use
+ */
+ private Resource setupResource(EntityManager em) {
+ theAgent = new Agent("testagent", "localhost", 1234, "", "randomToken");
+ em.persist(theAgent);
+
+ theResourceType = new ResourceType("test-plat", "test-plugin", ResourceCategory.PLATFORM, null);
+ em.persist(theResourceType);
+
+ theResource = new Resource("test-platform-key", "test-platform-name", theResourceType);
+ theResource.setUuid("" + new Random().nextInt());
+ theResource.setAgent(theAgent);
+ em.persist(theResource);
+
+ em.flush();
+ return theResource;
+ }
+
+ /**
+ * Set up another unique resource that will be related to <code>theAgent</code>. The resource will be of type <code>
+ * theResourceType</code>.
+ *
+ * @param em The EntityManager to use
+ * @param uniqueNumber used to define a unique key for the resource
+ *
+ * @return A Resource ready to use
+ */
+ private Resource setupAnotherResource(EntityManager em, int uniqueNumber, Resource parentResource) {
+ Resource newResource;
+
+ newResource = new Resource("test-platform-key-" + uniqueNumber, "test-platform-name-" + uniqueNumber,
+ theResourceType);
+ newResource.setUuid("" + new Random().nextInt());
+ newResource.setAgent(theAgent);
+ parentResource.addChildResource(newResource);
+ em.persist(newResource);
+ additionalResources.add(newResource);
+
+ return newResource;
+ }
+
+ /**
+ * Set up an availability scenario where we set up availability for one hour, split it in the middle and have 20min
+ * up, 20min down, 20min up starting at 1:00am.
+ *
+ * @param em An EntityManager to use
+ *
+ * @return total number of availability records in the DB after we've added ours
+ *
+ * @throws Exception
+ */
+ private long setUpAvailabilities(EntityManager em) throws Exception {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(new Date());
+ cal.set(Calendar.HOUR, 1);
+ cal.set(Calendar.MINUTE, 0);
+ cal.set(Calendar.SECOND, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+ Date start = cal.getTime();
+
+ // split time
+ cal.set(Calendar.HOUR, 1);
+ cal.set(Calendar.MINUTE, 20);
+ Date splitStart = cal.getTime();
+ cal.set(Calendar.MINUTE, 40);
+ Date splitEnd = cal.getTime();
+
+ long count = countAvailabilitiesInDB(em);
+
+ availability1 = new Availability(theResource, start.getTime(), UP);
+ availability1.setEndTime(splitStart.getTime());
+ persistAvailability(availability1);
+
+ availability2 = new Availability(theResource, splitStart.getTime(), DOWN);
+ availability2.setEndTime(splitEnd.getTime());
+ persistAvailability(availability2);
+
+ availability3 = new Availability(theResource, splitEnd.getTime(), UP);
+ persistAvailability(availability3);
+
+ long countNow = countAvailabilitiesInDB(em);
+
+ assert countNow == (count + 3) : "Did not find three availabilities - instead found: " + countNow;
+
+ return countNow;
+ }
+
+ /**
+ * Convenience method for persisting availability. Availability data can no longer be directly merged
+ * by the EntityManager because it does not update the corresponding currentAvailability data on the
+ * Resource entity. This method will update the necessary objects for you.
+ */
+ private void persistAvailability(Availability... availabilities) {
+ AvailabilityReport report = new AvailabilityReport(false, theAgent.getName());
+ for (Availability avail : availabilities) {
+ report.addAvailability(avail);
+ }
+ availabilityManager.mergeAvailabilityReport(report);
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementBaselineManagerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementBaselineManagerTest.java
new file mode 100644
index 0000000..86bfb07
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementBaselineManagerTest.java
@@ -0,0 +1,616 @@
+/*
+ * 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.enterprise.server.measurement.test;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Random;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.measurement.MeasurementBaseline;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementOOB;
+import org.rhq.core.domain.measurement.MeasurementSchedule;
+import org.rhq.core.domain.measurement.NumericType;
+import org.rhq.core.domain.measurement.composite.MeasurementOOBComposite;
+import org.rhq.core.domain.resource.Agent;
+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.domain.util.PageControl;
+import org.rhq.enterprise.server.measurement.MeasurementBaselineManagerLocal;
+import org.rhq.enterprise.server.measurement.MeasurementOOBManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+@Test
+public class MeasurementBaselineManagerTest extends AbstractEJB3Test {
+ private Agent agent;
+ private ResourceType platformType;
+ private Resource platform;
+ private Resource platform2;
+ private MeasurementDefinition measDef;
+ private MeasurementSchedule measSched;
+ private MeasurementSchedule measSched2;
+ private EntityManager entityManager;
+ private ResourceManagerLocal resourceManager;
+ private MeasurementBaselineManagerLocal baselineManager;
+ private MeasurementOOBManagerLocal oobManager;
+ private Subject overlord;
+
+ // for the large inventory test
+ private List<Resource> allResources;
+ private List<MeasurementDefinition> allDefs;
+ private List<MeasurementSchedule> allScheds;
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ this.prepareScheduler();
+ this.resourceManager = LookupUtil.getResourceManager();
+ this.baselineManager = LookupUtil.getMeasurementBaselineManager();
+ this.oobManager = LookupUtil.getOOBManager();
+ this.overlord = LookupUtil.getSubjectManager().getOverlord();
+ }
+
+ @AfterMethod
+ public void afterMethod() throws Exception {
+ this.unprepareScheduler();
+ }
+
+ /**
+ * Tests auto-calculation with a large inventory.
+ *
+ * @throws Throwable
+ */
+ public void testAutoBaselineCalculationsWithLargeInventory() throws Throwable {
+ long startingTime;
+
+ begin();
+
+ try {
+ setupManyResources(entityManager, 20, 10);
+
+ long now = System.currentTimeMillis();
+ long eldest = now - 180000;
+ long elder = now - 120000;
+ long young = now - 60000;
+ long youngest = now;
+
+ int dataCount = allScheds.size();
+ for (MeasurementSchedule sched : allScheds) {
+ insertMeasurementDataNumeric1H(eldest, sched, 30.0, 20.0, 40.0);
+ insertMeasurementDataNumeric1H(elder, sched, 5.0, 2.0, 8.0);
+ insertMeasurementDataNumeric1H(young, sched, 6.0, 3.0, 9.0);
+ insertMeasurementDataNumeric1H(youngest, sched, 40.0, 30.0, 50.0);
+ if ((--dataCount % 500) == 0) {
+ System.out.println(String.valueOf(dataCount) + " more test measurement data left to insert");
+ commitAndBegin();
+ }
+ }
+
+ commit();
+
+ startingTime = System.currentTimeMillis();
+
+ long computeTime = baselineManager.calculateAutoBaselines(90000, System.currentTimeMillis());
+ assert computeTime > 0;
+
+ System.out.println(">>>>>>> a) [" + allScheds.size() + "] baselines calculated in ["
+ + (System.currentTimeMillis() - startingTime) + "] ms");
+
+ // calculate them again, the delete query will be triggered this time
+ startingTime = System.currentTimeMillis();
+ computeTime = baselineManager.calculateAutoBaselines(90000, System.currentTimeMillis());
+ assert computeTime > 0;
+
+ System.out.println(">>>>>>> b) [" + allScheds.size() + "] baselines calculated in ["
+ + (System.currentTimeMillis() - startingTime) + "] ms");
+
+ deleteManyResources();
+ } catch (Throwable t) {
+ System.out.println("TEST FAILURE STACK TRACE FOLLOWS:");
+ t.printStackTrace();
+ throw t;
+ } finally {
+ try {
+ getTransactionManager().rollback();
+ } catch (Exception e) {
+ }
+
+ allScheds.clear();
+ allDefs.clear();
+ allResources.clear();
+ allScheds = null;
+ allDefs = null;
+ allResources = null;
+ }
+ }
+
+ /**
+ * This is a very important test - it tests native queries that are hardcoded. We need this test because just
+ * deploying the EJB3 entities does not ensure these native queries didn't break; running this test will exercise
+ * the native queries.
+ *
+ * @throws Throwable
+ */
+ public void testAutoBaselineCalculations() throws Throwable {
+ begin();
+
+ try {
+ setupResources(entityManager);
+ assert entityManager.find(Resource.class, platform.getId()) != null : "Did not setup platform - cannot test";
+
+ long now = System.currentTimeMillis();
+ long eldest = now - 180000;
+ long elder = now - 120000;
+ long young = now - 60000;
+ long youngest = now;
+
+ insertMeasurementDataNumeric1H(0, measSched, 0.0, 0.0, 0.0);
+ insertMeasurementDataNumeric1H(eldest, measSched, 30.0, 20.0, 40.0);
+ insertMeasurementDataNumeric1H(elder, measSched, 5.0, 2.0, 8.0);
+ insertMeasurementDataNumeric1H(young, measSched, 6.0, 3.0, 9.0);
+ insertMeasurementDataNumeric1H(youngest, measSched, 40.0, 30.0, 50.0);
+
+ insertMeasurementDataNumeric1H(0, measSched2, 0.0, 0.0, 0.0);
+ insertMeasurementDataNumeric1H(eldest, measSched2, 5000.0, 3500.0, 6500.0);
+ insertMeasurementDataNumeric1H(elder, measSched2, 5000.0, 3000.0, 7000.0);
+ insertMeasurementDataNumeric1H(young, measSched2, 2000.0, 1000.0, 3000.0);
+ insertMeasurementDataNumeric1H(youngest, measSched2, 1500.0, 500.0, 2500.0);
+
+ commit();
+
+ // pass now for olderThanTime to ensure all existing baselines are deleted
+ // pass 30000 for amountOfData to only include the youngest in the baseline calculation
+ long computeTime = baselineManager.calculateAutoBaselines(30000, System.currentTimeMillis());
+ assert computeTime > 0;
+
+ MeasurementBaseline bl1;
+ MeasurementBaseline bl2;
+ int bl1Id;
+ int bl2Id;
+ Date bl1ComputeTime;
+ Date bl2ComputeTime;
+
+ begin();
+
+ bl1 = entityManager.find(MeasurementSchedule.class, measSched.getId()).getBaseline();
+ assert bl1 != null : "Baseline for measSched should have been inserted";
+ assert bl1.getSchedule().getId() == measSched.getId();
+ assert !bl1.isUserEntered();
+ assertEquals(30.0, bl1.getMin());
+ assertEquals(50.0, bl1.getMax());
+ assertEquals(40.0, bl1.getMean());
+
+ bl2 = entityManager.find(MeasurementSchedule.class, measSched2.getId()).getBaseline();
+ assert bl2 != null : "Baseline for measSched2 should have been inserted";
+ assert bl2.getSchedule().getId() == measSched2.getId();
+ assert !bl2.isUserEntered();
+ assertEquals(500.0, bl2.getMin());
+ assertEquals(2500.0, bl2.getMax());
+ assertEquals(1500.0, bl2.getMean());
+
+ // remember these, the next time we calculate, they will be deleted and new ones created
+ bl1Id = bl1.getId();
+ bl2Id = bl2.getId();
+ bl1ComputeTime = bl1.getComputeTime();
+ bl2ComputeTime = bl2.getComputeTime();
+
+ commit();
+
+ // calculate them again, the values will be the same, but the delete query will be triggered
+ // wait a bit so our compute time will be assured to be different
+ Thread.sleep(1000L);
+ computeTime = baselineManager.calculateAutoBaselines(30000, System.currentTimeMillis());
+ assert computeTime > 0;
+
+ begin();
+
+ bl1 = entityManager.find(MeasurementSchedule.class, measSched.getId()).getBaseline();
+ assert bl1 != null : "Baseline for measSched should have been inserted";
+ assert bl1.getSchedule().getId() == measSched.getId();
+ assert !bl1.isUserEntered();
+ assertEquals(30.0, bl1.getMin());
+ assertEquals(50.0, bl1.getMax());
+ assertEquals(40.0, bl1.getMean());
+
+ bl2 = entityManager.find(MeasurementSchedule.class, measSched2.getId()).getBaseline();
+ assert bl2 != null : "Baseline for measSched2 should have been inserted";
+ assert bl2.getSchedule().getId() == measSched2.getId();
+ assert !bl2.isUserEntered();
+ assertEquals(500.0, bl2.getMin());
+ assertEquals(2500.0, bl2.getMax());
+ assertEquals(1500.0, bl2.getMean());
+
+ // check the new IDs with the old ones - they should be different due to the delete query
+ assert bl1.getId() != bl1Id : "bl1.getId() was " + bl1.getId() + ", bl1Id was " + bl1Id;
+ assert bl2.getId() != bl2Id : "bl2.getId() was " + bl2.getId() + ", bl2Id was " + bl2Id;
+ assert bl1.getComputeTime().after(bl1ComputeTime);
+ assert bl2.getComputeTime().after(bl2ComputeTime);
+
+ commit();
+
+ // calculate them again using wider ranges to include more (all available) 1H data in the calculation
+ Thread.sleep(1000L);
+ computeTime = baselineManager.calculateAutoBaselines(240000, System.currentTimeMillis());
+ assert computeTime > 0;
+
+ begin();
+
+ bl1 = entityManager.find(MeasurementSchedule.class, measSched.getId()).getBaseline();
+ assert bl1 != null : "Baseline for measSched should have been inserted";
+ assert bl1.getSchedule().getId() == measSched.getId();
+ assert !bl1.isUserEntered();
+ assertEquals(2.0, bl1.getMin());
+ assertEquals(50.00, bl1.getMax());
+ assertEquals(20.25, bl1.getMean());
+
+ bl2 = entityManager.find(MeasurementSchedule.class, measSched2.getId()).getBaseline();
+ assert bl2 != null : "Baseline for measSched2 should have been inserted";
+ assert bl2.getSchedule().getId() == measSched2.getId();
+ assert !bl2.isUserEntered();
+ assertEquals(500.0, bl2.getMin());
+ assertEquals(7000.0, bl2.getMax());
+ assertEquals(3375.0, bl2.getMean());
+
+ // check the new IDs with the old ones - they should be different due to the delete query
+ assert bl1.getId() != bl1Id;
+ assert bl2.getId() != bl2Id;
+ assert bl1.getComputeTime().after(bl1ComputeTime);
+ assert bl2.getComputeTime().after(bl2ComputeTime);
+
+ commit();
+
+ deleteResources();
+ } catch (Throwable t) {
+ System.out.println("TEST FAILURE STACK TRACE FOLLOWS:");
+ t.printStackTrace();
+ throw t;
+ } finally {
+ try {
+ getTransactionManager().rollback();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ /**
+ * Calculate Out of Bound values. Those need to use baselines, so they are tested here
+ * @throws Throwable If anything goes wrong.
+ */
+ @SuppressWarnings("unchecked")
+ public void testCalculateOOB() throws Throwable {
+
+ begin();
+
+ try {
+ setupResources(entityManager);
+ assert entityManager.find(Resource.class, platform.getId()) != null : "Did not setup platform - cannot test";
+
+ long now = System.currentTimeMillis();
+ long eldest = now - 180000;
+ long elder = now - 120000;
+ long young = now - 60000;
+ long youngest = now;
+
+ insertMeasurementDataNumeric1H(0, measSched, 0.0, 0.0, 0.0);
+ insertMeasurementDataNumeric1H(eldest, measSched, 30.0, 20.0, 40.0);
+ insertMeasurementDataNumeric1H(elder, measSched, 5.0, 2.0, 8.0);
+ insertMeasurementDataNumeric1H(young, measSched, 6.0, 3.0, 9.0);
+ insertMeasurementDataNumeric1H(youngest, measSched, 40.0, 30.0, 50.0);
+
+ insertMeasurementDataNumeric1H(0, measSched2, 0.0, 0.0, 0.0);
+ insertMeasurementDataNumeric1H(eldest, measSched2, 5000.0, 3500.0, 6500.0);
+ insertMeasurementDataNumeric1H(elder, measSched2, 5000.0, 3000.0, 7000.0);
+ insertMeasurementDataNumeric1H(young, measSched2, 2000.0, 1000.0, 3000.0);
+ insertMeasurementDataNumeric1H(youngest, measSched2, 1500.0, 500.0, 2500.0);
+
+ commit();
+
+ long computeTime = baselineManager.calculateAutoBaselines(30000, System.currentTimeMillis());
+ assert computeTime > 0;
+
+ begin();
+ // check the 2 values at 5000 against their bands computed between [500 and 1000]
+ oobManager.computeOOBsFromHourBeginingAt(overlord, eldest);
+
+ // check results
+ Query q = entityManager.createQuery("SELECT oo FROM MeasurementOOB oo");
+ List<MeasurementOOB> oobs = q.getResultList();
+ System.out.println("OOBs calculated: \n" + oobs);
+ for (MeasurementOOB oob : oobs) {
+ if (oob.getScheduleId() == measSched.getId()) {
+ assert oob.getOobFactor() == 50 : "Expected: 50, was " + oob.getOobFactor();
+ } else {
+ assert oob.getOobFactor() == 200 : "Expected: 200, was " + oob.getOobFactor();
+ }
+ }
+
+ PageControl pc = PageControl.getUnlimitedInstance();
+
+ List<MeasurementOOBComposite> comps = oobManager.getSchedulesWithOOBs(overlord, null, null, null, pc);
+ // System.out.println("Composites: " + comps);
+ assert comps.size() == 2 : "Expected 2 composites, but got " + comps.size();
+
+ comps = oobManager.getHighestNOOBsForResource(overlord, platform.getId(), 2);
+ assert comps.size() == 1 : "Expected 1 composite, but got " + comps.size();
+
+ // Compute some more OOBs
+ oobManager.computeOOBsFromHourBeginingAt(overlord, elder);
+ q = entityManager.createQuery("SELECT oo FROM MeasurementOOB oo");
+ oobs = q.getResultList();
+ // System.out.println("OOBs calculated: \n" + oobs);
+
+ comps = oobManager.getSchedulesWithOOBs(overlord, null, null, null, pc);
+ // System.out.println("Composites: " + comps);
+ assert comps.size() == 2 : "Expected 2, but was " + comps.size();
+
+ commit();
+
+ // Clean up
+
+ begin();
+
+ q = entityManager.createQuery("DELETE FROM MeasurementOOB oo WHERE oo.id = :sched1 OR oo.id = :sched2");
+ q.setParameter("sched1", measSched.getId());
+ q.setParameter("sched2", measSched2.getId());
+ q.executeUpdate();
+ commit();
+
+ deleteResources();
+ } catch (Throwable t) {
+ System.out.println("TEST FAILURE STACK TRACE FOLLOWS:");
+ t.printStackTrace();
+ throw t;
+ } finally {
+ try {
+ getTransactionManager().rollback();
+ } catch (Exception e) {
+ }
+ }
+
+ }
+
+ private void setupResources(EntityManager em) {
+ agent = new Agent("test-agent", "localhost", 1234, "", "randomToken");
+ em.persist(agent);
+
+ platformType = new ResourceType("testplatAB", "p", ResourceCategory.PLATFORM, null);
+ em.persist(platformType);
+
+ platform = new Resource("platform1", "testAutoBaseline Platform One", platformType);
+ platform.setUuid("" + new Random().nextInt());
+ em.persist(platform);
+ platform.setAgent(agent);
+
+ platform2 = new Resource("platform2", "testAutoBaseline Platform Two", platformType);
+ platform2.setUuid("" + new Random().nextInt());
+ // deleteResource removes the agent, so we can't have two direct platforms for it, make one a child of the other
+ platform.addChildResource(platform2);
+ em.persist(platform2);
+ platform2.setAgent(agent);
+
+ measDef = new MeasurementDefinition(platformType, "testAutoBaseline");
+ measDef.setDefaultOn(true);
+ measDef.setDisplayName("testAutoBaseline Measurement Display Name");
+ measDef.setMeasurementType(NumericType.DYNAMIC);
+ em.persist(measDef);
+
+ measSched = new MeasurementSchedule(measDef, platform);
+ measSched.setEnabled(true);
+ platform.addSchedule(measSched);
+ measDef.addSchedule(measSched);
+ em.persist(measSched);
+
+ measSched2 = new MeasurementSchedule(measDef, platform2);
+ measSched2.setEnabled(true);
+ platform2.addSchedule(measSched2);
+ measDef.addSchedule(measSched2);
+ em.persist(measSched2);
+ }
+
+ private void deleteResources() {
+ Object doomed;
+
+ try {
+ // perform in-band and out-of-band work in quick succession
+ // deleteResource will remove platform and platform2, as well as the agent
+ List<Integer> deletedIds = resourceManager.uninventoryResource(overlord, platform.getId());
+ for (Integer deletedResourceId : deletedIds) {
+ resourceManager.uninventoryResourceAsyncWork(overlord, deletedResourceId);
+ }
+
+ begin();
+
+ deleteMeasurementDataNumeric1H(measSched);
+ deleteMeasurementDataNumeric1H(measSched2);
+
+ if ((doomed = entityManager.find(MeasurementSchedule.class, measSched.getId())) != null) {
+ entityManager.remove(doomed);
+ }
+
+ if ((doomed = entityManager.find(MeasurementSchedule.class, measSched2.getId())) != null) {
+ entityManager.remove(doomed);
+ }
+
+ if ((doomed = entityManager.find(MeasurementDefinition.class, measDef.getId())) != null) {
+ entityManager.remove(doomed);
+ }
+
+ if ((doomed = entityManager.find(ResourceType.class, platformType.getId())) != null) {
+ entityManager.remove(doomed);
+ }
+
+ commit();
+ } catch (Exception e) {
+ System.out.println("Cannot delete test resources, database still has test data in it");
+ e.printStackTrace();
+ }
+ }
+
+ private void setupManyResources(EntityManager em, int resourceCount, int measurementCount) {
+ allResources = new ArrayList<Resource>(resourceCount);
+ allDefs = new ArrayList<MeasurementDefinition>(measurementCount);
+ allScheds = new ArrayList<MeasurementSchedule>(resourceCount * measurementCount);
+
+ platformType = new ResourceType("testplatAB", "p", ResourceCategory.PLATFORM, null);
+ em.persist(platformType);
+
+ for (int m = 0; m < measurementCount; m++) {
+ MeasurementDefinition def = new MeasurementDefinition(platformType, "testAutoBaselineMeasDef" + m);
+ def.setDefaultOn(true);
+ def.setDisplayName("testAutoBaseline Measurement Display Name" + m);
+ def.setMeasurementType(NumericType.DYNAMIC);
+ em.persist(def);
+ allDefs.add(def);
+ }
+
+ em.flush();
+ em.clear();
+
+ System.out.println("Populating test inventory with [" + resourceCount + "] resources.");
+
+ agent = new Agent("test-agent", "localhost", 1234, "", "randomToken");
+ em.persist(agent);
+
+ Resource root = null;
+ for (int r = 0; r < resourceCount; r++) {
+ Resource resource = new Resource(String.valueOf(r), "testAutoBaselineResource" + r, platformType);
+ resource.setUuid("" + new Random().nextInt());
+ if (root == null) {
+ root = resource;
+ } else {
+ root.addChildResource(resource);
+ }
+ em.persist(resource);
+ allResources.add(resource);
+ resource.setAgent(agent);
+
+ for (MeasurementDefinition def : allDefs) {
+ MeasurementSchedule sched = new MeasurementSchedule(def, resource);
+ sched.setEnabled(true);
+ resource.addSchedule(sched);
+ def.addSchedule(sched);
+ em.persist(sched);
+ allScheds.add(sched);
+ }
+
+ if ((r % 50) == 0) {
+ System.out.println("..." + r);
+ em.flush();
+ em.clear();
+ }
+ }
+
+ em.flush();
+ em.clear();
+ System.out.println("Test inventory now has [" + resourceCount + "] resources.");
+
+ return;
+ }
+
+ private void deleteManyResources() {
+ Object doomed;
+
+ try {
+ int dataCount = allScheds.size();
+ begin();
+ for (MeasurementSchedule doomedSched : allScheds) {
+ deleteMeasurementDataNumeric1H(doomedSched);
+ if ((--dataCount % 1000) == 0) {
+ System.out.println(String.valueOf(dataCount) + " more test measurement data left to delete");
+ commitAndBegin();
+ }
+ }
+ commit();
+
+ // delete the resources which will cascade delete all schedules
+ Resource root = allResources.get(0);
+ // perform in-band and out-of-band work in quick succession
+ // this also deletes the agent
+ List<Integer> deletedIds = resourceManager.uninventoryResource(overlord, root.getId());
+ for (Integer deletedResourceId : deletedIds) {
+ resourceManager.uninventoryResourceAsyncWork(overlord, deletedResourceId);
+ }
+
+ begin();
+
+ for (MeasurementDefinition doomedDef : allDefs) {
+ if ((doomed = entityManager.find(MeasurementDefinition.class, doomedDef.getId())) != null) {
+ entityManager.remove(doomed);
+ }
+ }
+
+ if ((doomed = entityManager.find(ResourceType.class, platformType.getId())) != null) {
+ entityManager.remove(doomed);
+ }
+
+ commit();
+
+ } catch (Exception e) {
+ System.out.println("Cannot delete test resources, database still has test data in it");
+ e.printStackTrace();
+ }
+ }
+
+ // commitAndBegin, commit, begin are used mainly when testing in a debugger
+ // so you can commit the data, and examine it in an external SQL tool without
+ // worrying about transactions timing out within the paused test thread.
+ private void commitAndBegin() throws Exception {
+ commit();
+ begin(); // put a breakpoint here and call commitAndBegin at a place where you want to pause the test
+ }
+
+ private void commit() throws Exception {
+ entityManager.flush();
+ getTransactionManager().commit();
+ entityManager.close();
+ }
+
+ private void begin() throws Exception {
+ getTransactionManager().begin();
+ entityManager = getEntityManager();
+ }
+
+ private void insertMeasurementDataNumeric1H(long timeStamp, MeasurementSchedule schedule, double value, double min,
+ double max) {
+ String sql = "INSERT INTO RHQ_measurement_data_num_1h "
+ + "(time_stamp, schedule_id, value, minvalue, maxvalue) " + "VALUES (" + timeStamp + "," + schedule.getId()
+ + "," + value + "," + min + "," + max + ")";
+
+ Query q = entityManager.createNativeQuery(sql);
+ assert q.executeUpdate() == 1;
+ }
+
+ private void deleteMeasurementDataNumeric1H(MeasurementSchedule schedule) {
+ String sql = "DELETE FROM RHQ_measurement_data_num_1h WHERE schedule_id = " + schedule.getId();
+
+ Query q = entityManager.createNativeQuery(sql);
+ q.executeUpdate();
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementDataManagerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementDataManagerTest.java
new file mode 100644
index 0000000..80f0cd2
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementDataManagerTest.java
@@ -0,0 +1,737 @@
+/*
+ * 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.measurement.test;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.agent.measurement.MeasurementAgentService;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.criteria.MeasurementDataTraitCriteria;
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.DisplayType;
+import org.rhq.core.domain.measurement.MeasurementCategory;
+import org.rhq.core.domain.measurement.MeasurementData;
+import org.rhq.core.domain.measurement.MeasurementDataPK;
+import org.rhq.core.domain.measurement.MeasurementDataTrait;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementSchedule;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.measurement.calltime.CallTimeData;
+import org.rhq.core.domain.measurement.calltime.CallTimeDataComposite;
+import org.rhq.core.domain.measurement.calltime.CallTimeDataKey;
+import org.rhq.core.domain.resource.Agent;
+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.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.measurement.CallTimeDataManagerLocal;
+import org.rhq.enterprise.server.measurement.MeasurementDataManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.ResourceTreeHelper;
+
+/**
+ * Test some measurement subsystem functionality
+ * @author Heiko W. Rupp
+ */
+
+public class MeasurementDataManagerTest extends AbstractEJB3Test {
+
+ private static final int DELTA = 20;
+ private MeasurementDataManagerLocal measurementDataManager;
+ private CallTimeDataManagerLocal callTimeDataManager;
+
+ private Subject overlord;
+
+ private Resource resource1, resource2;
+ private ResourceGroup group;
+ private MeasurementDefinition definitionCt1, definitionCt2, definitionCt3;
+ private MeasurementSchedule schedule1, schedule2, schedule3;
+ private ResourceType theResourceType;
+ private Agent theAgent;
+ private Set<MeasurementData> expectedResult1, expectedResult2, expectedResult3, expectedResult4;
+
+ @BeforeMethod
+ public void beforeMethod() {
+ try {
+ this.measurementDataManager = LookupUtil.getMeasurementDataManager();
+ this.callTimeDataManager = LookupUtil.getCallTimeDataManager();
+ this.overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ } catch (Throwable t) {
+ // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
+ // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+
+ @AfterMethod
+ public void afterMethod() {
+
+ try {
+ // delete values
+ callTimeDataManager.purgeCallTimeData(new Date());
+
+ EntityManager em = beginTx();
+
+ // delete keys
+ List<Integer> resourceIds = new ArrayList<Integer>();
+ resourceIds.add(resource1.getId());
+ resourceIds.add(resource2.getId());
+ Query q = em.createNamedQuery(CallTimeDataKey.QUERY_DELETE_BY_RESOURCES);
+ q.setParameter("resourceIds", resourceIds);
+ q.executeUpdate();
+
+ resource1 = em.merge(resource1);
+ for (MeasurementSchedule sched : resource1.getSchedules()) {
+ em.remove(sched);
+ }
+ ResourceTreeHelper.deleteResource(em, resource1);
+
+ resource2 = em.merge(resource2);
+ for (MeasurementSchedule sched : resource2.getSchedules()) {
+ em.remove(sched);
+ }
+ ResourceTreeHelper.deleteResource(em, resource2);
+
+ definitionCt1 = em.merge(definitionCt1);
+ em.remove(definitionCt1);
+ definitionCt2 = em.merge(definitionCt2);
+ em.remove(definitionCt2);
+ if (definitionCt3 != null) {
+ definitionCt3 = em.merge(definitionCt3);
+ em.remove(definitionCt3);
+ }
+
+ theResourceType = em.merge(theResourceType);
+ em.remove(theResourceType);
+
+ // delete group (if exist)
+ if (group != null) {
+ group = em.merge(group);
+ em.remove(group);
+ }
+
+ theAgent = em.merge(theAgent);
+ em.remove(theAgent);
+
+ commitAndClose(em);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void bz658491() throws Exception {
+
+ try {
+ EntityManager em = beginTx();
+
+ setupResources(em);
+
+ em.flush();
+ long now = System.currentTimeMillis();
+
+ MeasurementScheduleRequest request1 = new MeasurementScheduleRequest(schedule1);
+ MeasurementScheduleRequest request2 = new MeasurementScheduleRequest(schedule2);
+
+ CallTimeData data1 = new CallTimeData(request1);
+ CallTimeData data2 = new CallTimeData(request2);
+
+ data1.addCallData("/foo", new Date(), 100);
+ data2.addCallData("/bar", new Date(), 200);
+
+ MeasurementReport report = new MeasurementReport();
+ report.addData(data1);
+ report.addData(data2);
+
+ commitAndClose(em);
+
+ measurementDataManager.mergeMeasurementReport(report);
+
+ // Do not remove this sleep -- the previous is is asynchronous
+ // and the sleep "guarantees" that data is actually hitting the db
+ Thread.sleep(10000);
+
+ PageList<CallTimeDataComposite> list1 = callTimeDataManager.findCallTimeDataForResource(overlord,
+ schedule1.getId(), now - DELTA, System.currentTimeMillis() + DELTA, new PageControl());
+ PageList<CallTimeDataComposite> list2 = callTimeDataManager.findCallTimeDataForResource(overlord,
+ schedule2.getId(), now - DELTA, System.currentTimeMillis() + DELTA, new PageControl());
+
+ assert list1 != null;
+ assert list2 != null;
+
+ assert list1.size() == 1 : "List 1 returned " + list1.size() + " entries, expected was 1";
+ assert list2.size() == 1 : "List 2 returned " + list2.size() + " entries, expected was 1";
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
+ @Test
+ public void bz658491OneResource() throws Exception {
+
+ try {
+ EntityManager em = beginTx();
+
+ setupResources(em);
+
+ em.flush();
+ long now = System.currentTimeMillis();
+
+ MeasurementScheduleRequest request1 = new MeasurementScheduleRequest(schedule1);
+ MeasurementScheduleRequest request2 = new MeasurementScheduleRequest(schedule2);
+
+ CallTimeData data1 = new CallTimeData(request1);
+ CallTimeData data2 = new CallTimeData(request2);
+
+ data1.addCallData("/foo", new Date(), 100);
+ data2.addCallData("/bar", new Date(), 200);
+
+ MeasurementReport report = new MeasurementReport();
+ report.addData(data1);
+ report.addData(data2);
+
+ commitAndClose(em);
+
+ measurementDataManager.mergeMeasurementReport(report);
+
+ // Do not remove this sleep -- the previous is is asynchronous
+ // and the sleep "guarantees" that data is actually hitting the db
+ Thread.sleep(10000);
+
+ PageList<CallTimeDataComposite> list1 = callTimeDataManager.findCallTimeDataForResource(overlord,
+ schedule1.getId(), now - DELTA, System.currentTimeMillis() + DELTA, new PageControl());
+ PageList<CallTimeDataComposite> list2 = callTimeDataManager.findCallTimeDataForResource(overlord,
+ schedule2.getId(), now - DELTA, System.currentTimeMillis() + DELTA, new PageControl());
+
+ assert list1 != null;
+ assert list2 != null;
+
+ assert list1.size() == 1 : "List 1 returned " + list1.size() + " entries, expected was 1";
+ assert list2.size() == 1 : "List 2 returned " + list2.size() + " entries, expected was 1";
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
+ /**
+ * Just set up two resources plus measurement definitions
+ *
+ * @param em The EntityManager to use
+ *
+ */
+ private void setupResources(EntityManager em) {
+ theAgent = new Agent("testagent", "localhost", 1234, "", "randomToken");
+ em.persist(theAgent);
+
+ theResourceType = new ResourceType("test-plat", "test-plugin", ResourceCategory.PLATFORM, null);
+ em.persist(theResourceType);
+
+ definitionCt1 = new MeasurementDefinition("CT-Def1", MeasurementCategory.PERFORMANCE,
+ MeasurementUnits.MILLISECONDS, DataType.CALLTIME, true, 60000, DisplayType.SUMMARY);
+ definitionCt1.setResourceType(theResourceType);
+ em.persist(definitionCt1);
+
+ definitionCt2 = new MeasurementDefinition("CT-Def2", MeasurementCategory.PERFORMANCE,
+ MeasurementUnits.MILLISECONDS, DataType.CALLTIME, true, 60000, DisplayType.SUMMARY);
+ definitionCt2.setResourceType(theResourceType);
+ em.persist(definitionCt2);
+
+ resource1 = new Resource("test-platform-key1", "test-platform-name", theResourceType);
+ resource1.setUuid("" + new Random().nextInt());
+ resource1.setAgent(theAgent);
+ em.persist(resource1);
+ resource2 = new Resource("test-platform-key2", "test-platform-name", theResourceType);
+ resource2.setUuid("" + new Random().nextInt());
+ resource2.setAgent(theAgent);
+ em.persist(resource2);
+
+ schedule1 = new MeasurementSchedule(definitionCt1, resource1);
+ em.persist(schedule1);
+ definitionCt1.addSchedule(schedule1);
+ resource1.addSchedule(schedule1);
+
+ schedule2 = new MeasurementSchedule(definitionCt2, resource1);
+ em.persist(schedule2);
+ definitionCt1.addSchedule(schedule2);
+ resource2.addSchedule(schedule2);
+ }
+
+ /**
+ * Just set up the group of two resources plus measurement definitions
+ *
+ * @param em The EntityManager to use
+ *
+ */
+ private void setupGroupOfResources(EntityManager em) {
+ theAgent = new Agent("testagent", "localhost", 1234, "", "randomToken");
+ em.persist(theAgent);
+
+ theResourceType = new ResourceType("test-plat", "test-plugin", ResourceCategory.PLATFORM, null);
+ em.persist(theResourceType);
+
+ definitionCt1 = new MeasurementDefinition("CT-Def1", MeasurementCategory.PERFORMANCE,
+ MeasurementUnits.MILLISECONDS, DataType.CALLTIME, true, 60000, DisplayType.SUMMARY);
+ definitionCt1.setResourceType(theResourceType);
+ em.persist(definitionCt1);
+
+ definitionCt2 = new MeasurementDefinition("CT-Def2", MeasurementCategory.PERFORMANCE,
+ MeasurementUnits.MILLISECONDS, DataType.CALLTIME, true, 60000, DisplayType.SUMMARY);
+ definitionCt2.setResourceType(theResourceType);
+ em.persist(definitionCt2);
+
+ definitionCt3 = new MeasurementDefinition("CT-Def3", MeasurementCategory.PERFORMANCE,
+ MeasurementUnits.MILLISECONDS, DataType.CALLTIME, true, 60000, DisplayType.SUMMARY);
+ definitionCt3.setResourceType(theResourceType);
+ em.persist(definitionCt3);
+
+ resource1 = new Resource("test-platform-key1", "test-platform-name", theResourceType);
+ resource1.setUuid("" + new Random().nextInt());
+ resource1.setAgent(theAgent);
+ em.persist(resource1);
+
+ resource2 = new Resource("test-platform-key2", "test-platform-name", theResourceType);
+ resource2.setUuid("" + new Random().nextInt());
+ resource2.setAgent(theAgent);
+ em.persist(resource2);
+
+ schedule1 = new MeasurementSchedule(definitionCt1, resource1);
+ em.persist(schedule1);
+ definitionCt1.addSchedule(schedule1);
+ resource1.addSchedule(schedule1);
+
+ schedule2 = new MeasurementSchedule(definitionCt2, resource2);
+ em.persist(schedule2);
+ definitionCt2.addSchedule(schedule2);
+ resource2.addSchedule(schedule2);
+
+ schedule3 = new MeasurementSchedule(definitionCt3, resource2);
+ em.persist(schedule3);
+ definitionCt3.addSchedule(schedule3);
+ resource2.addSchedule(schedule3);
+
+ group = new ResourceGroup("test-group", theResourceType);
+ em.persist(group);
+
+ // prepare return values and expected values
+ long time1 = System.currentTimeMillis();
+ long time2 = time1 + 1;
+ long time3 = time2 + 1;
+ long time4 = time3 + 1;
+ String name1 = "a";
+ String name2 = "b";
+ String name3 = "c";
+ String name4 = "d";
+ String value1 = "test-value1";
+ String value2 = "test-value2";
+ String value3 = "test-value3";
+ String value4 = "test-value4";
+
+ // method findLiveDataForGroup adds prefix with resource id which is part of equals
+ MeasurementData expectedData1 = makeMeasurement(time1, schedule1.getId(), value1, name1);
+ expectedData1.setName(resource1.getId() + ":" + name1);
+ MeasurementData expectedData2 = makeMeasurement(time2, schedule2.getId(), value2, name2);
+ expectedData2.setName(resource2.getId() + ":" + name2);
+ MeasurementData expectedData3 = makeMeasurement(time3, schedule3.getId(), value3, name3);
+ expectedData3.setName(resource2.getId() + ":" + name3);
+ MeasurementData expectedData4 = makeMeasurement(time4, schedule2.getId(), value4, name4);
+ expectedData4.setName(resource2.getId() + ":" + name4);
+
+ expectedResult1 = new HashSet<MeasurementData>(1);
+ expectedResult1.add(expectedData1);
+ expectedResult2 = new HashSet<MeasurementData>(2);
+ expectedResult2.add(expectedData2);
+ expectedResult2.add(expectedData3);
+ expectedResult3 = new HashSet<MeasurementData>(3);
+ expectedResult3.addAll(expectedResult1);
+ expectedResult3.addAll(expectedResult2);
+ expectedResult4 = new HashSet<MeasurementData>(2);
+ expectedResult4.add(expectedData2);
+ expectedResult4.add(expectedData4);
+
+ // mock the MeasurementAgentService
+ MeasurementAgentService mockedMeasurementService = mock(MeasurementAgentService.class);
+ when(mockedMeasurementService.getRealTimeMeasurementValue(eq(resource1.getId()), any(Set.class))).thenReturn(
+ new HashSet<MeasurementData>(Arrays.asList(makeMeasurement(time1, schedule1.getId(), value1, name1))));
+ when(mockedMeasurementService.getRealTimeMeasurementValue(eq(resource2.getId()), any(Set.class))).thenReturn(
+ new HashSet<MeasurementData>(Arrays.asList(makeMeasurement(time2, schedule2.getId(), value2, name2),
+ makeMeasurement(time3, schedule3.getId(), value3, name3))));
+ TestServerCommunicationsService agentServiceContainer = prepareForTestAgents();
+ agentServiceContainer.measurementService = mockedMeasurementService;
+ }
+
+ @Test
+ public void testFindLiveDataForGroup1() throws Exception {
+ // prepare DB
+ EntityManager em = beginTx();
+ setupGroupOfResources(em);
+ commitAndClose(em);
+ try {
+ Set<MeasurementData> actualResult = measurementDataManager.findLiveDataForGroup(overlord, group.getId(),
+ new int[] { resource1.getId() }, new int[] { definitionCt1.getId() });
+
+ Set<MeasurementData> actualResultWithNewHashCodes = new HashSet<MeasurementData>(actualResult);
+ assertEquals(expectedResult1, actualResultWithNewHashCodes);
+
+ actualResult = measurementDataManager.findLiveDataForGroup(overlord, group.getId(),
+ new int[] { resource2.getId() }, new int[] { definitionCt2.getId(), definitionCt3.getId() });
+ actualResultWithNewHashCodes = new HashSet<MeasurementData>(actualResult);
+ assertEquals(expectedResult2, actualResultWithNewHashCodes);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ throw e;
+ }
+ }
+
+ @Test
+ public void testFindLiveDataForGroup2() throws Exception {
+ // prepare DB
+ EntityManager em = beginTx();
+ setupGroupOfResources(em);
+ commitAndClose(em);
+ try {
+ Set<MeasurementData> actualResult = measurementDataManager.findLiveDataForGroup(overlord, group.getId(),
+ new int[] { resource1.getId(), resource2.getId() },
+ new int[] { definitionCt1.getId(), definitionCt2.getId(), definitionCt3.getId() });
+ Set<MeasurementData> actualResultWithNewHashCodes = new HashSet<MeasurementData>(actualResult);
+ assertEquals(expectedResult3, actualResultWithNewHashCodes);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ throw e;
+ }
+ }
+
+ @Test
+ public void testFindLiveDataForGroup3() throws Exception {
+ // prepare DB
+ EntityManager em = beginTx();
+ setupGroupOfResources(em);
+ commitAndClose(em);
+ try {
+
+ Set<MeasurementData> actualResult = measurementDataManager.findLiveDataForGroup(overlord, group.getId(),
+ null, new int[] { definitionCt1.getId() });
+ assertEquals(Collections.emptySet(), actualResult);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ throw e;
+ }
+ }
+
+ @Test
+ public void testFindLiveDataForGroup4() throws Exception {
+ // prepare DB
+ EntityManager em = beginTx();
+ setupGroupOfResources(em);
+ commitAndClose(em);
+ try {
+ measurementDataManager.findLiveDataForGroup(null, group.getId(), new int[] { resource1.getId() },
+ new int[] { definitionCt1.getId() });
+ fail();
+ } catch (Exception e) {
+ // ok, it was expected
+ }
+ }
+
+ @Test
+ public void testAddAndFindTrait1() throws Exception {
+ // prepare DB
+ EntityManager em = beginTx();
+ setupGroupOfResources(em);
+ commitAndClose(em);
+ try {
+ Set<MeasurementDataTrait> expectedResult = new HashSet<MeasurementDataTrait>();
+ for (MeasurementData data : expectedResult1) {
+ data.setName(null);
+ expectedResult.add((MeasurementDataTrait) data);
+ }
+ // add the trait data (it stores it in db (without name field))
+ measurementDataManager.addTraitData(expectedResult);
+
+ // get back the trait data
+ List<MeasurementDataTrait> actualResult = measurementDataManager.findTraits(overlord, resource1.getId(), definitionCt1.getId());
+
+ Set<MeasurementData> actualResultSet = new HashSet<MeasurementData>(actualResult);
+ assertEquals(expectedResult, actualResultSet);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ throw e;
+ }
+ }
+
+ @Test
+ public void testAddAndFindTrait2() throws Exception {
+ // prepare DB
+ EntityManager em = beginTx();
+ setupGroupOfResources(em);
+ commitAndClose(em);
+ try {
+ Set<MeasurementDataTrait> expectedResult = new HashSet<MeasurementDataTrait>();
+ for (MeasurementData data : expectedResult4) {
+ data.setName(null);
+ expectedResult.add((MeasurementDataTrait) data);
+ }
+ // add the trait data (it stores it in db (without name field))
+ measurementDataManager.addTraitData(expectedResult);
+
+ // get back the trait data
+ List<MeasurementDataTrait> actualResult = measurementDataManager.findTraits(overlord, resource2.getId(), definitionCt2.getId());
+
+ Set<MeasurementData> actualResultSet = new HashSet<MeasurementData>(actualResult);
+ assertEquals(expectedResult, actualResultSet);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ throw e;
+ }
+ }
+
+ @Test
+ public void testAddAndFindTrait3() throws Exception {
+ // prepare DB
+ EntityManager em = beginTx();
+ setupGroupOfResources(em);
+ commitAndClose(em);
+ try {
+ Set<MeasurementDataTrait> traitsData = new HashSet<MeasurementDataTrait>();
+ Set<MeasurementDataTrait> expectedResult = new HashSet<MeasurementDataTrait>();
+ for (MeasurementData data : expectedResult2) {
+ data.setName(null);
+ traitsData.add((MeasurementDataTrait) data);
+ if (data.getScheduleId() == schedule2.getId()){
+ expectedResult.add((MeasurementDataTrait) data);
+ }
+ }
+
+ // add the trait data (it stores it in db (without name field))
+ measurementDataManager.addTraitData(traitsData);
+
+ // get back the trait data
+ List<MeasurementDataTrait> actualResult = measurementDataManager.findTraits(overlord, resource2.getId(), definitionCt2.getId());
+
+ Set<MeasurementData> actualResultSet = new HashSet<MeasurementData>(actualResult);
+ assertEquals(expectedResult, actualResultSet);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ throw e;
+ }
+ }
+
+ @Test
+ public void testFindNonExistentTraitByResourceId() throws Exception {
+ // prepare DB
+ EntityManager em = beginTx();
+ setupGroupOfResources(em);
+ commitAndClose(em);
+ try {
+ // get back the trait data
+ List<MeasurementDataTrait> actualResult = measurementDataManager.findTraits(overlord, resource2.getId(), definitionCt2.getId());
+
+ Set<MeasurementData> actualResultSet = new HashSet<MeasurementData>(actualResult);
+ assertEquals(Collections.<MeasurementData> emptySet(), actualResultSet);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ throw e;
+ }
+ }
+
+
+ /**
+ * This test tests more combination of criteria
+ * @throws Exception
+ */
+ @Test
+ public void testAddAndFindByCriteria() throws Exception {
+ // prepare DB
+ EntityManager em = beginTx();
+ setupGroupOfResources(em);
+ commitAndClose(em);
+ try {
+ Set<MeasurementDataTrait> expectedResult = new HashSet<MeasurementDataTrait>();
+ for (MeasurementData data : expectedResult1) {
+ data.setName(null);
+ expectedResult.add((MeasurementDataTrait) data);
+ }
+ // add the trait data (it stores it in db (without name field))
+ measurementDataManager.addTraitData(expectedResult);
+
+ // get back the trait data by schedule id
+ MeasurementDataTraitCriteria criteria = new MeasurementDataTraitCriteria();
+ criteria.addFilterScheduleId(schedule1.getId());
+ List<MeasurementDataTrait> actualResult = measurementDataManager.findTraitsByCriteria(overlord, criteria);
+ Set<MeasurementData> actualResultSet = new HashSet<MeasurementData>(actualResult);
+ assertEquals(expectedResult, actualResultSet);
+
+ // get back the trait data by resource id
+ criteria = new MeasurementDataTraitCriteria();
+ criteria.addFilterResourceId(resource1.getId());
+ actualResult = measurementDataManager.findTraitsByCriteria(overlord, criteria);
+ actualResultSet = new HashSet<MeasurementData>(actualResult);
+ assertEquals(expectedResult, actualResultSet);
+
+ // get back the trait data by schedule id and resource id
+ criteria = new MeasurementDataTraitCriteria();
+ criteria.addFilterScheduleId(schedule1.getId());
+ criteria.addFilterResourceId(resource1.getId());
+ actualResult = measurementDataManager.findTraitsByCriteria(overlord, criteria);
+ actualResultSet = new HashSet<MeasurementData>(actualResult);
+ assertEquals(expectedResult, actualResultSet);
+
+ // get back the trait data by wrong schedule id
+ criteria = new MeasurementDataTraitCriteria();
+ criteria.addFilterScheduleId(Integer.MIN_VALUE);
+ actualResult = measurementDataManager.findTraitsByCriteria(overlord, criteria);
+ assertTrue(actualResult.isEmpty());
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ throw e;
+ }
+ }
+
+ @Test
+ public void testAddAndFindCurrentTraitByResourceId() throws Exception {
+ // prepare DB
+ EntityManager em = beginTx();
+ setupGroupOfResources(em);
+ commitAndClose(em);
+ try {
+ // get back the trait data
+ List<MeasurementDataTrait> actualResult = measurementDataManager.findCurrentTraitsForResource(overlord, resource1.getId(), null);
+ assertTrue(actualResult.isEmpty());
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ throw e;
+ }
+ }
+
+
+ @Test
+ public void testAddAndFindCurrentTraitByResourceIdAcrossMoreSchedules() throws Exception {
+ // prepare DB
+ EntityManager em = beginTx();
+ setupGroupOfResources(em);
+ commitAndClose(em);
+ try {
+ Set<MeasurementDataTrait> expectedResult = new HashSet<MeasurementDataTrait>();
+ for (MeasurementData data : expectedResult2) {
+ data.setName(null);
+ expectedResult.add((MeasurementDataTrait) data);
+ }
+ // add the trait data (it stores it in db (without name field))
+ measurementDataManager.addTraitData(expectedResult);
+
+ // get back the trait data
+ List<MeasurementDataTrait> actualResult = measurementDataManager.findCurrentTraitsForResource(overlord, resource2.getId(), null);
+
+ Set<MeasurementData> actualResultSet = new HashSet<MeasurementData>(actualResult);
+ assertEquals(expectedResult, actualResultSet);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ throw e;
+ }
+ }
+
+ @Test
+ public void testFindNonExistentCurrentTraitByResourceId() throws Exception {
+ // prepare DB
+ EntityManager em = beginTx();
+ setupGroupOfResources(em);
+ commitAndClose(em);
+ try {
+ Set<MeasurementDataTrait> expectedResult = new HashSet<MeasurementDataTrait>();
+ for (MeasurementData data : expectedResult2) {
+ data.setName(null);
+ expectedResult.add((MeasurementDataTrait) data);
+ }
+ // add the trait data (it stores it in db (without name field))
+ measurementDataManager.addTraitData(expectedResult);
+
+ // get back the trait data
+ List<MeasurementDataTrait> actualResult = measurementDataManager.findCurrentTraitsForResource(overlord, resource2.getId(), null);
+
+ Set<MeasurementData> actualResultSet = new HashSet<MeasurementData>(actualResult);
+ assertEquals(expectedResult, actualResultSet);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ throw e;
+ }
+ }
+
+
+ private MeasurementData makeMeasurement(long time, int scheduleId, String value, String name) {
+ MeasurementData measurement = new MeasurementDataTrait(new MeasurementDataPK(time, scheduleId), value);
+ measurement.setName(name);
+ return measurement;
+ }
+
+ private EntityManager beginTx() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ return em;
+ }
+
+ private void commitAndClose(EntityManager em) throws Exception {
+ em.flush();
+ getTransactionManager().commit();
+ em.close();
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementScheduleManagerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementScheduleManagerTest.java
new file mode 100644
index 0000000..e978521
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementScheduleManagerTest.java
@@ -0,0 +1,366 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.measurement.test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import junit.framework.Assert;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.DisplayType;
+import org.rhq.core.domain.measurement.MeasurementCategory;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementSchedule;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.measurement.ResourceMeasurementScheduleRequest;
+import org.rhq.core.domain.measurement.calltime.CallTimeDataKey;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.measurement.MeasurementConstants;
+import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.ResourceTreeHelper;
+
+/**
+ * Test some measurement schedule handling
+ *
+ * @author Jay Shaughnessy
+ */
+public class MeasurementScheduleManagerTest extends AbstractMeasurementScheduleManagerTest {
+
+ private MeasurementScheduleManagerLocal measurementScheduleManager;
+
+ private Subject overlord;
+
+ private Resource resource1;
+ private MeasurementDefinition definitionCt1;
+ private ResourceType theResourceType;
+ private Agent theAgent;
+ private MeasurementScheduleTestServerCommunicationsService testCommService;
+
+ @BeforeMethod
+ public void beforeMethod() {
+ try {
+ prepareScheduler();
+ testCommService = (MeasurementScheduleTestServerCommunicationsService) prepareForTestAgents();
+
+ this.measurementScheduleManager = LookupUtil.getMeasurementScheduleManager();
+ this.overlord = LookupUtil.getSubjectManager().getOverlord();
+ } catch (Throwable t) {
+ // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
+ // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+
+ @AfterMethod
+ public void afterMethod() {
+ EntityManager em = null;
+
+ try {
+ // delete values
+ em = beginTx();
+
+ // delete keys
+ List<Integer> resourceIds = new ArrayList<Integer>();
+ resourceIds.add(resource1.getId());
+ Query q = em.createNamedQuery(CallTimeDataKey.QUERY_DELETE_BY_RESOURCES);
+ q.setParameter("resourceIds", resourceIds);
+ q.executeUpdate();
+
+ resource1 = em.merge(resource1);
+ for (MeasurementSchedule sched : resource1.getSchedules()) {
+ em.remove(sched);
+ }
+ ResourceTreeHelper.deleteResource(em, resource1);
+
+ definitionCt1 = em.merge(definitionCt1);
+ em.remove(definitionCt1);
+
+ theResourceType = em.merge(theResourceType);
+ em.remove(theResourceType);
+
+ theAgent = em.merge(theAgent);
+ em.remove(theAgent);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ } finally {
+ try {
+ unprepareScheduler();
+ unprepareForTestAgents();
+ } catch (Exception e) {
+ }
+
+ commitAndClose(em);
+ }
+
+ }
+
+ @Test
+ public void testIntervals() {
+
+ EntityManager em = null;
+
+ try {
+ em = beginTx();
+
+ setupResources(em);
+
+ MeasurementSchedule schedule1 = new MeasurementSchedule(definitionCt1, resource1);
+ em.persist(schedule1);
+ definitionCt1.addSchedule(schedule1);
+ resource1.addSchedule(schedule1);
+ resource1 = em.merge(resource1);
+
+ commitAndClose(em);
+ em = null;
+
+ // 60s is valid
+ schedule1.setInterval(60000L);
+ measurementScheduleManager.updateSchedule(overlord, schedule1);
+ schedule1 = measurementScheduleManager.getScheduleById(overlord, schedule1.getId());
+ Assert.assertEquals(60000L, schedule1.getInterval());
+
+ // 10s is invalid and should be assigned 30s
+ schedule1.setInterval(10000L);
+ measurementScheduleManager.updateSchedule(overlord, schedule1);
+ schedule1 = measurementScheduleManager.getScheduleById(overlord, schedule1.getId());
+ Assert.assertEquals(MeasurementConstants.MINIMUM_COLLECTION_INTERVAL_MILLIS, schedule1.getInterval());
+
+ // 0s is invalid and should be assigned 30s
+ schedule1.setInterval(0L);
+ measurementScheduleManager.updateSchedule(overlord, schedule1);
+ schedule1 = measurementScheduleManager.getScheduleById(overlord, schedule1.getId());
+ Assert.assertEquals(MeasurementConstants.MINIMUM_COLLECTION_INTERVAL_MILLIS, schedule1.getInterval());
+
+ // negative intervals are invalid and should be assigned 30s
+ schedule1.setInterval(-60000L);
+ measurementScheduleManager.updateSchedule(overlord, schedule1);
+ schedule1 = measurementScheduleManager.getScheduleById(overlord, schedule1.getId());
+ Assert.assertEquals(MeasurementConstants.MINIMUM_COLLECTION_INTERVAL_MILLIS, schedule1.getInterval());
+
+ // Try a different mechanism
+
+ // 60s is valid
+ measurementScheduleManager.updateSchedulesForResource(overlord, resource1.getId(),
+ new int[] { definitionCt1.getId() }, 60000L);
+ Set<ResourceMeasurementScheduleRequest> resScheds = measurementScheduleManager
+ .findSchedulesForResourceAndItsDescendants(new int[] { resource1.getId() }, false);
+ Assert.assertEquals(1, resScheds.size());
+ Set<MeasurementScheduleRequest> scheds = resScheds.iterator().next().getMeasurementSchedules();
+ Assert.assertEquals(1, scheds.size());
+ Assert.assertEquals(60000L, scheds.iterator().next().getInterval());
+
+ // 10s is invalid and should be assigned 30s
+ measurementScheduleManager.updateSchedulesForResource(overlord, resource1.getId(),
+ new int[] { definitionCt1.getId() }, 10000L);
+ resScheds = measurementScheduleManager.findSchedulesForResourceAndItsDescendants(
+ new int[] { resource1.getId() }, false);
+ Assert.assertEquals(1, resScheds.size());
+ scheds = resScheds.iterator().next().getMeasurementSchedules();
+ Assert.assertEquals(1, scheds.size());
+ Assert.assertEquals(MeasurementConstants.MINIMUM_COLLECTION_INTERVAL_MILLIS, scheds.iterator().next()
+ .getInterval());
+
+ // 0s is invalid and should be assigned 30s
+ measurementScheduleManager.updateSchedulesForResource(overlord, resource1.getId(),
+ new int[] { definitionCt1.getId() }, 0L);
+ resScheds = measurementScheduleManager.findSchedulesForResourceAndItsDescendants(
+ new int[] { resource1.getId() }, false);
+ Assert.assertEquals(1, resScheds.size());
+ scheds = resScheds.iterator().next().getMeasurementSchedules();
+ Assert.assertEquals(1, scheds.size());
+ Assert.assertEquals(MeasurementConstants.MINIMUM_COLLECTION_INTERVAL_MILLIS, scheds.iterator().next()
+ .getInterval());
+
+ // negative intervals are invalid and should be assigned 30s
+ measurementScheduleManager.updateSchedulesForResource(overlord, resource1.getId(),
+ new int[] { definitionCt1.getId() }, -60000L);
+ resScheds = measurementScheduleManager.findSchedulesForResourceAndItsDescendants(
+ new int[] { resource1.getId() }, false);
+ Assert.assertEquals(1, resScheds.size());
+ scheds = resScheds.iterator().next().getMeasurementSchedules();
+ Assert.assertEquals(1, scheds.size());
+ Assert.assertEquals(MeasurementConstants.MINIMUM_COLLECTION_INTERVAL_MILLIS, scheds.iterator().next()
+ .getInterval());
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ Assert.fail();
+
+ } finally {
+ commitAndClose(em);
+ }
+ }
+
+ @Test
+ public void testBug811696() {
+
+ EntityManager em = null;
+
+ try {
+ em = beginTx();
+
+ setupResources(em);
+ long defaultInterval = definitionCt1.getDefaultInterval();
+ long updatedInterval = defaultInterval * 2;
+
+ // first, establish a schedule for the test resource
+ MeasurementSchedule schedule1 = new MeasurementSchedule(definitionCt1, resource1);
+ schedule1.setInterval(defaultInterval);
+ em.persist(schedule1);
+ definitionCt1.addSchedule(schedule1);
+ resource1.addSchedule(schedule1);
+ resource1 = em.merge(resource1);
+
+ commitAndClose(em);
+ em = null;
+
+ // Test interval update of metrics at the template level
+ testCommService.init();
+
+ testCommService.setExpectedInterval(updatedInterval);
+ testCommService.setExpectedIsEnabled(true);
+
+ measurementScheduleManager.updateSchedulesForResourceType(overlord, new int[] { definitionCt1.getId() },
+ updatedInterval, true);
+ Assert.assertTrue(testCommService.isTested());
+ if (testCommService.hasFailures()) {
+ Assert.fail(testCommService.getFailures().get(0));
+ }
+
+ Set<ResourceMeasurementScheduleRequest> resScheds = measurementScheduleManager
+ .findSchedulesForResourceAndItsDescendants(new int[] { resource1.getId() }, false);
+ Assert.assertEquals(1, resScheds.size());
+ ResourceMeasurementScheduleRequest rmsr = resScheds.iterator().next();
+ Set<MeasurementScheduleRequest> scheds = rmsr.getMeasurementSchedules();
+ Assert.assertEquals(1, scheds.size());
+ MeasurementScheduleRequest msr = scheds.iterator().next();
+ Assert.assertEquals(updatedInterval, msr.getInterval());
+ Assert.assertEquals(true, msr.isEnabled());
+
+ // Test disable of metrics at the template level, this should have no effect on the interval in the client
+ // or in the db
+ testCommService.init();
+
+ testCommService.setExpectedInterval(updatedInterval);
+ testCommService.setExpectedIsEnabled(false);
+
+ measurementScheduleManager.disableSchedulesForResourceType(overlord, new int[] { definitionCt1.getId() },
+ true);
+ Assert.assertTrue(testCommService.isTested());
+
+ resScheds = measurementScheduleManager.findSchedulesForResourceAndItsDescendants(
+ new int[] { resource1.getId() }, false);
+ Assert.assertEquals(1, resScheds.size());
+ rmsr = resScheds.iterator().next();
+ scheds = rmsr.getMeasurementSchedules();
+ Assert.assertEquals(1, scheds.size());
+ msr = scheds.iterator().next();
+ Assert.assertEquals(updatedInterval, msr.getInterval());
+ Assert.assertEquals(false, msr.isEnabled());
+
+ // Test enable of metrics at the template level, this should have no effect on the interval in the client
+ // or in the db
+ testCommService.init();
+
+ testCommService.setExpectedInterval(updatedInterval);
+ testCommService.setExpectedIsEnabled(false);
+
+ measurementScheduleManager.enableSchedulesForResourceType(overlord, new int[] { definitionCt1.getId() },
+ true);
+ Assert.assertTrue(testCommService.isTested());
+
+ resScheds = measurementScheduleManager.findSchedulesForResourceAndItsDescendants(
+ new int[] { resource1.getId() }, false);
+ Assert.assertEquals(1, resScheds.size());
+ rmsr = resScheds.iterator().next();
+ scheds = rmsr.getMeasurementSchedules();
+ Assert.assertEquals(1, scheds.size());
+ msr = scheds.iterator().next();
+ Assert.assertEquals(updatedInterval, msr.getInterval());
+ Assert.assertEquals(true, msr.isEnabled());
+
+ } catch (Exception e) {
+ Assert.fail(e.getMessage());
+
+ } finally {
+ commitAndClose(em);
+ }
+ }
+
+ /**
+ * Just set up two resources plus measurement definitions
+ *
+ * @param em The EntityManager to use
+ *
+ */
+ private void setupResources(EntityManager em) {
+ theAgent = new Agent("testagent", "localhost", 1234, "", "randomToken");
+ em.persist(theAgent);
+
+ theResourceType = new ResourceType("test-plat", "test-plugin", ResourceCategory.PLATFORM, null);
+ em.persist(theResourceType);
+
+ definitionCt1 = new MeasurementDefinition("CT-Def1", MeasurementCategory.PERFORMANCE,
+ MeasurementUnits.MILLISECONDS, DataType.MEASUREMENT, true, 120000L, DisplayType.SUMMARY);
+ definitionCt1.setResourceType(theResourceType);
+ em.persist(definitionCt1);
+
+ resource1 = new Resource("test-platform-key1", "test-platform-name", theResourceType);
+ resource1.setUuid("" + new Random().nextInt());
+ resource1.setAgent(theAgent);
+ em.persist(resource1);
+ }
+
+ private EntityManager beginTx() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ return em;
+ }
+
+ private void commitAndClose(EntityManager em) {
+ try {
+ if (null != em) {
+ em.flush();
+ getTransactionManager().commit();
+ em.close();
+ }
+ } catch (Throwable t) {
+
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementViewManagerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementViewManagerTest.java
new file mode 100644
index 0000000..285e2ce
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementViewManagerTest.java
@@ -0,0 +1,142 @@
+package org.rhq.enterprise.server.measurement.test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementSchedule;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.measurement.MeasurementViewManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.ResourceTreeHelper;
+
+public class MeasurementViewManagerTest extends AbstractEJB3Test {
+
+ private MeasurementViewManagerLocal viewManager;
+ private SubjectManagerLocal subjectManager;
+
+ private static final int SIZE = 5;
+
+ private ResourceType type;
+ private List<Resource> resources;
+ private List<MeasurementDefinition> definitions;
+ private List<MeasurementSchedule> schedules;
+
+ private Subject overlord;
+
+ @Test
+ public void testAll() {
+ // TODO: jmarques - write unit tests for MeasurementViewManager
+ }
+
+ @BeforeMethod
+ public void init() throws Exception {
+ viewManager = LookupUtil.getMeasurementViewManager();
+ subjectManager = LookupUtil.getSubjectManager();
+
+ overlord = subjectManager.getOverlord();
+
+ getTransactionManager().begin();
+ try {
+ EntityManager em = getEntityManager();
+
+ String prefix = MeasurementViewManagerTest.class.getSimpleName();
+
+ type = new ResourceType(prefix + "type", prefix + "plugin", ResourceCategory.PLATFORM, null);
+ em.persist(type);
+
+ resources = new ArrayList<Resource>();
+ for (int i = 0; i < SIZE; i++) {
+ Resource resource = new Resource(prefix + "key " + i, prefix + "key " + i, type);
+ resource.setUuid(resource.getResourceKey());
+ resources.add(resource);
+ em.persist(resource);
+ }
+
+ definitions = new ArrayList<MeasurementDefinition>();
+ for (int i = 0; i < SIZE; i++) {
+ MeasurementDefinition definition = new MeasurementDefinition(type, prefix + "definition " + i);
+ definitions.add(definition);
+ type.addMetricDefinition(definition);
+ em.persist(definition);
+ }
+ type = em.merge(type);
+
+ schedules = new ArrayList<MeasurementSchedule>();
+ for (int i = 0; i < SIZE; i++) {
+ for (int j = 0; j < SIZE; j++) {
+ MeasurementDefinition definition = definitions.get(i);
+ Resource resource = resources.get(j);
+ MeasurementSchedule schedule = new MeasurementSchedule(definition, resource);
+ schedules.add(schedule);
+ definition.addSchedule(schedule);
+ resource.addSchedule(schedule);
+ em.persist(schedule);
+ }
+ }
+ for (int i = 0; i < SIZE; i++) {
+ MeasurementDefinition definition = definitions.get(i);
+ definitions.set(i, em.merge(definition));
+ }
+ for (int j = 0; j < SIZE; j++) {
+ Resource resource = resources.get(j);
+ resources.set(j, em.merge(resource));
+ }
+ } finally {
+ getTransactionManager().commit();
+ }
+ }
+
+ @AfterMethod
+ public void afterTest() throws Exception {
+ getTransactionManager().begin();
+ try {
+ EntityManager em = getEntityManager();
+
+ List<Integer> measurementDefinitionIds = new ArrayList<Integer>();
+ for (int i = 0; i < definitions.size(); i++) {
+ measurementDefinitionIds.add(definitions.get(i).getId());
+ }
+ Query removeSchedules = em
+ .createQuery("delete from MeasurementSchedule ms where ms.definition.id IN ( :ids ) ");
+ removeSchedules.setParameter("ids", measurementDefinitionIds);
+ removeSchedules.executeUpdate();
+
+ List<Integer> resourceIds = new ArrayList<Integer>();
+ for (int i = 0; i < resources.size(); i++) {
+ resourceIds.add(resources.get(i).getId());
+ }
+ if (type != null) {
+ Query removeDefinitions = em
+ .createQuery("delete from MeasurementDefinition md where md.resourceType.id = :resourceTypeId ");
+ removeDefinitions.setParameter("resourceTypeId", type.getId());
+ removeDefinitions.executeUpdate();
+ }
+
+ for (int resourceId : resourceIds) {
+ Resource r = em.find(Resource.class, resourceId);
+ ResourceTreeHelper.deleteResource(em, r);
+ }
+
+ if (type != null) {
+ type = em.find(ResourceType.class, type.getId());
+ em.remove(type);
+ }
+ } finally {
+ getTransactionManager().commit();
+ }
+
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/operation/OperationManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/operation/OperationManagerBeanTest.java
new file mode 100644
index 0000000..f3b1f91
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/operation/OperationManagerBeanTest.java
@@ -0,0 +1,1708 @@
+/*
+ * 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.enterprise.server.operation;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Random;
+
+import javax.ejb.EJBException;
+import javax.persistence.EntityManager;
+
+import org.quartz.SimpleTrigger;
+import org.quartz.Trigger;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.agent.PluginContainerException;
+import org.rhq.core.clientapi.agent.operation.CancelResults;
+import org.rhq.core.clientapi.agent.operation.CancelResults.InterruptedState;
+import org.rhq.core.clientapi.agent.operation.OperationAgentService;
+import org.rhq.core.clientapi.server.operation.OperationServerService;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.operation.GroupOperationHistory;
+import org.rhq.core.domain.operation.OperationDefinition;
+import org.rhq.core.domain.operation.OperationRequestStatus;
+import org.rhq.core.domain.operation.ResourceOperationHistory;
+import org.rhq.core.domain.operation.bean.GroupOperationSchedule;
+import org.rhq.core.domain.operation.bean.ResourceOperationSchedule;
+import org.rhq.core.domain.operation.composite.GroupOperationLastCompletedComposite;
+import org.rhq.core.domain.operation.composite.GroupOperationScheduleComposite;
+import org.rhq.core.domain.operation.composite.ResourceOperationLastCompletedComposite;
+import org.rhq.core.domain.operation.composite.ResourceOperationScheduleComposite;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.InventoryStatus;
+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.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.core.util.exception.ExceptionPackage;
+import org.rhq.enterprise.server.authz.PermissionException;
+import org.rhq.enterprise.server.configuration.ConfigurationManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
+import org.rhq.enterprise.server.scheduler.SchedulerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Test for {@link OperationManagerBean} SLSB.
+ */
+@Test(groups = "operation.manager")
+public class OperationManagerBeanTest extends AbstractEJB3Test {
+
+ private static final boolean ENABLE_TESTS = true;
+
+ private ConfigurationManagerLocal configurationManager;
+ private OperationManagerLocal operationManager;
+ private SchedulerLocal schedulerManager;
+ private Subject overlord;
+ private Resource newResource;
+ private OperationDefinition newOperation;
+ private ResourceGroup newGroup;
+ private OperationServerService operationServerService;
+
+ // defines the behavior of the simulated agent
+ // Sleep - if more than 0, the amount of milliseconds the agent sleeps
+ // Timeout - if true, the operation will fail due to a "timeout"
+ // Error - if not null, the operation will fail with this as the error message
+ private long simulatedOperation_Sleep;
+ private boolean simulatedOperation_Timeout;
+ private String simulatedOperation_Error;
+
+ // for those tests that cancel an operation, this will be the results of the simulated cancellation
+ private CancelResults simulatedOperation_CancelResults;
+
+ /**
+ * Prepares things for the entire test class.
+ */
+ @BeforeClass
+ public void beforeClass() {
+ configurationManager = LookupUtil.getConfigurationManager();
+ operationManager = LookupUtil.getOperationManager();
+ schedulerManager = LookupUtil.getSchedulerBean();
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ operationServerService = new OperationServerServiceImpl();
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void afterClass() {
+ operationServerService = null;
+ }
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ TestServerCommunicationsService agentServiceContainer = prepareForTestAgents();
+ agentServiceContainer.operationService = new TestConfigService();
+
+ prepareScheduler();
+
+ simulatedOperation_Sleep = 500L;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Error = null;
+
+ newResource = createNewResource();
+ newOperation = newResource.getResourceType().getOperationDefinitions().iterator().next();
+ newGroup = newResource.getExplicitGroups().iterator().next();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ try {
+ deleteNewResource(newResource);
+ } finally {
+ unprepareForTestAgents();
+ unprepareScheduler();
+ }
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testSchedulerCustomProperties() throws Exception {
+ // our test scheduler configuration defines a custom timeout for all operations
+ assert schedulerManager.getDefaultOperationTimeout() != null;
+ assert schedulerManager.getDefaultOperationTimeout() == 5;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testTrueTimeout() throws Exception {
+ Resource resource = newResource;
+
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 20000L; // the operation timeout is defined at 10 seconds, we'll block it for 20s
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date(System.currentTimeMillis() + 5000L));
+ ResourceOperationSchedule schedule = operationManager.scheduleResourceOperation(overlord, resource.getId(),
+ "testOp", null, trigger, "desc");
+ List<ResourceOperationSchedule> schedules;
+ schedules = operationManager.findScheduledResourceOperations(overlord, resource.getId());
+ assert schedules != null;
+ assert schedules.size() == 1;
+
+ Thread.sleep(17000L); // wait for it to timeout
+
+ // this will change all INPROGRESS histories that have timed out to FAILURE
+ operationManager.checkForTimedOutOperations(overlord);
+
+ PageList<ResourceOperationHistory> results;
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ ResourceOperationHistory history = results.get(0);
+ System.out.println("~~~~~~~~~~~~~~~~~" + history);
+ assert history.getErrorMessage() != null : history;
+ assert history.getErrorMessage().indexOf("Timed out") > -1 : history;
+ assert history.getStatus() == OperationRequestStatus.FAILURE : history;
+
+ operationManager.deleteOperationHistory(overlord, history.getId(), false);
+
+ // make sure it was purged
+ results = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0;
+
+ // nothing to unschedule really
+
+ // but lets prove to ourselves that it isn't scheduled anymore (because it executed)
+ schedules = operationManager.findScheduledResourceOperations(overlord, resource.getId());
+ assert schedules != null;
+ assert schedules.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testUnscheduledGroupOperation() throws Exception {
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 0L;
+
+ // let the trigger not fire until several seconds from now so we can query the schedule itself
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date(System.currentTimeMillis() + 10000L));
+ GroupOperationSchedule schedule = operationManager.scheduleGroupOperation(overlord, newGroup.getId(), null,
+ true, "testOp", null, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() == null;
+ assert schedule.getGroup().getId() == newGroup.getId();
+
+ List<GroupOperationSchedule> schedules;
+ schedules = operationManager.findScheduledGroupOperations(overlord, newGroup.getId());
+ assert schedules != null;
+ assert schedules.size() == 1;
+ GroupOperationSchedule returnedSchedule = schedules.get(0);
+ assert returnedSchedule.getSubject().equals(overlord);
+ assert returnedSchedule.getGroup().getId() == newGroup.getId();
+ assert returnedSchedule.getParameters() == null;
+ assert returnedSchedule.getOperationName().equals("testOp");
+ assert returnedSchedule.getDescription().equals("desc");
+
+ // let's immediately unschedule it before it triggers
+ operationManager.unscheduleGroupOperation(overlord, returnedSchedule.getJobId().toString(), returnedSchedule
+ .getGroup().getId());
+
+ PageList<GroupOperationHistory> results;
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results.size() == 0;
+
+ // should be no resource histories that belong to it
+ PageList<ResourceOperationHistory> results2;
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results2 != null;
+ assert results2.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testUnscheduledGroupOperationWithParameters() throws Exception {
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 0L;
+
+ Configuration params = new Configuration();
+ params.put(new PropertySimple("param1", "group-test"));
+ params.put(new PropertySimple("param2", "blah"));
+
+ // let the trigger not fire until several seconds from now so we can query the schedule itself
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date(System.currentTimeMillis() + 3600000L));
+ GroupOperationSchedule schedule = operationManager.scheduleGroupOperation(overlord, newGroup.getId(), null,
+ true, "testOp", params, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() != null;
+ assert schedule.getGroup().getId() == newGroup.getId();
+
+ int configId = params.getId();
+ Configuration returnedConfiguration = configurationManager.getConfigurationById(configId);
+ assert returnedConfiguration.getProperties().size() == 2;
+ assert returnedConfiguration.getSimple("param1").getStringValue().equals("group-test");
+ assert returnedConfiguration.getSimple("param2").getStringValue().equals("blah");
+
+ List<GroupOperationSchedule> schedules;
+ schedules = operationManager.findScheduledGroupOperations(overlord, newGroup.getId());
+ assert schedules != null;
+ assert schedules.size() == 1;
+ GroupOperationSchedule returnedSchedule = schedules.get(0);
+ assert returnedSchedule.getSubject().equals(overlord);
+ assert returnedSchedule.getGroup().getId() == newGroup.getId();
+ assert returnedSchedule.getParameters() != null;
+ assert returnedSchedule.getOperationName().equals("testOp");
+ assert returnedSchedule.getDescription().equals("desc");
+
+ PageList<GroupOperationScheduleComposite> list;
+ list = operationManager.findCurrentlyScheduledGroupOperations(overlord, PageControl.getUnlimitedInstance());
+ assert list.size() == 1;
+ assert list.get(0).getGroupId() == newGroup.getId();
+ assert list.get(0).getGroupName().equals(newGroup.getName());
+ assert list.get(0).getOperationName().equals("Test Operation");
+
+ // let's immediately unschedule it before it triggers
+ operationManager.unscheduleGroupOperation(overlord, returnedSchedule.getJobId().toString(), returnedSchedule
+ .getGroup().getId());
+
+ list = operationManager.findCurrentlyScheduledGroupOperations(overlord, PageControl.getUnlimitedInstance());
+ assert list.size() == 0;
+
+ PageList<GroupOperationHistory> results;
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results.size() == 0;
+
+ // should be no resource histories that belong to it
+ PageList<ResourceOperationHistory> results2;
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results2 != null;
+ assert results2.size() == 0;
+
+ // should be no dangling configuration entities representing group operation parameters
+ Configuration returnedConfiguration2 = configurationManager.getConfigurationById(configId);
+ assert returnedConfiguration2 == null;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetScheduledGroupOperations() throws Exception {
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 0L;
+
+ // let the trigger not fire until several seconds from now so we can query the schedule itself
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date(System.currentTimeMillis() + 5000L));
+ GroupOperationSchedule schedule = operationManager.scheduleGroupOperation(overlord, newGroup.getId(), null,
+ true, "testOp", null, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() == null;
+ assert schedule.getGroup().getId() == newGroup.getId();
+
+ List<GroupOperationSchedule> schedules;
+ schedules = operationManager.findScheduledGroupOperations(overlord, newGroup.getId());
+ assert schedules != null;
+ assert schedules.size() == 1;
+ GroupOperationSchedule returnedSchedule = schedules.get(0);
+ assert returnedSchedule.getSubject().equals(overlord);
+ assert returnedSchedule.getGroup().getId() == newGroup.getId();
+ assert returnedSchedule.getParameters() == null;
+ assert returnedSchedule.getOperationName().equals("testOp");
+ assert returnedSchedule.getDescription().equals("desc");
+
+ Thread.sleep(9000L); // wait for it to be triggered and finish
+
+ PageList<GroupOperationHistory> results;
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results.size() == 1 : "Expected 1 result, but got " + results.size();
+
+ operationManager.deleteOperationHistory(overlord, results.get(0).getId(), false);
+
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results.size() == 0;
+
+ // purging group history purges all resource histories that belong to it
+ PageList<ResourceOperationHistory> results2;
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results2 != null;
+ assert results2.size() == 0;
+
+ // see that it isn't scheduled anymore
+ schedules = operationManager.findScheduledGroupOperations(overlord, newGroup.getId());
+ assert schedules != null;
+ assert schedules.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testCancelGroupOperation() throws Exception {
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 30000L;
+ simulatedOperation_CancelResults = new CancelResults(InterruptedState.RUNNING);
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date());
+ operationManager.scheduleGroupOperation(overlord, newGroup.getId(), new int[] { newResource.getId() }, true,
+ "testOp", null, trigger, "desc");
+
+ PageList<GroupOperationHistory> results = null;
+
+ // wait for it to be triggered so we get a history item
+ for (int i = 0; i < 5; i++) {
+ Thread.sleep(1000L);
+ results = operationManager.findPendingGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ if ((results != null) && (results.size() > 0)) {
+ break; // operation was triggered - got the history item
+ }
+ }
+
+ assert results != null;
+ assert results.size() == 1 : "-->" + results;
+ GroupOperationHistory history = results.get(0);
+ assert history.getStatus() == OperationRequestStatus.INPROGRESS : history;
+
+ // get the one resource history from the group
+ PageList<ResourceOperationHistory> results2 = null;
+
+ for (int i = 0; i < 5; i++) {
+ Thread.sleep(1000L);
+ results2 = operationManager.findPendingResourceOperationHistories(overlord, newResource.getId(),
+ PageControl.getUnlimitedInstance());
+ if ((results2 != null) && (results2.size() > 0)) {
+ break; // operation was triggered - got the history item
+ }
+ }
+
+ assert results2.size() == 1 : "Should have had 1 resource history result: " + results2;
+
+ ResourceOperationHistory rHistory = results2.get(0);
+ assert rHistory.getStatus() == OperationRequestStatus.INPROGRESS : rHistory;
+
+ // cancel the group history - which cancels all the resource histories
+ operationManager.cancelOperationHistory(overlord, history.getId(), false);
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 1;
+ assert results.get(0).getStatus() == OperationRequestStatus.CANCELED : results.get(0);
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results2.size() == 1 : "Should have had 1 resource history result: " + results2;
+ assert results2.get(0).getStatus() == OperationRequestStatus.CANCELED : results2.get(0);
+
+ // try to cancel it again, just to make sure it blows up appropriately
+ try {
+ operationManager.cancelOperationHistory(overlord, history.getId(), false);
+ assert false : "Should not have been able to cancel an operation that is not INPROGRESS";
+ } catch (EJBException expected) {
+ // expected
+ }
+
+ // purge the group history
+ operationManager.deleteOperationHistory(overlord, history.getId(), false);
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0; // none left, we purged the only group history there was
+
+ // purging group history purges all resource histories that belong to it
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results2 != null;
+ assert results2.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testCancelUncancelableGroupOperation() throws Exception {
+ // this test will attempt to cancel an operation that has already finished, in effect
+ // trying to cancel an uncancelable operation. This simulates the situation when
+ // an agent has finished running an operation but it has not yet sent the "success"
+ // or "failed" message to the server. So on the agent side it is finished, but the
+ // server side still thinks its INPROGRESS.
+
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 30000L;
+ simulatedOperation_CancelResults = new CancelResults(InterruptedState.FINISHED);
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date());
+ operationManager.scheduleGroupOperation(overlord, newGroup.getId(), new int[] { newResource.getId() }, true,
+ "testOp", null, trigger, "desc");
+
+ PageList<GroupOperationHistory> results = null;
+
+ // wait for it to be triggered so we get a history item
+ for (int i = 0; i < 5; i++) {
+ Thread.sleep(1000L);
+ results = operationManager.findPendingGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ if ((results != null) && (results.size() > 0)) {
+ break; // operation was triggered - got the history item
+ }
+ }
+
+ assert results != null;
+ assert results.size() == 1;
+ GroupOperationHistory history = results.get(0);
+ assert history.getStatus() == OperationRequestStatus.INPROGRESS : history;
+
+ // get the one resource history from the group
+ PageList<ResourceOperationHistory> results2;
+ results2 = operationManager.findPendingResourceOperationHistories(overlord, newResource.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results2.size() == 1 : "Should have had 1 resource history result: " + results2;
+
+ ResourceOperationHistory rHistory = results2.get(0);
+ assert rHistory.getStatus() == OperationRequestStatus.INPROGRESS : rHistory;
+
+ // cancel the group history - but we'll see that even though the group history will say canceled,
+ // this doesn't actually cancel the FINISHED resource operation. This simulates the fact that
+ // the agent couldn't cancel the resource op since it already finished.
+ operationManager.cancelOperationHistory(overlord, history.getId(), false);
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results.size() == 1;
+ assert results.get(0).getStatus() == OperationRequestStatus.CANCELED : results.get(0);
+
+ results = operationManager.findPendingGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results.size() == 0;
+
+ // still pending - our operation wasn't really canceled - waiting for the agent to tell us its finished
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results2.size() == 0;
+ results2 = operationManager.findPendingResourceOperationHistories(overlord, newResource.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results2.size() == 1;
+ assert results2.get(0).getStatus() == OperationRequestStatus.INPROGRESS : results2.get(0);
+
+ // purge the group history (note we tell it to even purge those in progress)
+ operationManager.deleteOperationHistory(overlord, history.getId(), true);
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0; // none left, we purged the only group history there was
+
+ // purging group history purges all resource histories that belong to it
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results2 != null;
+ assert results2.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testScheduleGroupOperation() throws Exception {
+ // make it a success
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 0L;
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date());
+ GroupOperationSchedule schedule = operationManager.scheduleGroupOperation(overlord, newGroup.getId(),
+ new int[] { newResource.getId() }, true, "testOp", null, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() == null;
+ assert schedule.getGroup().getId() == newGroup.getId();
+
+ Thread.sleep(4000L); // wait for it to finish, should be fast
+
+ PageList<GroupOperationHistory> results;
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 1;
+ GroupOperationHistory history = results.get(0);
+ assert history.getId() > 0 : history;
+ assert history.getJobId() != null : history;
+ assert history.getJobName() != null : history;
+ assert history.getJobGroup() != null : history;
+ assert history.getErrorMessage() == null : history;
+ assert history.getStatus() == OperationRequestStatus.SUCCESS : history;
+ assert history.getSubjectName().equals(overlord.getName()) : history;
+
+ PageList<GroupOperationLastCompletedComposite> list;
+ list = operationManager.findRecentlyCompletedGroupOperations(overlord, PageControl.getUnlimitedInstance());
+ assert list.size() == 1;
+ assert list.get(0).getOperationHistoryId() == history.getId();
+ assert list.get(0).getGroupId() == newGroup.getId();
+ assert list.get(0).getGroupName().equals(newGroup.getName());
+ assert list.get(0).getOperationName().equals("Test Operation");
+
+ // get the one resource history from the group
+ PageList<ResourceOperationHistory> results2;
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results2.size() == 1 : "Should have had 1 result: " + results2;
+
+ ResourceOperationHistory rHistory = results2.get(0);
+ assert rHistory.getId() > 0 : rHistory;
+ assert rHistory.getJobId() != null : rHistory;
+ assert rHistory.getJobName() != null : rHistory;
+ assert rHistory.getJobGroup() != null : rHistory;
+ assert rHistory.getErrorMessage() == null : rHistory;
+ assert rHistory.getStatus() == OperationRequestStatus.SUCCESS : rHistory;
+ assert rHistory.getSubjectName().equals(overlord.getName()) : rHistory;
+
+ operationManager.deleteOperationHistory(overlord, history.getId(), false);
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0; // none left, we purged the only group history there was
+
+ // purging group history purges all resource histories that belong to it
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results2 != null;
+ assert results2.size() == 0;
+
+ list = operationManager.findRecentlyCompletedGroupOperations(overlord, PageControl.getUnlimitedInstance());
+ assert list.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testScheduleGroupOperationRecurring() throws Exception {
+ // make it a success
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 0L;
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", 1, 2000L);
+ GroupOperationSchedule schedule = operationManager.scheduleGroupOperation(overlord, newGroup.getId(),
+ new int[] { newResource.getId() }, true, "testOp", null, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() == null;
+ assert schedule.getGroup().getId() == newGroup.getId();
+
+ Thread.sleep(8000L); // wait for it to finish, should be fast
+
+ PageList<GroupOperationHistory> results;
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+
+ // the group job executed twice
+ assert results != null;
+ assert results.size() == 2 : results;
+ GroupOperationHistory history0 = results.get(0);
+ GroupOperationHistory history1 = results.get(1);
+ assert history0.getId() > 0 : history0;
+ assert history0.getJobId() != null : history0;
+ assert history0.getJobName() != null : history0;
+ assert history0.getJobGroup() != null : history0;
+ assert history0.getErrorMessage() == null : history0;
+ assert history0.getStatus() == OperationRequestStatus.SUCCESS : history0;
+ assert history0.getSubjectName().equals(overlord.getName()) : history0;
+ assert history1.getId() > 0 : history1;
+ assert history1.getId() != history0.getId() : history1;
+ assert history1.getJobId() != null : history1;
+ assert !history1.getJobId().equals(history0.getJobId()) : history1;
+ assert history1.getJobName() != null : history1;
+ assert history1.getJobGroup() != null : history1;
+ assert history1.getErrorMessage() == null : history1;
+ assert history1.getStatus() == OperationRequestStatus.SUCCESS : history1;
+ assert history1.getSubjectName().equals(overlord.getName()) : history1;
+
+ // get the one resource's two history items from the group (resource executed once per group trigger)
+ PageList<ResourceOperationHistory> results2;
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results2.size() == 2 : "Should have had 2 results since it was triggered twice: " + results2;
+
+ ResourceOperationHistory rHistory0 = results2.get(0);
+ assert rHistory0.getId() > 0 : rHistory0;
+ assert rHistory0.getJobId() != null : rHistory0;
+ assert rHistory0.getJobName() != null : rHistory0;
+ assert rHistory0.getJobGroup() != null : rHistory0;
+ assert rHistory0.getErrorMessage() == null : rHistory0;
+ assert rHistory0.getStatus() == OperationRequestStatus.SUCCESS : rHistory0;
+ assert rHistory0.getSubjectName().equals(overlord.getName()) : rHistory0;
+
+ ResourceOperationHistory rHistory1 = results2.get(1);
+ assert rHistory1.getId() > 0 : rHistory1;
+ assert rHistory1.getId() != rHistory0.getId() : rHistory1;
+ assert rHistory1.getJobId() != null : rHistory1;
+ assert !rHistory1.getJobId().equals(rHistory0.getJobId()) : rHistory1;
+ assert rHistory1.getJobId().getJobGroup().equals(rHistory1.getJobGroup()) : rHistory1;
+ assert rHistory1.getJobId().getJobName().equals(rHistory1.getJobName()) : rHistory1;
+ assert rHistory1.getJobName() != null : rHistory1;
+ assert rHistory1.getJobGroup() != null : rHistory1;
+ assert rHistory1.getJobGroup().equals(rHistory0.getJobGroup()) : rHistory1;
+ assert rHistory1.getErrorMessage() == null : rHistory1;
+ assert rHistory1.getStatus() == OperationRequestStatus.SUCCESS : rHistory1;
+ assert rHistory1.getSubjectName().equals(overlord.getName()) : rHistory1;
+
+ operationManager.deleteOperationHistory(overlord, history0.getId(), false);
+ operationManager.deleteOperationHistory(overlord, history1.getId(), false);
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0 : results; // none left, we purged the two group histories
+
+ // purging group history purges all resource histories that belong to it
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results2 != null;
+ assert results2.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testScheduleGroupOperationWithParameters() throws Exception {
+ // make it a success
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 0L;
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date());
+ Configuration params = new Configuration();
+ params.put(new PropertySimple("param1", "group-test"));
+ params.put(new PropertySimple("param2", "blah"));
+
+ // the manager will ignore duplicates in the list - we put dups in here to
+ // test the comma-separator parser in the manager
+ int[] order = new int[] { newResource.getId(), newResource.getId() };
+
+ GroupOperationSchedule schedule = operationManager.scheduleGroupOperation(overlord, newGroup.getId(), order,
+ true, "testOp", params, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() != null;
+ assert schedule.getParameters().getId() > 0;
+ assert schedule.getParameters().getNames().size() == 2;
+ assert schedule.getParameters().getNames().contains("param1");
+ assert schedule.getParameters().getNames().contains("param2");
+ assert schedule.getParameters().getSimple("param1").getStringValue().equals("group-test");
+ assert schedule.getParameters().getSimple("param2").getStringValue().equals("blah");
+ assert schedule.getGroup().getId() == newGroup.getId();
+
+ int scheduleParamId = schedule.getParameters().getId();
+
+ Thread.sleep(4000L); // wait for it to finish, should be fast
+
+ PageList<GroupOperationHistory> results;
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 1;
+ GroupOperationHistory history = results.get(0);
+ assert history.getId() > 0 : history;
+ assert history.getJobId() != null : history;
+ assert history.getJobName() != null : history;
+ assert history.getJobGroup() != null : history;
+ assert history.getErrorMessage() == null : history;
+ assert history.getStatus() == OperationRequestStatus.SUCCESS : history;
+ assert history.getSubjectName().equals(overlord.getName()) : history;
+ assert history.getGroup().getId() == newGroup.getId();
+
+ // parameters and results are lazily loaded in the paginated queries, but are eagerly individually
+ history = (GroupOperationHistory) operationManager.getOperationHistoryByHistoryId(overlord, history.getId());
+ assert history.getParameters().getId() != scheduleParamId : "params should be copies - not shared";
+
+ // get the one resource history from the group
+ PageList<ResourceOperationHistory> results2;
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ ResourceOperationHistory rHistory = results2.get(0);
+ assert rHistory.getId() > 0 : rHistory;
+ assert rHistory.getJobId() != null : rHistory;
+ assert rHistory.getJobName() != null : rHistory;
+ assert rHistory.getJobGroup() != null : rHistory;
+ assert rHistory.getErrorMessage() == null : rHistory;
+ assert rHistory.getStatus() == OperationRequestStatus.SUCCESS : rHistory;
+ assert rHistory.getSubjectName().equals(overlord.getName()) : rHistory;
+
+ // parameters and results are lazily loaded in the paginated queries, but are eagerly individually
+ rHistory = (ResourceOperationHistory) operationManager.getOperationHistoryByHistoryId(overlord,
+ rHistory.getId());
+ assert rHistory.getResults() != null;
+ assert rHistory.getResults().getSimple("param1echo") != null;
+ assert rHistory.getResults().getSimple("param1echo").getStringValue().equals("group-test");
+ assert rHistory.getParameters().getId() != scheduleParamId : "params should be copies - not shared";
+ assert rHistory.getParameters().getId() != history.getParameters().getId() : "params should be copies - not shared";
+
+ operationManager.deleteOperationHistory(overlord, history.getId(), false);
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0; // none left, we purged the only group history there was
+
+ // purging group history purges all resource histories that belong to it
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results2 != null;
+ assert results2.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testScheduleGroupOperationError() throws Exception {
+ simulatedOperation_Error = "an error!";
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 0L;
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date());
+ GroupOperationSchedule schedule = operationManager.scheduleGroupOperation(overlord, newGroup.getId(),
+ new int[] { newResource.getId() }, true, "testOp", null, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() == null;
+ assert schedule.getGroup().getId() == newGroup.getId();
+
+ Thread.sleep(4000L); // wait for it to finish, should be fast
+
+ PageList<GroupOperationHistory> results;
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 1 : "Did not get 1 result back, but " + results.size();
+ GroupOperationHistory history = results.get(0);
+ assert history.getId() > 0 : history;
+ assert history.getJobId() != null : history;
+ assert history.getJobName() != null : history;
+ assert history.getJobGroup() != null : history;
+ assert history.getErrorMessage() != null : history;
+ assert history.getErrorMessage().indexOf(newResource.getName()) > -1 : history; // the name will be in the group error message
+ assert history.getStatus() == OperationRequestStatus.FAILURE : history;
+ assert history.getSubjectName().equals(overlord.getName()) : history;
+
+ // get the one resource history from the group
+ PageList<ResourceOperationHistory> results2;
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ ResourceOperationHistory rHistory = results2.get(0);
+ assert rHistory.getId() > 0 : rHistory;
+ assert rHistory.getJobId() != null : rHistory;
+ assert rHistory.getJobName() != null : rHistory;
+ assert rHistory.getJobGroup() != null : rHistory;
+ assert rHistory.getErrorMessage() != null : rHistory;
+ assert rHistory.getErrorMessage().indexOf("an error!") > -1 : rHistory;
+ assert rHistory.getStatus() == OperationRequestStatus.FAILURE : rHistory;
+ assert rHistory.getSubjectName().equals(overlord.getName()) : rHistory;
+
+ operationManager.deleteOperationHistory(overlord, history.getId(), false);
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0; // none left, we purged the only group history there was
+
+ // purging group history purges all resource histories that belong to it
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results2 != null;
+ assert results2.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testScheduleGroupOperationTimeout() throws Exception {
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = true;
+ simulatedOperation_Sleep = 0L;
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date());
+ GroupOperationSchedule schedule = operationManager.scheduleGroupOperation(overlord, newGroup.getId(),
+ new int[] { newResource.getId() }, true, "testOp", null, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() == null;
+ assert schedule.getGroup().getId() == newGroup.getId();
+
+ Thread.sleep(4000L); // wait for it to finish, should be fast
+
+ PageList<GroupOperationHistory> results;
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 1;
+ GroupOperationHistory history = results.get(0);
+ assert history.getId() > 0 : history;
+ assert history.getJobId() != null : history;
+ assert history.getJobName() != null : history;
+ assert history.getJobGroup() != null : history;
+ assert history.getErrorMessage() != null : history;
+ assert history.getErrorMessage().indexOf(newResource.getName()) > -1 : history; // the name will be in the group error message
+ assert history.getStatus() == OperationRequestStatus.FAILURE : history;
+ assert history.getSubjectName().equals(overlord.getName()) : history;
+
+ // get the one resource history from the group
+ PageList<ResourceOperationHistory> results2;
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ ResourceOperationHistory rHistory = results2.get(0);
+ assert rHistory.getId() > 0 : rHistory;
+ assert rHistory.getJobId() != null : rHistory;
+ assert rHistory.getJobName() != null : rHistory;
+ assert rHistory.getJobGroup() != null : rHistory;
+ assert rHistory.getErrorMessage() != null : rHistory;
+ assert rHistory.getErrorMessage().indexOf("Timed out") > -1 : rHistory;
+ assert rHistory.getStatus() == OperationRequestStatus.FAILURE : rHistory;
+ assert rHistory.getSubjectName().equals(overlord.getName()) : rHistory;
+
+ operationManager.deleteOperationHistory(overlord, history.getId(), false);
+ results = operationManager.findCompletedGroupOperationHistories(overlord, newGroup.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0; // none left, we purged the only group history there was
+
+ // purging group history purges all resource histories that belong to it
+ results2 = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results2 != null;
+ assert results2.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testUnscheduledResourceOperation() throws Exception {
+ Resource resource = newResource;
+
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 0L;
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date(System.currentTimeMillis() + 10000L));
+ ResourceOperationSchedule schedule = operationManager.scheduleResourceOperation(overlord, resource.getId(),
+ "testOp", null, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() == null;
+ assert schedule.getResource().getId() == newResource.getId();
+
+ List<ResourceOperationSchedule> schedules;
+ schedules = operationManager.findScheduledResourceOperations(overlord, resource.getId());
+ assert schedules != null;
+ assert schedules.size() == 1;
+ ResourceOperationSchedule returnedSchedule = schedules.get(0);
+ assert returnedSchedule.getSubject().equals(overlord);
+ assert returnedSchedule.getResource().getId() == resource.getId();
+ assert returnedSchedule.getParameters() == null;
+ assert returnedSchedule.getOperationName().equals("testOp");
+ assert returnedSchedule.getDescription().equals("desc");
+
+ PageList<ResourceOperationScheduleComposite> list;
+ list = operationManager.findCurrentlyScheduledResourceOperations(overlord, PageControl.getUnlimitedInstance());
+ assert list.size() == 1;
+ assert list.get(0).getResourceId() == resource.getId();
+ assert list.get(0).getResourceName().equals(resource.getName());
+ assert list.get(0).getOperationName().equals("Test Operation");
+
+ // let's immediately unschedule it before it triggers
+ operationManager.unscheduleResourceOperation(overlord, returnedSchedule.getJobId().toString(), returnedSchedule
+ .getResource().getId());
+
+ list = operationManager.findCurrentlyScheduledResourceOperations(overlord, PageControl.getUnlimitedInstance());
+ assert list.size() == 0;
+
+ // history should never have existed - we unscheduled faster than its trigger
+ PageList<ResourceOperationHistory> results;
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testUnscheduledResourceOperationWithParameters() throws Exception {
+ Resource resource = newResource;
+
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 0L;
+
+ Configuration params = new Configuration();
+ params.put(new PropertySimple("param1", "group-test"));
+ params.put(new PropertySimple("param2", "blah"));
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date(System.currentTimeMillis() + 10000L));
+ ResourceOperationSchedule schedule = operationManager.scheduleResourceOperation(overlord, resource.getId(),
+ "testOp", params, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() != null;
+ assert schedule.getResource().getId() == newResource.getId();
+
+ int configId = params.getId();
+ Configuration returnedConfiguration = configurationManager.getConfigurationById(configId);
+ assert returnedConfiguration.getProperties().size() == 2;
+ assert returnedConfiguration.getSimple("param1").getStringValue().equals("group-test");
+ assert returnedConfiguration.getSimple("param2").getStringValue().equals("blah");
+
+ List<ResourceOperationSchedule> schedules;
+ schedules = operationManager.findScheduledResourceOperations(overlord, resource.getId());
+ assert schedules != null;
+ assert schedules.size() == 1;
+ ResourceOperationSchedule returnedSchedule = schedules.get(0);
+ assert returnedSchedule.getSubject().equals(overlord);
+ assert returnedSchedule.getResource().getId() == resource.getId();
+ assert returnedSchedule.getParameters() != null;
+ assert returnedSchedule.getOperationName().equals("testOp");
+ assert returnedSchedule.getDescription().equals("desc");
+
+ // let's immediately unschedule it before it triggers
+ operationManager.unscheduleResourceOperation(overlord, returnedSchedule.getJobId().toString(), returnedSchedule
+ .getResource().getId());
+
+ // history should never have existed - we unscheduled faster than its trigger
+ PageList<ResourceOperationHistory> results;
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0;
+
+ // should be no dangling configuration entities representing group operation parameters
+ Configuration returnedConfiguration2 = configurationManager.getConfigurationById(configId);
+ assert returnedConfiguration2 == null;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetScheduledResourceOperations() throws Exception {
+ Resource resource = newResource;
+
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 0L;
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date(System.currentTimeMillis() + 5000L));
+ ResourceOperationSchedule schedule = operationManager.scheduleResourceOperation(overlord, resource.getId(),
+ "testOp", null, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() == null;
+ assert schedule.getResource().getId() == newResource.getId();
+
+ List<ResourceOperationSchedule> schedules;
+ schedules = operationManager.findScheduledResourceOperations(overlord, resource.getId());
+ assert schedules != null;
+ assert schedules.size() == 1;
+ ResourceOperationSchedule returnedSchedule = schedules.get(0);
+ assert returnedSchedule.getSubject().equals(overlord);
+ assert returnedSchedule.getResource().getId() == resource.getId();
+ assert returnedSchedule.getParameters() == null;
+ assert returnedSchedule.getOperationName().equals("testOp");
+ assert returnedSchedule.getDescription().equals("desc");
+
+ Thread.sleep(9000L); // wait for it to be triggered and complete
+
+ PageList<ResourceOperationHistory> results;
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+
+ assert results != null : "Results were unexpectedly empty";
+ if (results.isEmpty()) {
+ System.out.println("We did not yet get a result -- waiting some more");
+ Thread.sleep(5000L);
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ }
+
+ assert results != null : "Results were unexpectedly empty";
+ assert !results.isEmpty() : "We did not get results back";
+
+ operationManager.deleteOperationHistory(overlord, results.get(0).getId(), false);
+
+ // make sure it was purged
+ results = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0;
+
+ // see that it isn't scheduled anymore
+ schedules = operationManager.findScheduledResourceOperations(overlord, resource.getId());
+ assert schedules != null;
+ assert schedules.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetScheduledResourceOperationsError() throws Exception {
+ Resource resource = newResource;
+
+ simulatedOperation_Error = "some error";
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 0L;
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date(System.currentTimeMillis() + 5000L));
+ ResourceOperationSchedule schedule = operationManager.scheduleResourceOperation(overlord, resource.getId(),
+ "testOp", null, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() == null;
+ assert schedule.getResource().getId() == newResource.getId();
+
+ List<ResourceOperationSchedule> schedules;
+ schedules = operationManager.findScheduledResourceOperations(overlord, resource.getId());
+ assert schedules != null;
+ assert schedules.size() == 1;
+ ResourceOperationSchedule returnedSchedule = schedules.get(0);
+ assert returnedSchedule.getSubject().equals(overlord);
+ assert returnedSchedule.getResource().getId() == resource.getId();
+ assert returnedSchedule.getParameters() == null;
+ assert returnedSchedule.getOperationName().equals("testOp");
+ assert returnedSchedule.getDescription().equals("desc");
+
+ Thread.sleep(9000L); // wait for it to be triggered and complete
+
+ PageList<ResourceOperationHistory> results;
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+
+ assert results != null;
+ if (results.isEmpty()) {
+ System.out.println("We did not yet get a result -- waiting some more");
+ Thread.sleep(5000L);
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ }
+ assert results.size() == 1 : "Did not get 1 result, but " + results.size();
+
+ ResourceOperationHistory history = results.get(0);
+ assert history.getErrorMessage() != null : history;
+ assert history.getErrorMessage().indexOf("some error") > -1 : history;
+ assert history.getStatus() == OperationRequestStatus.FAILURE : history;
+
+ operationManager.deleteOperationHistory(overlord, history.getId(), false);
+
+ // make sure it was purged
+ results = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetScheduledResourceOperationsTimeout() throws Exception {
+ Resource resource = newResource;
+
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = true;
+ simulatedOperation_Sleep = 0L;
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date(System.currentTimeMillis() + 5000L));
+ ResourceOperationSchedule schedule = operationManager.scheduleResourceOperation(overlord, resource.getId(),
+ "testOp", null, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() == null;
+ assert schedule.getResource().getId() == newResource.getId();
+
+ List<ResourceOperationSchedule> schedules;
+ schedules = operationManager.findScheduledResourceOperations(overlord, resource.getId());
+ assert schedules != null;
+ assert schedules.size() == 1;
+ ResourceOperationSchedule returnedSchedule = schedules.get(0);
+ assert returnedSchedule.getSubject().equals(overlord);
+ assert returnedSchedule.getResource().getId() == resource.getId();
+ assert returnedSchedule.getParameters() == null;
+ assert returnedSchedule.getOperationName().equals("testOp");
+ assert returnedSchedule.getDescription().equals("desc");
+
+ Thread.sleep(9000L); // wait for it to be triggered and complete
+
+ PageList<ResourceOperationHistory> results;
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ if (results.isEmpty()) {
+ System.out.println("We did not yet get a result -- waiting some more");
+ Thread.sleep(5000L);
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ }
+ assert results.size() == 1 : "Did not get 1 result but " + results.size();
+
+ ResourceOperationHistory history = results.get(0);
+ assert history.getErrorMessage() != null : history;
+ assert history.getErrorMessage().indexOf("Timed out") > -1 : history;
+ assert history.getStatus() == OperationRequestStatus.FAILURE : history;
+
+ operationManager.deleteOperationHistory(overlord, history.getId(), false);
+
+ // make sure it was purged
+ results = operationManager.findCompletedResourceOperationHistories(overlord, newResource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0 : "Did not get 0 result but " + results.size();
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testCancelResourceOperation() throws Exception {
+ Resource resource = newResource;
+
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 30000L; // long enough so it doesn't finish before we cancel
+ simulatedOperation_CancelResults = new CancelResults(InterruptedState.RUNNING);
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date());
+ operationManager.scheduleResourceOperation(overlord, resource.getId(), "testOp", null, trigger, "desc");
+
+ PageList<ResourceOperationHistory> results = null;
+
+ // wait for it to be triggered so we get a history item
+ for (int i = 0; i < 5; i++) {
+ Thread.sleep(1000L);
+ results = operationManager.findPendingResourceOperationHistories(overlord, resource.getId(),
+ PageControl.getUnlimitedInstance());
+ if ((results != null) && (results.size() > 0)) {
+ break; // operation was triggered - got the history item
+ }
+ }
+
+ assert results != null;
+ assert results.size() == 1;
+ ResourceOperationHistory history = results.get(0);
+ assert history.getStatus() == OperationRequestStatus.INPROGRESS : history;
+
+ operationManager.cancelOperationHistory(overlord, history.getId(), false);
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 1;
+ history = results.get(0);
+ assert history.getStatus() == OperationRequestStatus.CANCELED : history;
+ System.out.println("test: Canceled resource history: " + history);
+
+ // try to cancel it again, just to make sure it blows up appropriately
+ try {
+ operationManager.cancelOperationHistory(overlord, history.getId(), false);
+ assert false : "Should not have been able to cancel an operation that is not INPROGRESS";
+ } catch (EJBException expected) {
+ // expected
+ }
+
+ operationManager.deleteOperationHistory(overlord, history.getId(), false);
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testCancelUncancelableResourceOperation() throws Exception {
+ // this test will attempt to cancel an operation that has already finished, in effect
+ // trying to cancel an uncancelable operation. This simulates the situation when
+ // an agent has finished running an operation but it has not yet sent the "success"
+ // or "failed" message to the server. So on the agent side it is finished, but the
+ // server side still thinks its INPROGRESS.
+
+ Resource resource = newResource;
+
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 30000L; // long enough so it doesn't notify that it finished before we cancel
+ simulatedOperation_CancelResults = new CancelResults(InterruptedState.FINISHED); // agent says its finished
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date());
+ operationManager.scheduleResourceOperation(overlord, resource.getId(), "testOp", null, trigger, "desc");
+
+ PageList<ResourceOperationHistory> results = null;
+
+ // wait for it to be triggered so we get a history item
+ for (int i = 0; i < 5; i++) {
+ Thread.sleep(1000L);
+ results = operationManager.findPendingResourceOperationHistories(overlord, resource.getId(),
+ PageControl.getUnlimitedInstance());
+ if ((results != null) && (results.size() > 0)) {
+ break; // operation was triggered - got the history item
+ }
+ }
+
+ assert results != null;
+ assert results.size() == 1;
+ ResourceOperationHistory history = results.get(0);
+ assert history.getStatus() == OperationRequestStatus.INPROGRESS : history;
+
+ operationManager.cancelOperationHistory(overlord, history.getId(), false);
+
+ // show that there are still no completed operations yet
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0;
+
+ // still pending - our operation wasn't really canceled - waiting for the agent to tell us its finished
+ results = operationManager.findPendingResourceOperationHistories(overlord, resource.getId(),
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 1;
+ history = results.get(0);
+
+ // we should have been told it finished on the agent - so we didn't cancel it
+ // server-side still will say inprogress - we are waiting for the agent to tell us
+ // the results of the finished operation, which should be imminent
+ assert history.getStatus() == OperationRequestStatus.INPROGRESS : history;
+ System.out.println("test: Uncancelable resource history: " + history);
+
+ operationManager.deleteOperationHistory(overlord, history.getId(), true);
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testScheduleResourceOperation() throws Exception {
+ Resource resource = newResource;
+
+ // make it a success after 500ms
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 0L;
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date(System.currentTimeMillis()));
+ ResourceOperationSchedule schedule = operationManager.scheduleResourceOperation(overlord, resource.getId(),
+ "testOp", null, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() == null;
+ assert schedule.getResource().getId() == newResource.getId();
+
+ Thread.sleep(4000L); // wait for it to finish, should be very quick
+
+ PageList<ResourceOperationHistory> results;
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 1;
+ ResourceOperationHistory history = results.get(0);
+ assert history.getId() > 0 : history;
+ assert history.getJobId() != null : history;
+ assert history.getJobName() != null : history;
+ assert history.getJobGroup() != null : history;
+ assert history.getErrorMessage() == null : history;
+ assert history.getStatus() == OperationRequestStatus.SUCCESS : history;
+ assert history.getSubjectName().equals(overlord.getName()) : history;
+
+ PageList<ResourceOperationLastCompletedComposite> list;
+ list = operationManager.findRecentlyCompletedResourceOperations(overlord, null,
+ PageControl.getUnlimitedInstance());
+ assert list.size() == 1;
+ assert list.get(0).getOperationHistoryId() == history.getId();
+ assert list.get(0).getResourceId() == resource.getId();
+ assert list.get(0).getResourceName().equals(resource.getName());
+ assert list.get(0).getOperationName().equals("Test Operation");
+
+ operationManager.deleteOperationHistory(overlord, history.getId(), false);
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0;
+
+ list = operationManager.findRecentlyCompletedResourceOperations(overlord, null,
+ PageControl.getUnlimitedInstance());
+ assert list.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testScheduleResourceOperationRecurring() throws Exception {
+ Resource resource = newResource;
+
+ // make it a success
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 0L;
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", 1, 750);
+ ResourceOperationSchedule schedule = operationManager.scheduleResourceOperation(overlord, resource.getId(),
+ "testOp", null, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() == null;
+ assert schedule.getResource().getId() == newResource.getId();
+
+ Thread.sleep(4000L); // wait for it to finish, should be very quick
+
+ PageList<ResourceOperationHistory> results;
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 2 : "Should have had multiple results: " + results;
+ ResourceOperationHistory history0 = results.get(0);
+ assert history0.getId() > 0 : history0;
+ assert history0.getJobId() != null : history0;
+ assert history0.getJobName() != null : history0;
+ assert history0.getJobGroup() != null : history0;
+ assert history0.getErrorMessage() == null : history0;
+ assert history0.getStatus() == OperationRequestStatus.SUCCESS : history0;
+ assert history0.getSubjectName().equals(overlord.getName()) : history0;
+
+ ResourceOperationHistory history1 = results.get(1);
+ assert history1.getId() > 0 : history1;
+ assert history1.getId() != history0.getId() : history1;
+ assert history1.getJobId() != null : history1;
+ assert !history1.getJobId().equals(history0.getJobId()) : history1;
+ assert history1.getJobName() != null : history1;
+ assert history1.getJobName().equals(history1.getJobId().getJobName()) : history1;
+ assert history1.getJobId().getJobName().equals(history0.getJobId().getJobName()) : history1;
+ assert history1.getJobGroup() != null : history1;
+ assert history1.getJobGroup().equals(history1.getJobId().getJobGroup()) : history1;
+ assert history1.getJobGroup().equals(history0.getJobGroup()) : history1;
+ assert history1.getJobId().getJobGroup().equals(history0.getJobId().getJobGroup()) : history1;
+ assert history1.getErrorMessage() == null : history1;
+ assert history1.getStatus() == OperationRequestStatus.SUCCESS : history1;
+ assert history1.getSubjectName().equals(overlord.getName()) : history1;
+
+ operationManager.deleteOperationHistory(overlord, history0.getId(), false);
+ operationManager.deleteOperationHistory(overlord, history1.getId(), false);
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testScheduleResourceOperationWithParameters() throws Exception {
+ Resource resource = newResource;
+
+ // make it a success after 500ms
+ simulatedOperation_Error = null;
+ simulatedOperation_Timeout = false;
+ simulatedOperation_Sleep = 0L;
+
+ Trigger trigger = new SimpleTrigger("tgrname", "tgrgroup", new Date());
+ Configuration params = new Configuration();
+ params.put(new PropertySimple("param1", "test-value!"));
+ ResourceOperationSchedule schedule = operationManager.scheduleResourceOperation(overlord, resource.getId(),
+ "testOp", params, trigger, "desc");
+ assert schedule != null;
+ assert schedule.getDescription().equals("desc");
+ assert schedule.getOperationName().equals("testOp");
+ assert schedule.getParameters() != null;
+ assert schedule.getParameters().getId() > 0;
+ assert schedule.getParameters().getSimple("param1") != null;
+ assert schedule.getResource().getId() == newResource.getId();
+
+ int scheduleParamId = schedule.getParameters().getId();
+
+ Thread.sleep(4000L); // wait for it to finish, should be very quick
+
+ PageList<ResourceOperationHistory> results;
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 1 : "size was " + results.size();
+ ResourceOperationHistory history = results.get(0);
+ assert history.getId() > 0 : history;
+ assert history.getJobId() != null : history;
+ assert history.getJobName() != null : history;
+ assert history.getJobGroup() != null : history;
+ assert history.getErrorMessage() == null : history;
+ assert history.getStatus() == OperationRequestStatus.SUCCESS : history;
+ assert history.getSubjectName().equals(overlord.getName()) : history;
+
+ // parameters and results are lazily loaded in the paginated queries, but are eagerly individually
+ history = (ResourceOperationHistory) operationManager.getOperationHistoryByHistoryId(overlord, history.getId());
+ assert history.getResults() != null;
+ assert history.getResults().getSimple("param1echo").getStringValue().equals("test-value!");
+ assert history.getParameters().getId() != scheduleParamId : "params should be copies - not shared";
+
+ operationManager.deleteOperationHistory(overlord, history.getId(), false);
+ results = operationManager.findCompletedResourceOperationHistories(overlord, resource.getId(), null, null,
+ PageControl.getUnlimitedInstance());
+ assert results != null;
+ assert results.size() == 0;
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testGetSupportedOperations() throws Exception {
+ Resource resource = newResource;
+
+ assert operationManager.isResourceOperationSupported(overlord, resource.getId());
+ assert operationManager.isGroupOperationSupported(overlord, newGroup.getId());
+
+ OperationDefinition op;
+ List<OperationDefinition> ops;
+
+ // need to eager load the definition because .equals compares the resource type objects
+ op = operationManager.getSupportedGroupOperation(overlord, newGroup.getId(), "testOp", true);
+ assert op != null;
+ assert op.getId() > 0;
+ assert op.getName().equals("testOp");
+ assert op.equals(newOperation);
+
+ // need to eager load the definition because .equals compares the resource type objects
+ ops = operationManager.findSupportedGroupOperations(overlord, newGroup.getId(), true);
+ assert ops != null;
+ assert ops.size() == 1;
+ op = ops.iterator().next();
+ assert op != null;
+ assert op.getId() > 0;
+ assert op.getName().equals("testOp");
+ assert op.equals(newOperation);
+
+ // need to eager load the definition because .equals compares the resource type objects
+ op = operationManager.getSupportedResourceOperation(overlord, newResource.getId(), "testOp", true);
+ assert op != null;
+ assert op.getId() > 0;
+ assert op.getName().equals("testOp");
+ assert op.equals(newOperation);
+
+ // need to eager load the definition because .equals compares the resource type objects
+ ops = operationManager.findSupportedResourceOperations(overlord, newResource.getId(), true);
+ assert ops != null;
+ assert ops.size() == 1;
+ op = ops.iterator().next();
+ assert op != null;
+ assert op.getId() > 0;
+ assert op.getName().equals("testOp");
+ assert op.equals(newOperation);
+ }
+
+ @Test(enabled = ENABLE_TESTS)
+ public void testNoPermissions() throws Exception {
+ Subject noPermSubject = new Subject("userWithNoPermissions", true, false);
+ Resource resource = newResource;
+
+ try {
+ noPermSubject = LookupUtil.getSubjectManager().createSubject(overlord, noPermSubject);
+ noPermSubject = createSession(noPermSubject);
+
+ assert !operationManager.isResourceOperationSupported(noPermSubject, resource.getId()) : "Should not have permission to get control info";
+ assert !operationManager.isGroupOperationSupported(noPermSubject, newGroup.getId()) : "Should not have permission to get control info";
+
+ try {
+ Trigger trigger = new SimpleTrigger();
+ operationManager
+ .scheduleResourceOperation(noPermSubject, resource.getId(), "testOp", null, trigger, "");
+ assert false : "Should not have permission to schedule a new op";
+ } catch (PermissionException expected) {
+ }
+
+ try {
+ operationManager.findScheduledGroupOperations(noPermSubject, newGroup.getId());
+ assert false : "Should not have permission to do this";
+ } catch (PermissionException expected) {
+ }
+
+ try {
+ operationManager.findScheduledResourceOperations(noPermSubject, newResource.getId());
+ assert false : "Should not have permission to do this";
+ } catch (PermissionException expected) {
+ }
+
+ try {
+ // do not need to eager load just to test authorization
+ operationManager.getSupportedGroupOperation(noPermSubject, newGroup.getId(), "testOp", false);
+ assert false : "Should not have permission to do this";
+ } catch (PermissionException expected) {
+ }
+
+ try {
+ // do not need to eager load just to test authorization
+ operationManager.findSupportedGroupOperations(noPermSubject, newGroup.getId(), false);
+ assert false : "Should not have permission to do this";
+ } catch (PermissionException expected) {
+ }
+
+ try {
+ // do not need to eager load just to test authorization
+ operationManager.getSupportedResourceOperation(noPermSubject, newResource.getId(), "testOp", false);
+ assert false : "Should not have permission to do this";
+ } catch (PermissionException expected) {
+ }
+
+ try {
+ // do not need to eager load just to test authorization
+ operationManager.findSupportedResourceOperations(noPermSubject, newResource.getId(), false);
+ assert false : "Should not have permission to do this";
+ } catch (PermissionException expected) {
+ }
+ } finally {
+ LookupUtil.getSubjectManager().deleteUsers(LookupUtil.getSubjectManager().getOverlord(),
+ new int[] { noPermSubject.getId() });
+ }
+ }
+
+ private Resource createNewResource() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ Resource resource;
+
+ try {
+ try {
+ ResourceType resourceType = new ResourceType("plat" + System.currentTimeMillis(), "test",
+ ResourceCategory.PLATFORM, null);
+
+ OperationDefinition def = new OperationDefinition(resourceType, "testOp");
+ def.setTimeout(10);
+ def.setDisplayName("Test Operation");
+ resourceType.addOperationDefinition(def);
+
+ em.persist(resourceType);
+
+ Agent agent = new Agent("testagent", "testaddress", 1, "", "testtoken");
+ em.persist(agent);
+ em.flush();
+
+ resource = new Resource("reskey" + System.currentTimeMillis(), "resname", resourceType);
+ resource.setUuid("" + new Random().nextInt());
+ resource.setAgent(agent);
+ resource.setInventoryStatus(InventoryStatus.COMMITTED);
+ em.persist(resource);
+
+ ResourceGroup group = new ResourceGroup("testgroupOMB" + System.currentTimeMillis(), resourceType);
+ em.persist(group);
+ group.addExplicitResource(resource);
+ } catch (Exception e) {
+ System.out.println("CANNOT PREPARE TEST: " + e);
+ getTransactionManager().rollback();
+ throw e;
+ }
+
+ em.flush();
+ getTransactionManager().commit();
+ } finally {
+ em.close();
+ }
+
+ return resource;
+ }
+
+ private void deleteNewResource(Resource resource) throws Exception {
+ if (null != resource) {
+ EntityManager em = null;
+
+ try {
+ ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+ ResourceGroupManagerLocal resourceGroupManager = LookupUtil.getResourceGroupManager();
+
+ // first, get entity for group removal
+ getTransactionManager().begin();
+ em = getEntityManager();
+
+ Resource res = em.find(Resource.class, resource.getId());
+ ResourceGroup group = res.getExplicitGroups().iterator().next();
+
+ getTransactionManager().commit();
+ em.close();
+ em = null;
+
+ // then invoke bulk delete on the resource to remove any dependencies not defined in the hibernate entity model
+ // perform in-band and out-of-band work in quick succession
+ List<Integer> deletedIds = resourceManager.uninventoryResource(overlord, resource.getId());
+ for (Integer deletedResourceId : deletedIds) {
+ resourceManager.uninventoryResourceAsyncWork(overlord, deletedResourceId);
+ }
+
+ // then kill the group via the RG manager, it also handles cleanup of non hibernate model info
+ resourceGroupManager.deleteResourceGroup(overlord, group.getId());
+
+ // now dispose of other hibernate entities
+ getTransactionManager().begin();
+ em = getEntityManager();
+
+ ResourceType type = em.find(ResourceType.class, resource.getResourceType().getId());
+ Agent agent = em.find(Agent.class, resource.getAgent().getId());
+ if (null != agent) {
+ em.remove(agent);
+ }
+ if (null != type) {
+ em.remove(type);
+ }
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ System.out.println("CANNOT CLEAN UP TEST (" + this.getClass().getSimpleName() + ") Cause: " + e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+ } finally {
+ if (null != em) {
+ em.close();
+ }
+ }
+ }
+ }
+
+ private class TestConfigService implements OperationAgentService {
+ public void invokeOperation(final String jobId, final int resourceId, final String operationName,
+ final Configuration paramConfig) throws PluginContainerException {
+ Thread thread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ System.out.println("~~~~~OPERATION TRIGGERED! op=" + operationName + ", jobId=" + jobId
+ + ", time=" + new Date());
+
+ long start = System.currentTimeMillis();
+
+ // this method simulates the agent actually invoking the operation
+ if (simulatedOperation_Sleep > 0L) {
+ Thread.sleep(simulatedOperation_Sleep);
+ }
+
+ long end = System.currentTimeMillis();
+
+ if (simulatedOperation_Error != null) {
+ ExceptionPackage error = new ExceptionPackage(new Exception(simulatedOperation_Error));
+ if (operationServerService != null) {
+ operationServerService.operationFailed(jobId, null, error, start, end);
+ }
+ } else if (simulatedOperation_Timeout) {
+ if (operationServerService != null) {
+ operationServerService.operationTimedOut(jobId, start, end);
+ }
+ } else {
+ Configuration results = null;
+ if ((paramConfig != null) && (paramConfig.getSimple("param1") != null)) {
+ results = new Configuration();
+ results.put(new PropertySimple("param1echo", paramConfig.getSimple("param1")
+ .getStringValue()));
+ }
+
+ if (operationServerService != null) {
+ operationServerService.operationSucceeded(jobId, results, start, end);
+ }
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+ };
+
+ thread.start();
+ }
+
+ public CancelResults cancelOperation(String jobId) {
+ return simulatedOperation_CancelResults;
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/performance/test/AvailabilityInsertPurgeTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/performance/test/AvailabilityInsertPurgeTest.java
new file mode 100644
index 0000000..4b9dea2
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/performance/test/AvailabilityInsertPurgeTest.java
@@ -0,0 +1,411 @@
+/*
+ * 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.performance.test;
+
+import java.lang.reflect.Method;
+import java.util.Date;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.testng.ITestResult;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.alert.AlertCondition;
+import org.rhq.core.domain.alert.AlertConditionCategory;
+import org.rhq.core.domain.alert.AlertDampening;
+import org.rhq.core.domain.alert.AlertDefinition;
+import org.rhq.core.domain.alert.AlertPriority;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.discovery.AvailabilityReport;
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
+import org.rhq.enterprise.server.core.AgentManagerLocal;
+import org.rhq.enterprise.server.measurement.AvailabilityManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.system.SystemManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3PerformanceTest;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.helpers.perftest.support.reporting.ExcelExporter;
+import org.rhq.helpers.perftest.support.testng.DatabaseSetupInterceptor;
+import org.rhq.helpers.perftest.support.testng.DatabaseState;
+import org.rhq.helpers.perftest.support.testng.PerformanceReporting;
+
+/**
+ * Performance test the availabilities subsystem
+ *
+ * @author Heiko W. Rupp
+ * @author Lukas Krejci
+ */
+@Test(groups = "PERF")
+@Listeners({ DatabaseSetupInterceptor.class })
+@PerformanceReporting(exporter = ExcelExporter.class)
+@DatabaseState(url = "perftest/AvailabilityInsertPurgeTest-testOne-data.xml.zip", dbVersion = "2.101")
+public class AvailabilityInsertPurgeTest extends AbstractEJB3PerformanceTest {
+
+ ResourceManagerLocal resourceManager;
+ AvailabilityManagerLocal availabilityManager;
+ AgentManagerLocal agentManager;
+ SystemManagerLocal systemManager;
+ AlertDefinitionManagerLocal alertDefinitionManager;
+ private static final int MILLIS_APART = 2000;
+ private static final String ROUND__FORMAT = "Round %6d";
+ private static final String PURGE__FORMAT = "Purge %6d";
+ private static final int[] ROUNDS = new int[] { 1000, 2000, 3000, 5000, 10000 };
+
+ // private static final int[] ROUNDS = new int[]{10,20};
+
+ @BeforeMethod
+ public void beforeMethod(Method method) {
+ super.setupTimings(method);
+ Date now = new Date();
+ try {
+ this.availabilityManager = LookupUtil.getAvailabilityManager();
+ this.resourceManager = LookupUtil.getResourceManager();
+ this.agentManager = LookupUtil.getAgentManager();
+ this.systemManager = LookupUtil.getSystemManager();
+ this.alertDefinitionManager = LookupUtil.getAlertDefinitionManager();
+ /*
+ * NOTE: do not try to get Subjects in here, as they will only be available after
+ * this method has finished and the DatabaseSetupInterceptor has initialized the
+ * database.
+ */
+ } catch (Throwable t) {
+ // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
+ // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
+ t.printStackTrace();
+ System.err.flush();
+ throw new RuntimeException(t);
+ }
+ }
+
+ @AfterMethod
+ public void afterMethod(ITestResult result, Method meth) {
+ super.reportTimings(result, meth);
+ }
+
+ /**
+ * Send availability reports to the server and measure timing.
+ * For each resource, availability alternates for each report.
+ * There are multiple rounds of sending with higher numbers of reports.
+ * @throws Exception If anything goes wrong
+ * @see #ROUNDS for the number of availability reports per round
+ */
+ public void testAlternating() throws Exception {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ Date now = new Date();
+
+ EntityManager em = getEntityManager();
+ Query q = em.createQuery("SELECT r FROM Resource r");
+ List<Resource> resources = q.getResultList();
+ Resource res = resources.get(0);
+ Agent agent = agentManager.getAgentByResourceId(overlord, res.getId());
+
+ q = em.createQuery("SELECT COUNT(a) FROM Availability a ");
+ Object o = q.getSingleResult();
+ Long l = (Long) o;
+ if (l != 0) {
+ throw new IllegalStateException("Availabilities table is not empty");
+ }
+ systemManager.vacuum(overlord, new String[] { "rhq_availability" });
+
+ for (int MULTI : ROUNDS) {
+ String round = String.format(ROUND__FORMAT, MULTI);
+
+ long t1 = System.currentTimeMillis() - (MULTI * MILLIS_APART);
+ for (int i = 0; i < MULTI; i++) {
+
+ AvailabilityReport report = new AvailabilityReport(agent.getName());
+ for (Resource r : resources) {
+ AvailabilityType at = (i % 2 == 0) ? AvailabilityType.UP : AvailabilityType.DOWN;
+ Availability a = new Availability(r, (t1 + i * MILLIS_APART), at);
+ report.addAvailability(a);
+ }
+ startTiming(round);
+ availabilityManager.mergeAvailabilityReport(report);
+ endTiming(round);
+ }
+
+ // merge is over. Now lets purge in two steps
+ startTiming(String.format(PURGE__FORMAT, MULTI));
+ availabilityManager.purgeAvailabilities(t1 + (MULTI / 2) * MILLIS_APART);
+ endTiming(String.format(PURGE__FORMAT, MULTI));
+ startTiming(String.format(PURGE__FORMAT, MULTI));
+ availabilityManager.purgeAvailabilities(t1);
+ endTiming(String.format(PURGE__FORMAT, MULTI));
+ // Vacuum the db
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+ systemManager.vacuum(overlord, new String[] { "rhq_availability" });
+
+ }
+
+ long timing1000 = getTiming(String.format(ROUND__FORMAT, 1000));
+ long timing2000 = getTiming(String.format(ROUND__FORMAT, 2000));
+ long timing3000 = getTiming(String.format(ROUND__FORMAT, 3000));
+ long timing5000 = getTiming(String.format(ROUND__FORMAT, 5000));
+ long timing10000 = getTiming(String.format(ROUND__FORMAT, 10000));
+
+ assertLinear(timing1000, timing2000, 2, "Merge2");
+ assertLinear(timing1000, timing3000, 3, "Merge3");
+ assertLinear(timing1000, timing5000, 5, "Merge5");
+ assertLinear(timing1000, timing10000, 10, "Merge10");
+
+ long purge1000 = getTiming(String.format(PURGE__FORMAT, 1000));
+ long purge2000 = getTiming(String.format(PURGE__FORMAT, 2000));
+ long purge3000 = getTiming(String.format(PURGE__FORMAT, 3000));
+ long purge5000 = getTiming(String.format(PURGE__FORMAT, 5000));
+
+ assertLinear(purge1000, purge2000, 2, "Purge2");
+ assertLinear(purge1000, purge3000, 3, "Purge3");
+ assertLinear(purge1000, purge5000, 5, "Purge3");
+
+ }
+
+ /**
+ * Like {@link #testAlternating}, but availabilities are now random per resource and report.
+ * @throws Exception If anything goes wrong
+ * @see #ROUNDS for the number of availability reports per round
+ */
+ public void testRandom() throws Exception {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ EntityManager em = getEntityManager();
+ Query q = em.createQuery("SELECT r FROM Resource r");
+ List<Resource> resources = q.getResultList();
+ Resource res = resources.get(0);
+ Agent agent = agentManager.getAgentByResourceId(overlord, res.getId());
+
+ for (int MULTI : ROUNDS) {
+ String round = String.format(ROUND__FORMAT, MULTI);
+
+ long t1 = System.currentTimeMillis() - (MULTI * MILLIS_APART);
+ for (int i = 0; i < MULTI; i++) {
+
+ AvailabilityReport report = new AvailabilityReport(agent.getName());
+ for (Resource r : resources) {
+ int rand = (int) (Math.random() * 2);
+ AvailabilityType at = (rand == 1) ? AvailabilityType.UP : AvailabilityType.DOWN;
+ Availability a = new Availability(r, (t1 + i * MILLIS_APART), at);
+ report.addAvailability(a);
+ }
+ startTiming(round);
+ availabilityManager.mergeAvailabilityReport(report);
+ endTiming(round);
+ }
+
+ // merge is over. Now lets purge in two steps
+ startTiming(String.format(PURGE__FORMAT, MULTI));
+ availabilityManager.purgeAvailabilities(t1 + (MULTI / 2) * MILLIS_APART);
+ endTiming(String.format(PURGE__FORMAT, MULTI));
+ startTiming(String.format(PURGE__FORMAT, MULTI));
+ availabilityManager.purgeAvailabilities(t1);
+ endTiming(String.format(PURGE__FORMAT, MULTI));
+ // Vacuum the db
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+ systemManager.vacuum(overlord, new String[] { "rhq_availability" });
+
+ }
+
+ long timing1000 = getTiming(String.format(ROUND__FORMAT, 1000));
+ long timing2000 = getTiming(String.format(ROUND__FORMAT, 2000));
+ long timing3000 = getTiming(String.format(ROUND__FORMAT, 3000));
+ long timing5000 = getTiming(String.format(ROUND__FORMAT, 5000));
+ long timing10000 = getTiming(String.format(ROUND__FORMAT, 10000));
+
+ assertLinear(timing1000, timing2000, 2, "Merge2");
+ assertLinear(timing1000, timing3000, 3, "Merge3");
+ assertLinear(timing1000, timing5000, 5, "Merge5");
+ assertLinear(timing1000, timing10000, 10, "Merge10");
+
+ long purge1000 = getTiming(String.format(PURGE__FORMAT, 1000));
+ long purge2000 = getTiming(String.format(PURGE__FORMAT, 2000));
+ long purge3000 = getTiming(String.format(PURGE__FORMAT, 3000));
+ long purge5000 = getTiming(String.format(PURGE__FORMAT, 5000));
+
+ assertLinear(purge1000, purge2000, 2, "Purge2");
+ assertLinear(purge1000, purge3000, 3, "Purge3");
+ assertLinear(purge1000, purge5000, 5, "Purge3");
+
+ }
+
+ /**
+ * Like {@link #testAlternating}, but availabilities are always up per resource and report.
+ * @throws Exception If anything goes wrong
+ * @see #ROUNDS for the number of availability reports per round
+ */
+ public void testAlwaysUp() throws Exception {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ EntityManager em = getEntityManager();
+ Query q = em.createQuery("SELECT r FROM Resource r");
+ List<Resource> resources = q.getResultList();
+ Resource res = resources.get(0);
+ Agent agent = agentManager.getAgentByResourceId(overlord, res.getId());
+
+ for (int MULTI : ROUNDS) {
+ String round = String.format(ROUND__FORMAT, MULTI);
+
+ long t1 = System.currentTimeMillis() - (MULTI * MILLIS_APART);
+ for (int i = 0; i < MULTI; i++) {
+
+ AvailabilityReport report = new AvailabilityReport(agent.getName());
+ for (Resource r : resources) {
+ AvailabilityType at = AvailabilityType.UP;
+ Availability a = new Availability(r, (t1 + i * MILLIS_APART), at);
+ report.addAvailability(a);
+ }
+ startTiming(round);
+ availabilityManager.mergeAvailabilityReport(report);
+ endTiming(round);
+ }
+
+ // merge is over. Now lets purge in two steps
+ startTiming(String.format(PURGE__FORMAT, MULTI));
+ availabilityManager.purgeAvailabilities(t1 + (MULTI / 2) * MILLIS_APART);
+ endTiming(String.format(PURGE__FORMAT, MULTI));
+ startTiming(String.format(PURGE__FORMAT, MULTI));
+ availabilityManager.purgeAvailabilities(t1);
+ endTiming(String.format(PURGE__FORMAT, MULTI));
+ // Vacuum the db
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+ systemManager.vacuum(overlord, new String[] { "rhq_availability" });
+
+ }
+
+ long timing1000 = getTiming(String.format(ROUND__FORMAT, 1000));
+ long timing2000 = getTiming(String.format(ROUND__FORMAT, 2000));
+ long timing3000 = getTiming(String.format(ROUND__FORMAT, 3000));
+ long timing5000 = getTiming(String.format(ROUND__FORMAT, 5000));
+ long timing10000 = getTiming(String.format(ROUND__FORMAT, 10000));
+
+ assertLinear(timing1000, timing2000, 2, "Merge2");
+ assertLinear(timing1000, timing3000, 3, "Merge3");
+ assertLinear(timing1000, timing5000, 5, "Merge5");
+ assertLinear(timing1000, timing10000, 10, "Merge10");
+
+ long purge1000 = getTiming(String.format(PURGE__FORMAT, 1000));
+ long purge2000 = getTiming(String.format(PURGE__FORMAT, 2000));
+ long purge3000 = getTiming(String.format(PURGE__FORMAT, 3000));
+ long purge5000 = getTiming(String.format(PURGE__FORMAT, 5000));
+
+ assertLinear(purge1000, purge2000, 2, "Purge2");
+ assertLinear(purge1000, purge3000, 3, "Purge3");
+ assertLinear(purge1000, purge5000, 5, "Purge3");
+
+ }
+
+ /**
+ * Send availability reports to the server and measure timing.
+ * For each resource, availability alternates for each report.
+ * There are multiple rounds of sending with higher numbers of reports.
+ * For one resource we set up an alert to fire every going down report.
+ * @throws Exception If anything goes wrong
+ * @see #ROUNDS for the number of availability reports per round
+ */
+ public void testAlternatingWithAlert() throws Exception {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ EntityManager em = getEntityManager();
+ Query q = em.createQuery("SELECT r FROM Resource r");
+ List<Resource> resources = q.getResultList();
+ Resource res = resources.get(0);
+ Agent agent = agentManager.getAgentByResourceId(overlord, res.getId());
+
+ q = em.createQuery("SELECT COUNT(a) FROM Availability a ");
+ Object o = q.getSingleResult();
+ Long l = (Long) o;
+ if (l != 0) {
+ throw new IllegalStateException("Availabilities table is not empty");
+ }
+ systemManager.vacuum(overlord, new String[] { "rhq_availability" });
+
+ // Set up an alert definition on one resource
+ AlertCondition goingDown = new AlertCondition();
+ goingDown.setCategory(AlertConditionCategory.AVAILABILITY);
+ goingDown.setComparator("==");
+ goingDown.setOption(AvailabilityType.DOWN.toString());
+
+ AlertDefinition def = new AlertDefinition();
+ def.addCondition(goingDown);
+ def.setName("Test alert definition");
+ def.setPriority(AlertPriority.MEDIUM);
+ def.setAlertDampening(new AlertDampening(AlertDampening.Category.NONE));
+ def.setRecoveryId(0);
+ alertDefinitionManager.createAlertDefinition(overlord, def, res.getId(), true);
+
+ for (int MULTI : ROUNDS) {
+ String round = String.format(ROUND__FORMAT, MULTI);
+
+ long t1 = System.currentTimeMillis() - (MULTI * MILLIS_APART);
+ for (int i = 0; i < MULTI; i++) {
+
+ AvailabilityReport report = new AvailabilityReport(agent.getName());
+ for (Resource r : resources) {
+ AvailabilityType at = (i % 2 == 0) ? AvailabilityType.UP : AvailabilityType.DOWN;
+ Availability a = new Availability(r, (t1 + i * MILLIS_APART), at);
+ report.addAvailability(a);
+ }
+ startTiming(round);
+ availabilityManager.mergeAvailabilityReport(report);
+ endTiming(round);
+ }
+
+ // merge is over. Now lets purge in two steps
+ startTiming(String.format(PURGE__FORMAT, MULTI));
+ availabilityManager.purgeAvailabilities(t1 + (MULTI / 2) * MILLIS_APART);
+ endTiming(String.format(PURGE__FORMAT, MULTI));
+ startTiming(String.format(PURGE__FORMAT, MULTI));
+ availabilityManager.purgeAvailabilities(t1);
+ endTiming(String.format(PURGE__FORMAT, MULTI));
+ // Vacuum the db
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+ systemManager.vacuum(overlord, new String[] { "rhq_availability" });
+
+ }
+
+ long timing1000 = getTiming(String.format(ROUND__FORMAT, 1000));
+ long timing2000 = getTiming(String.format(ROUND__FORMAT, 2000));
+ long timing3000 = getTiming(String.format(ROUND__FORMAT, 3000));
+ long timing5000 = getTiming(String.format(ROUND__FORMAT, 5000));
+ long timing10000 = getTiming(String.format(ROUND__FORMAT, 10000));
+
+ assertLinear(timing1000, timing2000, 2, "Merge2");
+ assertLinear(timing1000, timing3000, 3, "Merge3");
+ assertLinear(timing1000, timing5000, 5, "Merge5");
+ assertLinear(timing1000, timing10000, 10, "Merge10");
+
+ long purge1000 = getTiming(String.format(PURGE__FORMAT, 1000));
+ long purge2000 = getTiming(String.format(PURGE__FORMAT, 2000));
+ long purge3000 = getTiming(String.format(PURGE__FORMAT, 3000));
+ long purge5000 = getTiming(String.format(PURGE__FORMAT, 5000));
+
+ assertLinear(purge1000, purge2000, 2, "Purge2");
+ assertLinear(purge1000, purge3000, 3, "Purge3");
+ assertLinear(purge1000, purge5000, 5, "Purge3");
+
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/performance/test/CallTimeInsertPurgeTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/performance/test/CallTimeInsertPurgeTest.java
new file mode 100644
index 0000000..7d7d63e
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/performance/test/CallTimeInsertPurgeTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.performance.test;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementSchedule;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.domain.measurement.calltime.CallTimeData;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
+import org.rhq.enterprise.server.core.AgentManagerLocal;
+import org.rhq.enterprise.server.event.EventManagerLocal;
+import org.rhq.enterprise.server.measurement.AvailabilityManagerLocal;
+import org.rhq.enterprise.server.measurement.CallTimeDataManagerLocal;
+import org.rhq.enterprise.server.measurement.MeasurementDataManagerBean;
+import org.rhq.enterprise.server.measurement.MeasurementDataManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.system.SystemManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3PerformanceTest;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.helpers.perftest.support.reporting.ExcelExporter;
+import org.rhq.helpers.perftest.support.testng.DatabaseSetupInterceptor;
+import org.rhq.helpers.perftest.support.testng.DatabaseState;
+import org.rhq.helpers.perftest.support.testng.PerformanceReporting;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.lang.reflect.Method;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Test insertion of call time data and purging it
+ *
+ * @author Heiko W. Rupp
+ */
+@Test(groups = "PERF")
+@Listeners({ DatabaseSetupInterceptor.class })
+(a)PerformanceReporting(exporter=ExcelExporter.class)
+@DatabaseState(url = "perftest/AvailabilityInsertPurgeTest-testOne-data.xml.zip", dbVersion="2.101")
+public class CallTimeInsertPurgeTest extends AbstractEJB3PerformanceTest {
+
+ private final Log log = LogFactory.getLog(CallTimeInsertPurgeTest.class);
+
+
+ private static final int ROUNDS = 200;
+ private static final int NUM_SOURCES = 10;
+ private static final int LINES_PER_REPORT = 50;
+ ResourceManagerLocal resourceManager;
+ AvailabilityManagerLocal availabilityManager;
+ AgentManagerLocal agentManager;
+ SystemManagerLocal systemManager;
+ AlertDefinitionManagerLocal alertDefinitionManager;
+ MeasurementDataManagerLocal measurementDataManager;
+ private static final int MILLIS_APART = 2000;
+ private static final String ROUND__FORMAT = "Round %6d";
+ private static final String PURGE__FORMAT = "Purge %6d";
+
+
+ @BeforeMethod
+ public void beforeMethod(Method method) {
+ super.setupTimings(method);
+ try {
+ this.availabilityManager = LookupUtil.getAvailabilityManager();
+ this.resourceManager = LookupUtil.getResourceManager();
+ this.agentManager = LookupUtil.getAgentManager();
+ this.systemManager = LookupUtil.getSystemManager();
+ this.alertDefinitionManager = LookupUtil.getAlertDefinitionManager();
+ this.measurementDataManager = LookupUtil.getMeasurementDataManager();
+ /*
+ * NOTE: do not try to get Subjects or other DB stuff in here, as they will only
+ * be available after this method has finished and the DatabaseSetupInterceptor
+ * has initialized the database.
+ */
+ } catch (Throwable t) {
+ // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
+ // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+
+
+ public void testSimple() throws Exception {
+
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+
+ EntityManager em = getEntityManager();
+ Query q = em.createQuery("SELECT r FROM Resource r");
+ List<Resource> resources = q.getResultList();
+ Resource res = resources.get(0);
+ if (!(res.getResourceType().getCategory()== ResourceCategory.PLATFORM))
+ res = resourceManager.getPlaformOfResource(overlord,res.getId());
+ ResourceType type = res.getResourceType();
+ MeasurementDefinition def = null;
+ Set<MeasurementDefinition> definitions = type.getMetricDefinitions();
+ for (MeasurementDefinition d : definitions) {
+ if (d.getName().equals("myCallTime"))
+ def = d;
+ }
+
+
+
+ MeasurementSchedule schedule = new MeasurementSchedule(def,res);
+ MeasurementScheduleRequest request = new MeasurementScheduleRequest(schedule);
+
+
+ for (int i = 0 ; i < ROUNDS ; i++) {
+ CallTimeData data = new CallTimeData(request);
+
+ MeasurementReport report = new MeasurementReport();
+
+
+ for (int j = 0 ; j < NUM_SOURCES ; j++) {
+ data.addCallData("/foo/" + j,new Date(),NUM_SOURCES-j);
+ }
+ report.addData(data);
+
+ startTiming();
+ measurementDataManager.mergeMeasurementReport(report);
+ endTiming();
+ }
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/performance/test/EventsInsertPurgeTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/performance/test/EventsInsertPurgeTest.java
new file mode 100644
index 0000000..de7c547
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/performance/test/EventsInsertPurgeTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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.performance.test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.event.Event;
+import org.rhq.core.domain.event.EventDefinition;
+import org.rhq.core.domain.event.EventSeverity;
+import org.rhq.core.domain.event.EventSource;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
+import org.rhq.enterprise.server.core.AgentManagerLocal;
+import org.rhq.enterprise.server.event.EventManagerLocal;
+import org.rhq.enterprise.server.measurement.AvailabilityManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.system.SystemManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3PerformanceTest;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.helpers.perftest.support.reporting.ExcelExporter;
+import org.rhq.helpers.perftest.support.testng.DatabaseSetupInterceptor;
+import org.rhq.helpers.perftest.support.testng.DatabaseState;
+import org.rhq.helpers.perftest.support.testng.PerformanceReporting;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.lang.reflect.Method;
+import java.sql.SQLException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Performance test the events subsystem
+ *
+ * @author Heiko W. Rupp
+ */
+@Test(groups = "PERF")
+@Listeners({ DatabaseSetupInterceptor.class })
+(a)PerformanceReporting(exporter=ExcelExporter.class)
+@DatabaseState(url = "perftest/AvailabilityInsertPurgeTest-testOne-data.xml.zip", dbVersion="2.101")
+public class EventsInsertPurgeTest extends AbstractEJB3PerformanceTest {
+
+ private static final int ROUNDS = 20000;
+ private static final int NUM_SOURCES = 10;
+ private static final int LINES_PER_REPORT = 50;
+ ResourceManagerLocal resourceManager;
+ AvailabilityManagerLocal availabilityManager;
+ AgentManagerLocal agentManager;
+ SystemManagerLocal systemManager;
+ AlertDefinitionManagerLocal alertDefinitionManager;
+ EventManagerLocal eventManager;
+ private static final int MILLIS_APART = 2000;
+ private static final String ROUND__FORMAT = "Round %6d";
+ private static final String PURGE__FORMAT = "Purge %6d";
+
+
+ @BeforeMethod
+ public void beforeMethod(Method method) {
+ super.setupTimings(method);
+ try {
+ this.availabilityManager = LookupUtil.getAvailabilityManager();
+ this.resourceManager = LookupUtil.getResourceManager();
+ this.agentManager = LookupUtil.getAgentManager();
+ this.systemManager = LookupUtil.getSystemManager();
+ this.alertDefinitionManager = LookupUtil.getAlertDefinitionManager();
+ this.eventManager = LookupUtil.getEventManager();
+ /*
+ * NOTE: do not try to get Subjects or other DB stuff in here, as they will only
+ * be available after this method has finished and the DatabaseSetupInterceptor
+ * has initialized the database.
+ */
+ } catch (Throwable t) {
+ // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
+ // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+
+ /**
+ * This test insertsevents from NUM_SOURCES sources into the
+ * event subsystem, where each set of events is LINES_PER_REPORT long.
+ * In total ROUNDS are inserted.
+ * After this, events are purged in two steps: first the first half of them
+ * and then the remaining ones.
+ * @throws Exception
+ */
+ public void testSimpleInserts() throws Exception {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+
+ EntityManager em = getEntityManager();
+ Query q = em.createQuery("SELECT r FROM Resource r");
+ List<Resource> resources = q.getResultList();
+ Resource res = resources.get(0);
+ if (!(res.getResourceType().getCategory()== ResourceCategory.PLATFORM))
+ res = resourceManager.getPlaformOfResource(overlord,res.getId());
+ ResourceType type = res.getResourceType();
+
+ EventDefinition def ;
+ Set<EventDefinition> eventDefs = type.getEventDefinitions();
+ if (eventDefs!=null && !eventDefs.isEmpty()) {
+ def = eventDefs.iterator().next();
+ }
+ else {
+ throw new RuntimeException("No event definition found, should not happen");
+ }
+
+
+ EventSource[] evSrc = new EventSource[NUM_SOURCES];
+ for (int i = 0; i < NUM_SOURCES; i++) {
+ evSrc[i] = new EventSource("ESource"+1, def, res);
+ }
+ long now = new Date().getTime() - ROUNDS * LINES_PER_REPORT;
+
+ for (int round = 1; round < ROUNDS; round++) {
+
+ Map<EventSource, Set<Event>> events = new HashMap<EventSource, Set<Event>>();
+ for (int sourceNum = 0 ; sourceNum < NUM_SOURCES; sourceNum++) {
+ Set<Event> eventSet = new HashSet<Event>();
+ for (int i = 0 ; i < LINES_PER_REPORT; i++) {
+ Event ev = new Event("EType", "ESource"+sourceNum, now+round*i, EventSeverity.INFO, "This is a 2nd test", evSrc[sourceNum]);
+ eventSet.add(ev);
+ }
+ events.put(evSrc[sourceNum], eventSet);
+ }
+ startTiming("add");
+ eventManager.addEventData(events);
+ endTiming("add");
+ }
+
+ try {
+ startTiming("purge_half");
+ eventManager.purgeEventData(new Date(now+(ROUNDS/2)*LINES_PER_REPORT));
+ endTiming("purge_half");
+ startTiming("purge_final");
+ eventManager.purgeEventData(new Date());
+ endTiming("purge_final");
+ } catch (SQLException e) {
+ e.printStackTrace();
+ throw e;
+ }
+
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
new file mode 100644
index 0000000..9ce4829
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
@@ -0,0 +1,420 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.hibernate.LazyInitializationException;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.core.domain.plugin.PluginKey;
+import org.rhq.core.domain.plugin.PluginStatusType;
+import org.rhq.core.domain.plugin.ServerPlugin;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
+import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.generic.GenericPluginDescriptorType;
+
+/**
+ * @author John Mazzitelli
+ */
+@Test
+public class ServerPluginsBeanTest extends AbstractEJB3Test {
+
+ private static final String TEST_PLUGIN_NAME_PREFIX = "serverplugintest";
+
+ private ServerPluginsLocal serverPluginsBean;
+
+ @BeforeMethod
+ public void beforeMethod() {
+ TestGenericServerPluginService pluginService;
+ pluginService = new TestGenericServerPluginService();
+ prepareCustomServerPluginService(pluginService);
+
+ serverPluginsBean = LookupUtil.getServerPlugins();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() {
+
+ EntityManager em = null;
+
+ try {
+ unprepareServerPluginService();
+ } catch (Exception e) {
+ }
+
+ try {
+ getTransactionManager().begin();
+ em = getEntityManager();
+
+ Query q = em
+ .createQuery("SELECT p FROM ServerPlugin p LEFT JOIN FETCH p.pluginConfiguration ppc LEFT JOIN FETCH p.scheduledJobsConfiguration psjc WHERE p.name LIKE 'serverplugintest%'");
+ List<ServerPlugin> doomed = q.getResultList();
+ for (ServerPlugin plugin : doomed) {
+ em.remove(em.getReference(ServerPlugin.class, plugin.getId()));
+ }
+
+ getTransactionManager().commit();
+ em.close();
+ em = null;
+ } catch (Exception e) {
+ try {
+ System.out.println("CANNOT CLEAN UP TEST: Cause: " + e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+ } finally {
+ if (null != em) {
+ em.close();
+ }
+ }
+ }
+
+ public void testGetPlugins() throws Exception {
+ ServerPlugin p1 = registerPlugin(1);
+ ServerPlugin p2 = registerPlugin(2);
+ PluginKey p1key = new PluginKey(p1);
+ PluginKey p2key = new PluginKey(p2);
+ List<PluginKey> pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(true);
+ assert pluginKeys.contains(p1key) : pluginKeys;
+ assert pluginKeys.contains(p2key) : pluginKeys;
+ pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(false);
+ assert !pluginKeys.contains(p1key) : pluginKeys;
+ assert !pluginKeys.contains(p2key) : pluginKeys;
+
+ ServerPlugin plugin = this.serverPluginsBean.getServerPlugin(p1key);
+ assert plugin.getId() == p1.getId() : plugin;
+ assert plugin.getName().equals(p1.getName()) : plugin;
+ assetLazyInitializationException(plugin);
+
+ plugin = this.serverPluginsBean.getServerPluginRelationships(plugin);
+ assert plugin.getPluginConfiguration() != null;
+ assert plugin.getScheduledJobsConfiguration() != null;
+ assert plugin.getPluginConfiguration().equals(p1.getPluginConfiguration());
+ assert plugin.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration());
+
+ List<ServerPlugin> plugins = this.serverPluginsBean.getServerPlugins();
+ assert plugins.contains(p1) : plugins;
+ assert plugins.contains(p2) : plugins;
+ assetLazyInitializationException(plugins.get(plugins.indexOf(p1)));
+ assetLazyInitializationException(plugins.get(plugins.indexOf(p2)));
+
+ plugins = this.serverPluginsBean.getAllServerPlugins();
+ assert plugins.contains(p1) : plugins;
+ assert plugins.contains(p2) : plugins;
+ assetLazyInitializationException(plugins.get(plugins.indexOf(p1)));
+ assetLazyInitializationException(plugins.get(plugins.indexOf(p2)));
+
+ List<Integer> ids = new ArrayList<Integer>(2);
+ ids.add(p1.getId());
+ ids.add(p2.getId());
+ plugins = this.serverPluginsBean.getServerPluginsById(ids);
+ assert plugins.size() == 2 : plugins;
+ assert plugins.contains(p1) : plugins;
+ assert plugins.contains(p2) : plugins;
+ assetLazyInitializationException(plugins.get(plugins.indexOf(p1)));
+ assetLazyInitializationException(plugins.get(plugins.indexOf(p2)));
+
+ long lastTimestamp;
+ lastTimestamp = this.serverPluginsBean.getLastConfigurationChangeTimestamp(p1.getId());
+ assert lastTimestamp == getConfigurationLastModifiedTimestamp(p1);
+ lastTimestamp = this.serverPluginsBean.getLastConfigurationChangeTimestamp(p2.getId());
+ assert lastTimestamp == getConfigurationLastModifiedTimestamp(p2);
+ }
+
+ public void testUpdatePlugins() throws Exception {
+ ServerPlugin p1 = registerPlugin(1);
+ PluginKey p1key = new PluginKey(p1);
+
+ p1 = this.serverPluginsBean.getServerPlugin(p1key);
+ p1 = this.serverPluginsBean.getServerPluginRelationships(p1);
+
+ ServerPlugin p1update = this.serverPluginsBean.updateServerPluginExceptContent(getOverlord(), p1);
+ p1update = this.serverPluginsBean.getServerPluginRelationships(p1update);
+
+ assert p1update.getId() == p1.getId() : p1update;
+ assert p1update.getId() == p1.getId() : p1update;
+ assert p1update.getName().equals(p1.getName()) : p1update;
+ assert p1update.getName().equals(p1.getName()) : p1update;
+ assert p1update.getPluginConfiguration().equals(p1.getPluginConfiguration()) : p1update;
+ assert p1update.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration()) : p1update;
+ p1update.getPluginConfiguration().equals(p1.getPluginConfiguration());
+ p1update.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration());
+ }
+
+ public void testDisableEnablePlugins() throws Exception {
+ ServerPlugin p1 = registerPlugin(1);
+ ServerPlugin p2 = registerPlugin(2);
+ PluginKey p1key = new PluginKey(p1);
+ PluginKey p2key = new PluginKey(p2);
+
+ List<Integer> ids = new ArrayList<Integer>(2);
+ ids.add(p1.getId());
+ ids.add(p2.getId());
+ List<PluginKey> disabled = this.serverPluginsBean.disableServerPlugins(getOverlord(), ids);
+ assert disabled.size() == 2 : disabled;
+ assert disabled.contains(p1key) : disabled;
+ assert disabled.contains(p2key) : disabled;
+ ;
+ assert this.serverPluginsBean.getServerPlugin(p1key).getStatus() == PluginStatusType.INSTALLED; // still installed
+ assert this.serverPluginsBean.getServerPlugin(p2key).getStatus() == PluginStatusType.INSTALLED; // still installed
+ List<PluginKey> pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(false);
+ assert pluginKeys.contains(p1key) : pluginKeys;
+ assert pluginKeys.contains(p2key) : pluginKeys;
+ pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(true);
+ assert !pluginKeys.contains(p1key) : pluginKeys;
+ assert !pluginKeys.contains(p2key) : pluginKeys;
+
+ // re-enable them
+ this.serverPluginsBean.enableServerPlugins(getOverlord(), ids);
+ pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(true);
+ assert pluginKeys.contains(p1key) : pluginKeys;
+ assert pluginKeys.contains(p2key) : pluginKeys;
+ pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(false);
+ assert !pluginKeys.contains(p1key) : pluginKeys;
+ assert !pluginKeys.contains(p2key) : pluginKeys;
+
+ // make sure none of these enable/disable settings lost our config
+ ServerPlugin plugin = this.serverPluginsBean.getServerPlugin(p1key);
+ plugin = this.serverPluginsBean.getServerPluginRelationships(plugin);
+ assert plugin.getPluginConfiguration() != null; // no LazyInitException should be thrown!
+ assert plugin.getPluginConfiguration().equals(p1.getPluginConfiguration());
+ plugin = this.serverPluginsBean.getServerPlugin(p2key);
+ plugin = this.serverPluginsBean.getServerPluginRelationships(plugin);
+ assert plugin.getPluginConfiguration() != null; // no LazyInitException should be thrown!
+ assert plugin.getPluginConfiguration().equals(p1.getPluginConfiguration());
+ }
+
+ public void testUndeployPlugins() throws Exception {
+
+ int originalSize = this.serverPluginsBean.getAllServerPlugins().size();
+
+ PluginStatusType status;
+
+ PluginKey missingKey;
+ missingKey = new PluginKey(PluginDeploymentType.SERVER, new ServerPluginType(GenericPluginDescriptorType.class)
+ .stringify(), TEST_PLUGIN_NAME_PREFIX + "1");
+ status = this.serverPluginsBean.getServerPluginStatus(missingKey);
+ assert status == null;
+ missingKey = new PluginKey(PluginDeploymentType.SERVER, new ServerPluginType(GenericPluginDescriptorType.class)
+ .stringify(), TEST_PLUGIN_NAME_PREFIX + "2");
+ status = this.serverPluginsBean.getServerPluginStatus(missingKey);
+ assert status == null;
+
+ ServerPlugin p1 = registerPlugin(1);
+ ServerPlugin p2 = registerPlugin(2);
+ PluginKey p1key = new PluginKey(p1);
+ PluginKey p2key = new PluginKey(p2);
+
+ status = this.serverPluginsBean.getServerPluginStatus(p1key);
+ assert status == PluginStatusType.INSTALLED;
+ status = this.serverPluginsBean.getServerPluginStatus(p2key);
+ assert status == PluginStatusType.INSTALLED;
+
+ assert this.serverPluginsBean.getServerPlugins().size() == originalSize + 2;
+ assert this.serverPluginsBean.getAllServerPlugins().size() == originalSize + 2;
+
+ List<Integer> ids = new ArrayList<Integer>(2);
+ ids.add(p1.getId());
+ ids.add(p2.getId());
+ List<PluginKey> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
+ assert undeployed.size() == 2 : undeployed;
+ assert undeployed.contains(p1key) : undeployed;
+ assert undeployed.contains(p2key) : undeployed;
+ ServerPlugin p1deleted = getDeletedPluginInTx(p1.getName());
+ ServerPlugin p2deleted = getDeletedPluginInTx(p2.getName());
+ assert p1deleted.getStatus() == PluginStatusType.DELETED;
+ assert p2deleted.getStatus() == PluginStatusType.DELETED;
+
+ List<PluginKey> pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(false);
+ assert !pluginKeys.contains(p1key) : "deleted plugins should not be returned even here" + pluginKeys;
+ assert !pluginKeys.contains(p2key) : "deleted plugins should not be returned even here" + pluginKeys;
+ pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(true);
+ assert !pluginKeys.contains(p1.getName()) : pluginKeys;
+ assert !pluginKeys.contains(p2.getName()) : pluginKeys;
+
+ assert this.serverPluginsBean.getServerPlugins().size() == originalSize;
+ assert this.serverPluginsBean.getAllServerPlugins().size() == originalSize + 2;
+ }
+
+ public void testReRegisterPlugins() throws Exception {
+
+ PluginStatusType status;
+
+ PluginKey missingKey;
+ missingKey = new PluginKey(PluginDeploymentType.SERVER, new ServerPluginType(GenericPluginDescriptorType.class)
+ .stringify(), TEST_PLUGIN_NAME_PREFIX + "1");
+ status = this.serverPluginsBean.getServerPluginStatus(missingKey);
+ assert status == null;
+ missingKey = new PluginKey(PluginDeploymentType.SERVER, new ServerPluginType(GenericPluginDescriptorType.class)
+ .stringify(), TEST_PLUGIN_NAME_PREFIX + "2");
+ status = this.serverPluginsBean.getServerPluginStatus(missingKey);
+ assert status == null;
+
+ ServerPlugin p1 = registerPlugin(1);
+ ServerPlugin p2 = registerPlugin(2);
+ PluginKey p1key = new PluginKey(p1);
+ PluginKey p2key = new PluginKey(p2);
+
+ status = this.serverPluginsBean.getServerPluginStatus(p1key);
+ assert status == PluginStatusType.INSTALLED;
+ status = this.serverPluginsBean.getServerPluginStatus(p2key);
+ assert status == PluginStatusType.INSTALLED;
+
+ List<Integer> ids = new ArrayList<Integer>(2);
+ ids.add(p1.getId());
+ ids.add(p2.getId());
+ List<PluginKey> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
+ assert undeployed.size() == 2 : undeployed;
+ assert undeployed.contains(p1key) : undeployed;
+ assert undeployed.contains(p2key) : undeployed;
+ ServerPlugin p1deleted = getDeletedPluginInTx(p1.getName());
+ assert p1deleted.getStatus() == PluginStatusType.DELETED;
+ assert p1deleted.getPluginConfiguration() == null; // undeploy should have removed this
+ assert p1deleted.getScheduledJobsConfiguration() == null; // undeploy should have removed this
+ ServerPlugin p2deleted = getDeletedPluginInTx(p1.getName());
+ assert p2deleted.getStatus() == PluginStatusType.DELETED;
+ assert p2deleted.getPluginConfiguration() == null; // undeploy should have removed this
+ assert p2deleted.getScheduledJobsConfiguration() == null; // undeploy should have removed this
+
+ List<PluginKey> pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(false);
+ assert !pluginKeys.contains(p1key) : "deleted plugins should not be returned even here" + pluginKeys;
+ assert !pluginKeys.contains(p2key) : "deleted plugins should not be returned even here" + pluginKeys;
+ pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(true);
+ assert !pluginKeys.contains(p1key) : pluginKeys;
+ assert !pluginKeys.contains(p2key) : pluginKeys;
+
+ // purge them completely from the DB to prepare to re-register them
+ this.serverPluginsBean.purgeServerPlugin(getOverlord(), p1key);
+ this.serverPluginsBean.purgeServerPlugin(getOverlord(), p2key);
+
+ // we just purged the database, make sure our entity ID's are all zero, since the original IDs are gone
+ p1.setId(0);
+ p2.setId(0);
+ p1.setPluginConfiguration(p1.getPluginConfiguration().deepCopy(false));
+ p2.setPluginConfiguration(p2.getPluginConfiguration().deepCopy(false));
+ p1.setScheduledJobsConfiguration(p1.getScheduledJobsConfiguration().deepCopy(false));
+ p2.setScheduledJobsConfiguration(p2.getScheduledJobsConfiguration().deepCopy(false));
+
+ // re-register them now
+ ServerPlugin p1again = this.serverPluginsBean.registerServerPlugin(getOverlord(), p1, null);
+ ServerPlugin p2again = this.serverPluginsBean.registerServerPlugin(getOverlord(), p2, null);
+
+ pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(true);
+ assert pluginKeys.contains(p1key) : pluginKeys;
+ assert pluginKeys.contains(p2key) : pluginKeys;
+ assert p1again.getStatus() == PluginStatusType.INSTALLED;
+ assert p2again.getStatus() == PluginStatusType.INSTALLED;
+ pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(false);
+ assert !pluginKeys.contains(p1key) : pluginKeys;
+ assert !pluginKeys.contains(p2key) : pluginKeys;
+ }
+
+ private ServerPlugin registerPlugin(int index) throws Exception {
+ ServerPlugin plugin = new ServerPlugin(0, TEST_PLUGIN_NAME_PREFIX + index, "path", "displayName", true,
+ PluginStatusType.INSTALLED, "description", "help", "md5", "version", "ampsVersion",
+ createPluginConfiguration(), createScheduledJobsConfiguration(), new ServerPluginType(
+ GenericPluginDescriptorType.class).stringify(), System.currentTimeMillis(), System.currentTimeMillis());
+
+ plugin = this.serverPluginsBean.registerServerPlugin(getOverlord(), plugin, null);
+ assert plugin.getId() > 0;
+ assert plugin.isEnabled() == true;
+ assert plugin.getDeployment() == PluginDeploymentType.SERVER;
+ assert plugin.getStatus() == PluginStatusType.INSTALLED;
+ assert plugin.getPluginConfiguration() != null;
+ assert plugin.getScheduledJobsConfiguration() != null;
+ assert plugin.getType().equals(new ServerPluginType(GenericPluginDescriptorType.class).stringify());
+ return plugin;
+ }
+
+ private void assetLazyInitializationException(ServerPlugin plugin) {
+ try {
+ plugin.getPluginConfiguration().toString();
+ assert false : "Should have thrown a lazy-initialization exception - we didn't load config";
+ } catch (LazyInitializationException ok) {
+ }
+ try {
+ plugin.getScheduledJobsConfiguration().toString();
+ assert false : "Should have thrown a lazy-initialization exception - we didn't load config";
+ } catch (LazyInitializationException ok) {
+ }
+ }
+
+ private Configuration createPluginConfiguration() {
+ Configuration config = new Configuration();
+ config.put(new PropertySimple("simpleprop1", "simpleprop1value"));
+ return config;
+ }
+
+ private Configuration createScheduledJobsConfiguration() {
+ Configuration config = new Configuration();
+ PropertyMap map = new PropertyMap("jobname");
+ config.put(map);
+ map.put(new PropertySimple("methodName", "methodNameValue"));
+ return config;
+ }
+
+ private Subject getOverlord() {
+ return LookupUtil.getSubjectManager().getOverlord();
+ }
+
+ private ServerPlugin getDeletedPluginInTx(String pluginName) throws Exception {
+ EntityManager em = getEntityManager();
+ getTransactionManager().begin();
+ try {
+ Query q = em.createNamedQuery(ServerPlugin.QUERY_FIND_ANY_BY_NAME);
+ q.setParameter("name", pluginName);
+ return (ServerPlugin) q.getSingleResult();
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ private long getConfigurationLastModifiedTimestamp(ServerPlugin plugin) {
+ // determine the last time the plugin config or schedule jobs changed
+ // return 0 value if plugin doesn't have any config whatsoever
+ long timestamp = 0;
+
+ Configuration config = plugin.getPluginConfiguration();
+ if (config != null) {
+ timestamp = config.getModifiedTime();
+ }
+
+ config = plugin.getScheduledJobsConfiguration();
+ if (config != null && config.getModifiedTime() > timestamp) {
+ timestamp = config.getModifiedTime();
+ }
+
+ return timestamp;
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerSyncContentProviderTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerSyncContentProviderTest.java
new file mode 100644
index 0000000..9599bd1
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerSyncContentProviderTest.java
@@ -0,0 +1,321 @@
+/*
+* RHQ Management Platform
+* Copyright (C) 2009 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.enterprise.server.plugin.pc.content;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.transaction.TransactionManager;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.content.ContentSource;
+import org.rhq.core.domain.content.ContentSourceType;
+import org.rhq.core.domain.content.PackageVersionContentSource;
+import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.content.RepoGroup;
+import org.rhq.core.domain.content.RepoRelationship;
+import org.rhq.core.domain.content.RepoRepoGroup;
+import org.rhq.core.domain.content.RepoRepoRelationship;
+import org.rhq.core.domain.criteria.RepoCriteria;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
+import org.rhq.enterprise.server.content.RepoManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * @author Jason Dobies
+ */
+public class ContentProviderManagerSyncContentProviderTest extends AbstractEJB3Test {
+
+ private static final String CUSTOM_IMPORTED_REPO_NAME = "customImportedRepo";
+
+ private static final String PREVIOUS_CANDIDATE_REPO_NAME = "testPreviousCandidate";
+
+ private TestContentServerPluginService pluginService;
+
+ // The following variables need to be cleaned up at the end of the test
+
+ private ContentSourceType testSourceType;
+
+ private ContentSource syncSource; // Source that is syncced in this test
+ private ContentSource nonSyncSource; // Existing source NOT being syncced in this test
+
+ private Repo nonCandidateOnOtherSource; // Should NOT appear in the sync packages call since its a different source
+
+ private List<Integer> reposToDelete = new ArrayList<Integer>();
+ private List<Integer> repoGroupsToDelete = new ArrayList<Integer>();
+ private Integer repoId;
+ private Integer relatedRepoId;
+
+ @BeforeMethod
+ public void setupBeforeMethod() throws Exception {
+
+ // Plugin service setup
+ prepareScheduler();
+ pluginService = new TestContentServerPluginService(this);
+
+ // Because of the (current) transaction settings of some of the nested methods (i.e. REQUIRES_NEW),
+ // this test must commit its data and clean up after itself, as compared to simply rolling back the
+ // transaction at the end.
+ TransactionManager tx = getTransactionManager();
+ tx.begin();
+ EntityManager entityManager = getEntityManager();
+
+ ContentSourceManagerLocal contentManager = LookupUtil.getContentSourceManager();
+ RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ Subject overlord = subjectManager.getOverlord();
+
+ // Create a sample content source type that will be used in this test
+ testSourceType = new ContentSourceType("testType");
+ entityManager.persist(testSourceType);
+ entityManager.flush();
+
+ //need to actually commit the tx so that the subsequent code can see the new entry in
+ //the database
+ tx.commit();
+
+ tx.begin();
+ //new entity manager associated with the new tx
+ entityManager = getEntityManager();
+
+ // Add a content source to sync in this test
+ syncSource = new ContentSource("testSource1", testSourceType);
+ contentManager.simpleCreateContentSource(overlord, syncSource);
+ entityManager.flush();
+
+ // Add an extra content source that isn't being syncced
+ nonSyncSource = new ContentSource("testSource2", testSourceType);
+ contentManager.simpleCreateContentSource(overlord, nonSyncSource);
+ entityManager.flush();
+
+ // Add existing repo against other source (this shouldn't show up in the request for packages)
+ nonCandidateOnOtherSource = new Repo("nonCandidateOnOtherSource");
+ nonCandidateOnOtherSource.setCandidate(false);
+ nonCandidateOnOtherSource.addContentSource(nonSyncSource);
+ repoManager.createRepo(overlord, nonCandidateOnOtherSource);
+
+ tx.commit();
+ }
+
+ @AfterMethod
+ public void tearDownAfterMethod() throws Exception {
+
+ try {
+ // Transactional stuff
+ TransactionManager tx = getTransactionManager();
+ tx.begin();
+ EntityManager entityManager = getEntityManager();
+
+ RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ Subject overlord = subjectManager.getOverlord();
+
+ // Delete the repo relationships
+ entityManager.createNamedQuery(RepoRepoRelationship.DELETE_BY_REPO_ID).setParameter("repoId", repoId)
+ .executeUpdate();
+
+ entityManager.createNamedQuery(RepoRelationship.DELETE_BY_RELATED_REPO_ID)
+ .setParameter("relatedRepoId", relatedRepoId).executeUpdate();
+
+ // Delete any repos that were created in this test
+ for (Integer repoId : reposToDelete) {
+ repoManager.deleteRepo(overlord, repoId);
+ }
+ reposToDelete.clear();
+
+ // Delete any repo groups that were created in this test
+ for (Integer repoGroupId : repoGroupsToDelete) {
+ repoManager.deleteRepoGroup(overlord, repoGroupId);
+ }
+ repoGroupsToDelete.clear();
+
+ // First disassociate packages from the content source
+ entityManager.createNamedQuery(PackageVersionContentSource.DELETE_BY_CONTENT_SOURCE_ID)
+ .setParameter("contentSourceId", syncSource.getId()).executeUpdate();
+
+ // Delete the existing repos
+ nonCandidateOnOtherSource = entityManager.find(Repo.class, nonCandidateOnOtherSource.getId());
+ entityManager.remove(nonCandidateOnOtherSource);
+
+ // Delete the source that was created
+ syncSource = entityManager.find(ContentSource.class, syncSource.getId());
+ entityManager.remove(syncSource);
+
+ nonSyncSource = entityManager.find(ContentSource.class, nonSyncSource.getId());
+ entityManager.remove(nonSyncSource);
+
+ // Delete the fake source type
+ testSourceType = entityManager.find(ContentSourceType.class, testSourceType.getId());
+ entityManager.remove(testSourceType);
+
+ tx.commit();
+ } finally {
+ // Plugin service teardown
+ unprepareServerPluginService();
+ unprepareScheduler();
+ }
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void synchronizeContentSource() throws Exception {
+
+ try {
+ getTransactionManager().begin();
+
+ // Setup
+ // --------------------------------------------
+ RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ Subject overlord = subjectManager.getOverlord();
+
+ // -> Add an already imported repo to the system so it already exists when the report introduces it
+ Repo existingImportedRepo = new Repo(TestContentProvider.EXISTING_IMPORTED_REPO_NAME);
+ existingImportedRepo.setCandidate(false);
+ repoManager.createRepo(overlord, existingImportedRepo);
+
+ // -> Add an already imported repo that wasn't introduced from the report; a user created repo
+ Repo customImportedRepo = new Repo(CUSTOM_IMPORTED_REPO_NAME);
+ customImportedRepo.setCandidate(false);
+ customImportedRepo.addContentSource(syncSource);
+ repoManager.createRepo(overlord, customImportedRepo);
+
+ // -> Simulate a candidate repo from a previous import that will be in this report as well
+ Repo existingCandidateRepo = new Repo(TestContentProvider.EXISTING_CANDIDATE_REPO_NAME);
+ existingCandidateRepo.setCandidate(true);
+ repoManager.createRepo(overlord, existingCandidateRepo);
+
+ // -> Simulate a candidate repo from a previous import that will *NOT* be in this report
+ Repo previousRepo = new Repo(PREVIOUS_CANDIDATE_REPO_NAME);
+ previousRepo.setCandidate(true);
+ previousRepo.addContentSource(syncSource);
+ repoManager.createRepo(overlord, previousRepo);
+
+ // Test
+ // --------------------------------------------
+ // TestContentProviderManager providerManager = new TestContentProviderManager();
+ pluginService.getContentProviderManager().testConnection(syncSource.getId());
+
+ boolean completed = pluginService.getContentProviderManager()
+ .synchronizeContentProvider(syncSource.getId());
+ assert completed;
+
+ // Verify RepoGroups
+ RepoGroup repoGroup = repoManager.getRepoGroupByName("testRepoGroup");
+ assert repoGroup != null;
+ repoGroupsToDelete.add(repoGroup.getId());
+
+ // Verify Repos
+ // --------------------------------------------
+ List<Repo> retrievedRepos;
+
+ // -> Simple Repo
+ retrievedRepos = repoManager.getRepoByName("testRepo1");
+ assert retrievedRepos.size() == 1;
+ assert retrievedRepos.get(0).isCandidate();
+ reposToDelete.add(retrievedRepos.get(0).getId());
+
+ // -> Repo in a group
+ retrievedRepos = repoManager.getRepoByName("testRepo2");
+ assert retrievedRepos.size() == 1;
+ assert retrievedRepos.get(0).isCandidate();
+ reposToDelete.add(retrievedRepos.get(0).getId());
+
+ Repo repoInGroup = retrievedRepos.get(0);
+
+ RepoCriteria findWithRepoGroup = new RepoCriteria();
+ findWithRepoGroup.fetchRepoRepoGroups(true);
+ findWithRepoGroup.addFilterId(repoInGroup.getId());
+
+ PageList<Repo> repoPageList = repoManager.findReposByCriteria(overlord, findWithRepoGroup);
+ repoInGroup = repoPageList.get(0);
+
+ Set<RepoRepoGroup> repoGroups = repoInGroup.getRepoRepoGroups();
+ assert repoGroups.size() == 1;
+
+ RepoRepoGroup repoRepoGroup = repoGroups.iterator().next();
+ assert repoRepoGroup.getRepoRepoGroupPK().getRepoGroup().getName().equals("testRepoGroup");
+ assert repoRepoGroup.getRepoRepoGroupPK().getRepo().getName().equals("testRepo2");
+
+ // -> Repo with a parent
+ retrievedRepos = repoManager.getRepoByName("testRepo3");
+ assert retrievedRepos.size() == 1;
+ assert retrievedRepos.get(0).isCandidate();
+ reposToDelete.add(retrievedRepos.get(0).getId());
+ relatedRepoId = retrievedRepos.get(0).getId();
+
+ retrievedRepos = repoManager.getRepoByName("testRepo4");
+ assert retrievedRepos.size() == 1;
+ assert retrievedRepos.get(0).isCandidate();
+ reposToDelete.add(retrievedRepos.get(0).getId());
+ repoId = retrievedRepos.get(0).getId();
+
+ RepoCriteria findWithRelationships = new RepoCriteria();
+ findWithRelationships.addFilterName("testRepo4");
+ findWithRelationships.fetchRepoRepoRelationships(true);
+ PageList<Repo> childRepoList = repoManager.findReposByCriteria(overlord, findWithRelationships);
+ assert childRepoList.size() == 1;
+
+ Repo childRepo = childRepoList.get(0);
+ Set<RepoRepoRelationship> childRepoRepoRelationship = childRepo.getRepoRepoRelationships();
+ assert childRepoRepoRelationship.size() == 1;
+
+ // -> Repo that was already imported in the system (make sure there is still only one)
+ retrievedRepos = repoManager.getRepoByName(TestContentProvider.EXISTING_IMPORTED_REPO_NAME);
+ assert retrievedRepos.size() == 1;
+ reposToDelete.add(retrievedRepos.get(0).getId());
+
+ // -> Repo that was imported but not in the report (i.e. a user created repo)
+ retrievedRepos = repoManager.getRepoByName(CUSTOM_IMPORTED_REPO_NAME);
+ assert retrievedRepos.size() == 1;
+ reposToDelete.add(retrievedRepos.get(0).getId());
+
+ // -> Repo that was already a candidate in the system (make sure it's not added again)
+ retrievedRepos = repoManager.getRepoByName(TestContentProvider.EXISTING_CANDIDATE_REPO_NAME);
+ assert retrievedRepos.size() == 1;
+ reposToDelete.add(retrievedRepos.get(0).getId());
+
+ // -> Make sure a repo that was previously a candidate of this content source but did not
+ // come back in the latest sync is removed
+ retrievedRepos = repoManager.getRepoByName(PREVIOUS_CANDIDATE_REPO_NAME);
+ assert retrievedRepos.size() == 0;
+
+ // -> Non-existent repo
+ retrievedRepos = repoManager.getRepoByName("testRepoFoo");
+ assert retrievedRepos.size() == 0;
+
+ getTransactionManager().commit();
+ } catch (Throwable t) {
+ getTransactionManager().rollback();
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerSyncRepoTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerSyncRepoTest.java
new file mode 100644
index 0000000..65154bb
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerSyncRepoTest.java
@@ -0,0 +1,312 @@
+/*
+* RHQ Management Platform
+* Copyright (C) 2009 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.enterprise.server.plugin.pc.content;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import javax.transaction.TransactionManager;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.content.ContentSource;
+import org.rhq.core.domain.content.ContentSourceType;
+import org.rhq.core.domain.content.Distribution;
+import org.rhq.core.domain.content.DistributionFile;
+import org.rhq.core.domain.content.DownloadMode;
+import org.rhq.core.domain.content.Package;
+import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.content.RepoDistribution;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.content.ContentManagerLocal;
+import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
+import org.rhq.enterprise.server.content.DistributionManagerLocal;
+import org.rhq.enterprise.server.content.RepoManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * @author Jason Dobies
+ */
+public class ContentProviderManagerSyncRepoTest extends AbstractEJB3Test {
+
+ private static final boolean TESTS_ENABLED = true;
+
+ private TestContentServerPluginService pluginService;
+
+ private TestContentProvider contentProvider1 = new TestContentProvider();
+ private TestContentProvider contentProvider2 = new TestContentProvider();
+
+ // The following variables need to be cleaned up at the end of the test
+
+ private ContentSourceType contentSourceType;
+ private PackageType packageType;
+ private ResourceType resourceType;
+
+ private List<ContentSource> repoContentSources = new ArrayList<ContentSource>();
+ private Repo repoToSync;
+
+ @BeforeMethod
+ public void setupBeforeMethod() throws Exception {
+
+ // Plugin service setup
+ prepareScheduler();
+ pluginService = new TestContentServerPluginService(this);
+
+ TransactionManager tx = getTransactionManager();
+ try {
+ tx.begin();
+ EntityManager entityManager = getEntityManager();
+
+ ContentManagerLocal contentManager = LookupUtil.getContentManager();
+ ContentSourceManagerLocal contentSourceManager = LookupUtil.getContentSourceManager();
+ RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
+ ResourceTypeManagerLocal resourceTypeManager = LookupUtil.getResourceTypeManager();
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ Subject overlord = subjectManager.getOverlord();
+
+ // protect if it aleady exists due to a failed run
+ contentSourceType = contentSourceManager.getContentSourceType("testType");
+ if (null == contentSourceType) {
+ // Create a sample content source type that will be used in this test
+ contentSourceType = new ContentSourceType("testType");
+ entityManager.persist(contentSourceType);
+ entityManager.flush();
+ }
+
+ // protect if it aleady exists due to a failed run
+ ContentSource cs1 = contentSourceManager.getContentSourceByNameAndType(overlord, "contentSource1",
+ "testType");
+ if (null == cs1) {
+ // A repo sync will query all providers for that repo, so add multiple providers
+ cs1 = new ContentSource("contentSource1", contentSourceType);
+ cs1.setDownloadMode(DownloadMode.DATABASE);
+ cs1 = contentSourceManager.simpleCreateContentSource(overlord, cs1);
+ }
+ ContentSource cs2 = contentSourceManager.getContentSourceByNameAndType(overlord, "contentSource2",
+ "testType");
+ if (null == cs2) {
+ cs2 = new ContentSource("contentSource2", contentSourceType);
+ cs2.setDownloadMode(DownloadMode.DATABASE);
+ cs2 = contentSourceManager.simpleCreateContentSource(overlord, cs2);
+ }
+
+ pluginService.associateContentProvider(cs1, contentProvider1);
+ pluginService.associateContentProvider(cs2, contentProvider2);
+
+ repoContentSources.add(cs1);
+ repoContentSources.add(cs2);
+
+ // Create the package type packages will be created against
+ resourceType = resourceTypeManager.getResourceTypeByNameAndPlugin(TestContentProvider.RESOURCE_TYPE_NAME,
+ TestContentProvider.RESOURCE_TYPE_PLUGIN_NAME);
+ if (null == resourceType) {
+ resourceType = new ResourceType(TestContentProvider.RESOURCE_TYPE_NAME,
+ TestContentProvider.RESOURCE_TYPE_PLUGIN_NAME, ResourceCategory.PLATFORM, null);
+ entityManager.persist(resourceType);
+ entityManager.flush();
+ }
+
+ List<PackageType> packageTypes = contentManager.findPackageTypes(overlord,
+ TestContentProvider.RESOURCE_TYPE_NAME, TestContentProvider.RESOURCE_TYPE_PLUGIN_NAME);
+ if (!packageTypes.isEmpty()) {
+ packageType = packageTypes.get(0);
+ } else {
+ packageType = new PackageType(TestContentProvider.PACKAGE_TYPE_NAME, resourceType);
+ entityManager.persist(packageType);
+ }
+
+ // Create the repo to be synced
+ List<Repo> repos = repoManager.getRepoByName(TestContentProvider.REPO_WITH_PACKAGES);
+ if (!repos.isEmpty()) {
+ repoToSync = repos.get(0);
+ } else {
+ Repo repo = new Repo(TestContentProvider.REPO_WITH_PACKAGES);
+ repo.addContentSource(cs1);
+ // repo.addContentSource(cs2); Disabled until we implement a second test content source to return new stuff
+ repoToSync = repoManager.createRepo(overlord, repo);
+ }
+
+ tx.commit();
+ } catch (Throwable t) {
+ tx.rollback();
+ // rethrow because if we swallow the exception then tests proceed to execute when they probably should not
+ throw new RuntimeException(t);
+ }
+ }
+
+ @AfterMethod
+ public void tearDownAfterMethod() throws Exception {
+ try {
+
+ TransactionManager tx = getTransactionManager();
+ tx.begin();
+ EntityManager entityManager = getEntityManager();
+
+ Query query;
+
+ ContentSourceManagerLocal contentSourceManagerLocal = LookupUtil.getContentSourceManager();
+ RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
+ DistributionManagerLocal distroManager = LookupUtil.getDistributionManagerLocal();
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ Subject overlord = subjectManager.getOverlord();
+
+ // Delete all distributions
+ distroManager.deleteDistributionMappingsForRepo(overlord, repoToSync.getId());
+
+ for (String distroLabel : TestContentProvider.DISTRIBUTIONS.keySet()) {
+ Distribution distro = distroManager.getDistributionByLabel(distroLabel);
+ if (distro != null) {
+ // Delete the files
+ query = entityManager.createNamedQuery(DistributionFile.DELETE_BY_DIST_ID);
+ query.setParameter("distId", distro.getId());
+ query.executeUpdate();
+
+ // Delete the actual distro
+ distroManager.deleteDistributionByDistId(overlord, distro.getId());
+ }
+ }
+
+ // Delete all package version <-> content source mappings
+ for (ContentSource source : repoContentSources) {
+ contentSourceManagerLocal.deleteContentSource(overlord, source.getId());
+ }
+ repoContentSources.clear();
+
+ // Delete the repo
+ repoManager.deleteRepo(overlord, repoToSync.getId());
+
+ // Delete any packages that were created
+ for (ContentProviderPackageDetails details : TestContentProvider.PACKAGES.values()) {
+ String packageName = details.getContentProviderPackageDetailsKey().getName();
+
+ query = entityManager.createNamedQuery(Package.QUERY_FIND_BY_NAME_PKG_TYPE_ID);
+ query.setParameter("name", packageName);
+ query.setParameter("packageTypeId", packageType.getId());
+
+ Package p = (Package) query.getSingleResult();
+ entityManager.remove(p);
+ }
+
+ // Delete the package type
+ packageType = entityManager.find(PackageType.class, packageType.getId());
+ entityManager.remove(packageType);
+
+ resourceType = entityManager.find(ResourceType.class, resourceType.getId());
+ entityManager.remove(resourceType);
+
+ // Delete the content source type
+ contentSourceType = entityManager.find(ContentSourceType.class, contentSourceType.getId());
+ entityManager.remove(contentSourceType);
+
+ tx.commit();
+
+ // Cleanup providers between tests
+ contentProvider1.reset();
+ contentProvider2.reset();
+
+ } finally {
+ // Plugin service teardown
+ unprepareServerPluginService();
+ unprepareScheduler();
+ }
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ @SuppressWarnings("unchecked")
+ public void synchronizeRepo() throws Exception {
+
+ // Test
+ // --------------------------------------------
+ boolean completed = pluginService.getContentProviderManager().synchronizeRepo(repoToSync.getId());
+ assert completed;
+
+ // Verify
+ // --------------------------------------------
+
+ // Make sure the proper calls were made into the provider
+ assert contentProvider1.getLogSynchronizePackagesRepos().size() == 1 : "Expected: 1, Found: "
+ + contentProvider1.getLogSynchronizePackagesRepos().size();
+
+ // Need to add in distro packages being syncced
+ assert contentProvider1.getLogGetInputStreamLocations().size() == TestContentProvider.PACKAGE_COUNT_FOR_BITS : "Expected: "
+ + TestContentProvider.PACKAGE_COUNT_FOR_BITS
+ + ", Found: "
+ + contentProvider1.getLogGetInputStreamLocations().size();
+
+ // Make sure all of the packages were added
+ TransactionManager tx = getTransactionManager();
+ tx.begin();
+ EntityManager entityManager = getEntityManager();
+
+ Query query = entityManager.createNamedQuery(PackageVersion.QUERY_FIND_BY_REPO_ID);
+ query.setParameter("repoId", repoToSync.getId());
+ List<PackageVersion> repoPackages = query.getResultList();
+
+ assert repoPackages.size() == TestContentProvider.PACKAGES.size() : "Expected: "
+ + TestContentProvider.PACKAGES.size() + ", Found: " + repoPackages.size();
+
+ // Make sure all of the distributions were added
+ query = entityManager.createNamedQuery(RepoDistribution.QUERY_FIND_BY_REPO_ID);
+ query.setParameter("repoId", repoToSync.getId());
+ List<RepoDistribution> repoDistributions = query.getResultList();
+
+ assert repoDistributions.size() == TestContentProvider.DISTRIBUTIONS.size() : "Expected: "
+ + TestContentProvider.DISTRIBUTIONS.size() + ", Found: " + repoDistributions.size();
+
+ // Make sure each distribution has the correct files associated
+ int distro1FileCount = countDistroFiles(entityManager, TestContentProvider.DISTRIBUTION_1_LABEL);
+ assert distro1FileCount == 2 : "Expected: 2, Found: " + distro1FileCount;
+
+ int distro2FileCount = countDistroFiles(entityManager, TestContentProvider.DISTRIBUTION_2_LABEL);
+ assert distro2FileCount == 1 : "Expected: 1, Found: " + distro1FileCount;
+
+ tx.rollback();
+ }
+
+ private int countDistroFiles(EntityManager entityManager, String label) {
+ Query query = entityManager.createNamedQuery(Distribution.QUERY_FIND_BY_DIST_LABEL);
+ query.setParameter("label", label);
+ Distribution distro = (Distribution) query.getSingleResult();
+
+ query = entityManager.createNamedQuery(DistributionFile.SELECT_BY_DIST_ID);
+ query.setParameter("distId", distro.getId());
+ List distroFiles = query.getResultList();
+
+ if (distroFiles == null) {
+ return 0;
+ } else {
+ return distroFiles.size();
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentSourcePackageDetailsKeyTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentSourcePackageDetailsKeyTest.java
new file mode 100644
index 0000000..df8acb2
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentSourcePackageDetailsKeyTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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, 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.enterprise.server.plugin.pc.content;
+
+import org.testng.annotations.Test;
+
+@Test
+public class ContentSourcePackageDetailsKeyTest {
+ public void testEqualsHashcode() {
+ ContentProviderPackageDetailsKey key1;
+ ContentProviderPackageDetailsKey key2;
+
+ key1 = new ContentProviderPackageDetailsKey("name1", "ver1", "pt1", "arch1", "rt1", "plugin1");
+ key2 = new ContentProviderPackageDetailsKey("name1", "ver1", "pt1", "arch1", "rt1", "plugin1");
+ assert key1.equals(key2);
+ assert key2.equals(key1);
+ assert key1.hashCode() == key2.hashCode();
+
+ key2 = new ContentProviderPackageDetailsKey("BLAH", "ver1", "pt1", "arch1", "rt1", "plugin1");
+ assert !key1.equals(key2);
+ assert !key2.equals(key1);
+ assert key1.hashCode() != key2.hashCode();
+
+ key2 = new ContentProviderPackageDetailsKey("name1", "BLAH", "pt1", "arch1", "rt1", "plugin1");
+ assert !key1.equals(key2);
+ assert !key2.equals(key1);
+ assert key1.hashCode() != key2.hashCode();
+
+ key2 = new ContentProviderPackageDetailsKey("name1", "ver1", "BLAH", "arch1", "rt1", "plugin1");
+ assert !key1.equals(key2);
+ assert !key2.equals(key1);
+ assert key1.hashCode() != key2.hashCode();
+
+ key2 = new ContentProviderPackageDetailsKey("name1", "ver1", "pt1", "BLAH", "rt1", "plugin1");
+ assert !key1.equals(key2);
+ assert !key2.equals(key1);
+ assert key1.hashCode() != key2.hashCode();
+
+ key2 = new ContentProviderPackageDetailsKey("name1", "ver1", "pt1", "arch1", "BLAH", "plugin1");
+ assert !key1.equals(key2);
+ assert !key2.equals(key1);
+ assert key1.hashCode() != key2.hashCode();
+
+ key2 = new ContentProviderPackageDetailsKey("name1", "ver1", "pt1", "arch1", "rt1", "BLAH");
+ assert !key1.equals(key2);
+ assert !key2.equals(key1);
+ assert key1.hashCode() != key2.hashCode();
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentProvider.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentProvider.java
new file mode 100644
index 0000000..749f73b
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentProvider.java
@@ -0,0 +1,351 @@
+package org.rhq.enterprise.server.plugin.pc.content;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.content.PackageDetailsKey;
+import org.rhq.core.domain.content.PackageVersion;
+
+public class TestContentProvider implements ContentProvider, PackageSource, RepoSource, DistributionSource {
+
+ /**
+ * Packages returned in a call to
+ * {@link #synchronizePackages(String, PackageSyncReport, Collection)} will
+ * indicate they are of this type. Any test attempting to call this
+ * synchronize method should be sure to create a package type of this name
+ * in the database prior to calling it.
+ */
+ public static final String PACKAGE_TYPE_NAME = "testContentProviderFakePackage";
+
+ /**
+ * In order to create a package type (as needed to create the type indicated
+ * in {@link #PACKAGE_TYPE_NAME}), the package type must be created as part
+ * of this resource type.
+ */
+ public static final String RESOURCE_TYPE_NAME = "testContentProviderFakeResourceType";
+
+ /**
+ * In order to create a resource type (as needed to create the type
+ * indicated in {@link #RESOURCE_TYPE_NAME}), this resource type plugin name
+ * should be used.
+ */
+ public static final String RESOURCE_TYPE_PLUGIN_NAME = "testContentProviderFakeResourceTypePlugin";
+
+ public static final String EXISTING_IMPORTED_REPO_NAME = "testRepoImportedExisting";
+ public static final String EXISTING_CANDIDATE_REPO_NAME = "testRepoCandidateExisting";
+
+ /**
+ * This content source will return packages when asked to synchronize a
+ * repo with this name.
+ */
+ public static final String REPO_WITH_PACKAGES = EXISTING_IMPORTED_REPO_NAME;
+
+ /**
+ * This content source will return distributions when asked to synchronize
+ * a repo with this name.
+ */
+ public static final String REPO_WITH_DISTRIBUTIONS = EXISTING_IMPORTED_REPO_NAME;
+
+ /**
+ * Collection of packages that will be returned from calling
+ * {@link #synchronizePackages(String, PackageSyncReport, Collection)}
+ * passing in a repo with the name {@link #REPO_WITH_PACKAGES}.
+ */
+ public static final Map<ContentProviderPackageDetailsKey, ContentProviderPackageDetails> PACKAGES = new HashMap<ContentProviderPackageDetailsKey, ContentProviderPackageDetails>(
+ 2);
+ static {
+
+ ContentProviderPackageDetailsKey key1 = new ContentProviderPackageDetailsKey("package1", "version1",
+ PACKAGE_TYPE_NAME, "noarch", RESOURCE_TYPE_NAME, RESOURCE_TYPE_PLUGIN_NAME);
+ ContentProviderPackageDetails details1 = new ContentProviderPackageDetails(key1);
+ details1.setFileName("filename1");
+ details1.setFileSize(4L);
+ details1.setLocation("foo1");
+
+ PACKAGES.put(key1, details1);
+
+ ContentProviderPackageDetailsKey key2 = new ContentProviderPackageDetailsKey("package2", "version2",
+ PACKAGE_TYPE_NAME, "noarch", RESOURCE_TYPE_NAME, RESOURCE_TYPE_PLUGIN_NAME);
+ ContentProviderPackageDetails details2 = new ContentProviderPackageDetails(key2);
+ details2.setFileName("filename2");
+ details2.setFileSize(4L);
+ details2.setLocation("foo2");
+
+ PACKAGES.put(key2, details2);
+ }
+
+ /**
+ * Number of associated distribution files: 2
+ */
+ public static final String DISTRIBUTION_1_LABEL = "distribution1";
+
+ /**
+ * Number of associated distribution files: 1
+ */
+ public static final String DISTRIBUTION_2_LABEL = "distribution2";
+
+ public static final Map<String, DistributionDetails> DISTRIBUTIONS = new HashMap<String, DistributionDetails>(2);
+ static {
+
+ // Note: The type "kickstart" should already be in the database from
+ // installation
+
+ /*
+ * Note: The md5 sums below will be used to determine if the file needs
+ * to be loaded through a call to getPackageBits. I set these to an
+ * invalid MD5 so they will *always* be downloaded.
+ */
+ DistributionDetails dis1 = new DistributionDetails(DISTRIBUTION_1_LABEL, "kickstart");
+ dis1.setDistributionPath("/kstrees");
+ DistributionFileDetails file11 = new DistributionFileDetails("dist1file1", System.currentTimeMillis(), "zzz");
+ DistributionFileDetails file12 = new DistributionFileDetails("dist1file2", System.currentTimeMillis(), "zzz");
+ dis1.addFile(file11);
+ dis1.addFile(file12);
+
+ DISTRIBUTIONS.put(dis1.getLabel(), dis1);
+
+ DistributionDetails dis2 = new DistributionDetails(DISTRIBUTION_2_LABEL, "kickstart");
+ dis2.setDistributionPath("/kstrees");
+ DistributionFileDetails file21 = new DistributionFileDetails("dist2file1", System.currentTimeMillis(), "zzz");
+ dis2.addFile(file21);
+
+ DISTRIBUTIONS.put(dis2.getLabel(), dis2);
+ }
+
+ public static final int PACKAGE_COUNT_FOR_BITS = PACKAGES.size() + 3; // packages
+ // +
+ // number
+ // of
+ // distro
+ // files
+
+ /**
+ * If <code>true</code>, the call to {@link #testConnection()} will throw an
+ * exception.
+ */
+ private boolean failTest = false;
+
+ // Set this value if you want the packageSync step to take a while
+ private int longRunningSynchSleep = 0;
+
+ /**
+ * Holds a list of all repo names that were passed into calls to
+ * {@link #synchronizePackages(String, PackageSyncReport, Collection)} to
+ * track when and with what data these calls are made.
+ */
+ private List<String> logSynchronizePackagesRepos = new ArrayList<String>();
+
+ /**
+ * Holds a list of all locations passed into calls to
+ * {@link #getInputStream(String)}.
+ */
+ private List<String> logGetInputStreamLocations = new ArrayList<String>();
+
+ /**
+ * Holds a list of all repo names that were passed into calls to
+ * {@link #synchronizeDistribution(String, DistributionSyncReport, Collection)}
+ * .
+ */
+ private List<String> logSynchronizeDistroRepos = new ArrayList<String>();
+
+ public void initialize(Configuration configuration) throws Exception {
+ // No-op
+ }
+
+ public void shutdown() {
+ // No-op
+ }
+
+ public void testConnection() throws Exception {
+
+ if (failTest) {
+ throw new Exception("Mock content source configured to fail the connection test");
+ }
+
+ System.out.println("Connection tested.");
+ }
+
+ public RepoImportReport importRepos() throws Exception {
+ RepoImportReport report = new RepoImportReport();
+
+ // Create a repo group in the system
+ RepoGroupDetails group1 = new RepoGroupDetails("testRepoGroup", "family");
+ report.addRepoGroup(group1);
+
+ // Simple repo
+ RepoDetails repo1 = new RepoDetails("testRepo1");
+ repo1.setDescription("First test repo");
+ report.addRepo(repo1);
+
+ // Repo belonging to a group that was created in the sync
+ RepoDetails repo2 = new RepoDetails("testRepo2");
+ repo2.setRepoGroup("testRepoGroup");
+ report.addRepo(repo2);
+
+ // Repo with a parent repo created in this sync
+ // Parent explicitly added to this list *after* this child to ensure
+ // that's not a problem
+ RepoDetails repo3 = new RepoDetails("testRepo3");
+ report.addRepo(repo3);
+
+ RepoDetails repo4 = new RepoDetails("testRepo4");
+ repo4.setParentRepoName("testRepo3");
+ report.addRepo(repo4);
+
+ // Repo that was already imported in the system
+ RepoDetails repo5 = new RepoDetails(EXISTING_IMPORTED_REPO_NAME);
+ report.addRepo(repo5);
+
+ // Repo that was already a candidate in the system
+ RepoDetails repo6 = new RepoDetails(EXISTING_CANDIDATE_REPO_NAME);
+ report.addRepo(repo6);
+
+ return report;
+ }
+
+ public void synchronizePackages(String repoName, PackageSyncReport report,
+ Collection<ContentProviderPackageDetails> existingPackages) throws SyncException, InterruptedException {
+
+ logSynchronizePackagesRepos.add(repoName);
+
+ if (!REPO_WITH_PACKAGES.equals(repoName)) {
+ return;
+ }
+
+ // For each package this provider wants to introduce, make sure it
+ // doesn't exist already.
+ // This basically means the report will only ever contain "added"
+ // packages and will only do so
+ // on the first call to this method. This will likely be changed as new
+ // requirements emerge.
+ for (ContentProviderPackageDetails pkg : PACKAGES.values()) {
+
+ ContentProviderPackageDetails existingPackage = findDetailsByKey(pkg.getContentProviderPackageDetailsKey(),
+ existingPackages);
+
+ if (existingPackage == null) {
+ report.addNewPackage(pkg);
+ }
+
+ }
+ System.out.println(this.getClass().getSimpleName() + ".synchronizePackages sleeping for "
+ + this.longRunningSynchSleep + " seconds");
+ Thread.sleep(this.longRunningSynchSleep);
+ }
+
+ public InputStream getInputStream(String location) throws Exception {
+
+ logGetInputStreamLocations.add(location);
+
+ String seed = "Test Bits " + System.currentTimeMillis();
+ ByteArrayInputStream bais = new ByteArrayInputStream(seed.getBytes());
+ BufferedInputStream bis = new BufferedInputStream(bais);
+
+ return bis;
+ }
+
+ public void synchronizeDistribution(String repoName, DistributionSyncReport report,
+ Collection<DistributionDetails> existingDistros) throws SyncException, InterruptedException {
+
+ logSynchronizeDistroRepos.add(repoName);
+
+ if (!REPO_WITH_DISTRIBUTIONS.equals(repoName)) {
+ return;
+ }
+
+ for (DistributionDetails distro : DISTRIBUTIONS.values()) {
+
+ boolean existing = false;
+ for (DistributionDetails existingDistro : existingDistros) {
+ if (distro.getLabel().equals(existingDistro.getLabel())) {
+ existing = true;
+ break;
+ }
+ }
+
+ if (!existing) {
+ report.addDistro(distro);
+ }
+ }
+ System.out.println(this.getClass().getSimpleName() + ".synchronizeDistribution sleeping for "
+ + this.longRunningSynchSleep + " seconds");
+
+ Thread.sleep(this.longRunningSynchSleep);
+ }
+
+ public String getDistFileRemoteLocation(String repoName, String label, String relativeFilename) {
+ return "foo";
+ }
+
+ /**
+ * Returns a list of repo names that were used to all calls to
+ * {@link #synchronizePackages(String, PackageSyncReport, Collection)}
+ * either since the creation of this instance or the last call to
+ * {@link #reset()}.
+ *
+ * @return handle to the actual list used to capture these names; be careful
+ * about iterating this list while making other calls against this
+ * instance
+ */
+ public List<String> getLogSynchronizePackagesRepos() {
+ return logSynchronizePackagesRepos;
+ }
+
+ /**
+ * Returns a list of locations passed into all calls to
+ * {@link #getInputStream(String)} since the creation of this instance or
+ * the lsat call to {@link #reset()}.
+ *
+ * @return handle to the actual list used to capture these names; be careful
+ * about iterating this list while making other calls against this
+ * instance
+ */
+ public List<String> getLogGetInputStreamLocations() {
+ return logGetInputStreamLocations;
+ }
+
+ /**
+ * Indicate how long you want the provider to sleep during the PackageSync
+ * step
+ *
+ * @param longRunningSynchSleep
+ */
+ public void setLongRunningSynchSleep(int longRunningSynchSleep) {
+ this.longRunningSynchSleep = longRunningSynchSleep;
+ }
+
+ /**
+ * Rests the logging of calls made into this instance.
+ */
+ public void reset() {
+ logGetInputStreamLocations.clear();
+ logSynchronizePackagesRepos.clear();
+ logSynchronizeDistroRepos.clear();
+ }
+
+ private ContentProviderPackageDetails findDetailsByKey(ContentProviderPackageDetailsKey key,
+ Collection<ContentProviderPackageDetails> packages) {
+
+ for (ContentProviderPackageDetails pkg : packages) {
+ if (pkg.getContentProviderPackageDetailsKey().equals(key)) {
+ return pkg;
+ }
+ }
+
+ return null;
+ }
+
+ public SyncProgressWeight getSyncProgressWeight() {
+ return SyncProgressWeight.DEFAULT_WEIGHTS;
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginService.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginService.java
new file mode 100644
index 0000000..da94c58
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginService.java
@@ -0,0 +1,168 @@
+/*
+ * 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.enterprise.server.plugin.pc.content;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.rhq.core.domain.content.ContentSource;
+import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
+
+/**
+ * Used as a mock service for the content source plugin container.
+ */
+public class TestContentServerPluginService extends ServerPluginService implements TestContentServerPluginServiceMBean {
+
+ private TestContentProviderManager contentProviderManager;
+
+ private Map<Integer, ContentProvider> providers = new HashMap<Integer, ContentProvider>();
+ private TestContentProvider defaultTestContentProvider;
+
+ /**
+ * Creates and initializes the content server plugin container for use with the given test case.
+ *
+ * @param testContainer cannot be <code>null</code>
+ */
+ public TestContentServerPluginService(AbstractEJB3Test testContainer) {
+ super();
+ testContainer.prepareCustomServerPluginService(this);
+ startMasterPluginContainer();
+
+ defaultTestContentProvider = new TestContentProvider();
+ }
+
+ /**
+ * Returns a subclass of {@link ContentProviderManager} that overrides the calls to retrieve a content
+ * provider, instead returning mock instances as configured through calls to
+ * {@link #associateContentProvider(ContentSource, ContentProvider)}.
+ *
+ * @return instance of {@link ContentProviderManager} with only its provider retrieval methods overwritten
+ */
+ public TestContentProviderManager getContentProviderManager() {
+ return contentProviderManager;
+ }
+
+ /**
+ * Configures the providers retrieved and used by test subclass of {@link ContentProviderManager}. When that
+ * class needs to retrieve a {@link ContentProvider} to do some work, it will check these associations for
+ * the proper source -> provider mapping.
+ * <p/>
+ * If this method is never called, in other words no specific associations are made, an instance of the default
+ * content source ({@link TestContentProvider}) will be used by the <code>ContentProviderManager</code>
+ * regardless of content source requested.
+ *
+ * @param source source that will be handed to the ContentProviderManager and used to retrieve a specific
+ * content source
+ * @param provider provider to use when the given source is requested for operations
+ */
+ public void associateContentProvider(ContentSource source, ContentProvider provider) {
+ providers.put(source.getId(), provider);
+ }
+
+ protected MasterServerPluginContainer createMasterPluginContainer() {
+ MasterServerPluginContainer master = new TestMasterServerPluginContainer();
+ File dir = new File(System.getProperty("java.io.tmpdir"), "test-server-plugins");
+ MasterServerPluginContainerConfiguration config = new MasterServerPluginContainerConfiguration(dir, dir, dir,
+ null);
+ master.initialize(config);
+ return master;
+ }
+
+ /**
+ * The test master plugin container.
+ */
+ private class TestMasterServerPluginContainer extends MasterServerPluginContainer {
+ protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
+ ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(1);
+ pcs.add(new TestContentServerPluginContainer(this));
+ return pcs;
+ }
+
+ protected ClassLoader createRootServerPluginClassLoader() {
+ return this.getClass().getClassLoader();
+ }
+
+ protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
+ return new HashMap<URL, ServerPluginDescriptorType>();
+ }
+ }
+
+ /**
+ * The test content plugin container.
+ */
+ private class TestContentServerPluginContainer extends ContentServerPluginContainer {
+ public TestContentServerPluginContainer(MasterServerPluginContainer master) {
+ super(master);
+ }
+
+ protected ContentProviderManager createAdapterManager() {
+ contentProviderManager = new TestContentProviderManager();
+ return contentProviderManager;
+ }
+
+ protected ContentServerPluginManager createPluginManager() {
+ TestContentProviderPluginManager pm = new TestContentProviderPluginManager(this);
+ return pm;
+ }
+ }
+
+ /**
+ * The test plugin manager.
+ */
+ private class TestContentProviderPluginManager extends ContentServerPluginManager {
+ public TestContentProviderPluginManager(ContentServerPluginContainer pc) {
+ super(pc);
+ }
+ }
+
+ /**
+ * The test adapter manager.
+ */
+ public class TestContentProviderManager extends ContentProviderManager {
+
+ public ContentProvider getIsolatedContentProvider(int contentProviderId) throws RuntimeException {
+ return getContentProvider(contentProviderId);
+ }
+
+ protected ContentProvider getIsolatedContentSourceAdapter(ContentSource contentSource) throws RuntimeException {
+ return getContentProvider(contentSource.getId());
+ }
+
+ protected ContentProvider instantiateAdapter(ContentSource contentSource) {
+ return getContentProvider(contentSource.getId());
+ }
+
+ private ContentProvider getContentProvider(int contentSourceId) {
+ if (providers.size() == 0) {
+ return defaultTestContentProvider;
+ } else {
+ return providers.get(contentSourceId);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginServiceMBean.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginServiceMBean.java
new file mode 100644
index 0000000..9842f8e
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginServiceMBean.java
@@ -0,0 +1,24 @@
+/*
+ * 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.enterprise.server.plugin.pc.content;
+
+import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceMBean;
+
+public interface TestContentServerPluginServiceMBean extends ServerPluginServiceMBean {
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
new file mode 100644
index 0000000..7eb7917
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
@@ -0,0 +1,215 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc.generic;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.plugin.PluginKey;
+import org.rhq.core.domain.plugin.PluginStatusType;
+import org.rhq.core.domain.plugin.ServerPlugin;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
+import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.State;
+import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericPluginManager;
+import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener.LifecycleState;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
+import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.generic.GenericPluginDescriptorType;
+
+@Test
+public class GenericServerPluginTest extends AbstractEJB3Test {
+ private TestGenericServerPluginService pluginService;
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ this.pluginService = new TestGenericServerPluginService();
+ deleteAllTestPluginJars(); // remove any old server plugins that might be still around
+ prepareCustomServerPluginService(this.pluginService);
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ unprepareServerPluginService();
+ deleteAllTestPluginJars(); // remove any server plugins that tests created
+ this.pluginService = null;
+ }
+
+ public void testSimpleGenericPlugin() throws Exception {
+ createPluginJar("testSimpleGenericPlugin.jar", "serverplugins/simple-generic-serverplugin.xml");
+ this.pluginService.startMasterPluginContainer();
+
+ // make sure everything is started
+ TestGenericServerPluginContainer pc = this.pluginService.genericPC;
+ assert pc.state == State.STARTED;
+ TestGenericPluginManager pm = (TestGenericPluginManager) pc.getPluginManager();
+ TestLifecycleListener component = (TestLifecycleListener) pm.components.values().iterator().next();
+ assert component.state == LifecycleState.STARTED;
+
+ // make sure the context is correct
+ Configuration config = component.context.getPluginConfiguration();
+ assert config != null;
+ assert config.getSimple("plugin-simple-prop-1") != null;
+
+ List<ScheduledJobDefinition> schedules = component.context.getSchedules();
+ assert schedules == null;
+
+ // make sure everything is shutdown
+ this.pluginService.stopMasterPluginContainer();
+ assert pc.state == State.UNINITIALIZED;
+ assert component.state == LifecycleState.UNINITIALIZED;
+ }
+
+ public void testGetInstalledPlugins() throws Exception {
+ File jar = createPluginJar("testSimpleGenericPlugin.jar", "serverplugins/simple-generic-serverplugin.xml");
+ ServerPluginType type = new ServerPluginType(GenericPluginDescriptorType.class);
+
+ ServerPluginDescriptorType descriptor = ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(jar.toURI()
+ .toURL());
+
+ ServerPlugin plugin = new ServerPlugin(0, descriptor.getName(), jar.getName(), descriptor.getDisplayName(),
+ true, PluginStatusType.INSTALLED, descriptor.getDescription(), null, MessageDigestGenerator
+ .getDigestString(jar), descriptor.getVersion(), descriptor.getApiVersion(), null, null, type
+ .stringify(), System.currentTimeMillis(), System.currentTimeMillis());
+
+ ServerPluginsLocal serverPluginsLocal = LookupUtil.getServerPlugins();
+ Map<ServerPluginType, List<PluginKey>> original = serverPluginsLocal.getInstalledServerPluginsGroupedByType();
+ serverPluginsLocal.registerServerPlugin(LookupUtil.getSubjectManager().getOverlord(), plugin, jar);
+
+ try {
+ Map<ServerPluginType, List<PluginKey>> map = serverPluginsLocal.getInstalledServerPluginsGroupedByType();
+ List<PluginKey> pluginKeys = map.get(type);
+
+ if (original.containsKey(type)) {
+ assert map.size() == original.size();
+ assert pluginKeys.size() == original.get(type).size() + 1;
+ } else {
+ assert map.size() == original.size() + 1;
+ assert pluginKeys.size() == 1;
+ }
+ boolean got_it = false;
+ for (PluginKey pluginKey : pluginKeys) {
+ if (pluginKey.getPluginName().equals("TestSimpleGenericPlugin")) {
+ got_it = true;
+ break;
+ }
+ }
+ assert got_it == true;
+ } finally {
+ // make sure we clean this up, even on error
+ serverPluginsLocal.purgeServerPlugin(LookupUtil.getSubjectManager().getOverlord(), new PluginKey(plugin));
+ }
+
+ // test that purge really deleted it
+ Map<ServerPluginType, List<PluginKey>> map = serverPluginsLocal.getInstalledServerPluginsGroupedByType();
+ List<PluginKey> pluginKeys = map.get(type);
+
+ assert map.size() == original.size();
+ if (pluginKeys == null) {
+ assert !original.containsKey(type) : "we dont have any plugins of this type, neither should original";
+ } else {
+ assert pluginKeys.size() == original.get(type).size();
+ boolean got_it = false;
+ for (PluginKey pluginKey : pluginKeys) {
+ if (pluginKey.getPluginName().equals("TestSimpleGenericPlugin")) {
+ got_it = true;
+ break;
+ }
+ }
+ assert got_it == false : "we still have the plugin, but it should have been purged";
+ }
+
+ return;
+ }
+
+ private File createPluginJar(String jarName, String descriptorXmlFilename) throws Exception {
+ FileOutputStream stream = null;
+ JarOutputStream out = null;
+ InputStream in = null;
+
+ try {
+ this.pluginService.masterConfig.getPluginDirectory().mkdirs();
+ File jarFile = new File(this.pluginService.masterConfig.getPluginDirectory(), jarName);
+ stream = new FileOutputStream(jarFile);
+ out = new JarOutputStream(stream);
+
+ // Add archive entry for the descriptor
+ JarEntry jarAdd = new JarEntry("META-INF/rhq-serverplugin.xml");
+ jarAdd.setTime(System.currentTimeMillis());
+ out.putNextEntry(jarAdd);
+
+ // Write the descriptor - note that we assume the xml file is in the test classloader
+ in = getClass().getClassLoader().getResourceAsStream(descriptorXmlFilename);
+ StreamUtil.copy(in, out, false);
+
+ return jarFile;
+ } finally {
+ if (in != null) {
+ in.close();
+ }
+ if (out != null) {
+ out.close();
+ }
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ }
+
+ private void deleteAllTestPluginJars() {
+ if (this.pluginService==null) {
+ System.err.println("Plugin service was null !!");
+ return;
+ }
+ MasterServerPluginContainerConfiguration masterConfig = this.pluginService.masterConfig;
+ if (masterConfig==null)
+ return;
+
+ File pluginDirectory = masterConfig.getPluginDirectory();
+
+ File[] files = pluginDirectory.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ if (file.getName().endsWith(".jar")) {
+ file.delete();
+ }
+ }
+ }
+ return;
+ }
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
new file mode 100644
index 0000000..e8cdb51
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
@@ -0,0 +1,219 @@
+/*
+ * 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.enterprise.server.plugin.pc.generic;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.plugin.PluginKey;
+import org.rhq.core.domain.plugin.PluginStatusType;
+import org.rhq.core.domain.plugin.ServerPlugin;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginManager;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
+import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorMetadataParser;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
+
+/**
+ * Used as a mock service for the generic server plugin container.
+ */
+public class TestGenericServerPluginService extends ServerPluginService implements TestGenericServerPluginServiceMBean {
+ public enum State {
+ INITIALIZED, STARTED, STOPPED, UNINITIALIZED
+ }
+
+ // public so tests can directly set these
+ public TestMasterServerPluginContainer master;
+ public TestGenericServerPluginContainer genericPC;
+ public MasterServerPluginContainerConfiguration masterConfig;
+
+ public TestGenericServerPluginService() {
+ // build the config at constructor time so tests have it even before the PC is initialized
+ File dir = new File(System.getProperty("java.io.tmpdir"), "test-server-plugins");
+ this.masterConfig = new MasterServerPluginContainerConfiguration(dir, dir, dir, null);
+ }
+
+ @Override
+ public MasterServerPluginContainer createMasterPluginContainer() {
+ this.master = new TestMasterServerPluginContainer();
+ this.master.initialize(this.masterConfig);
+ return this.master;
+ }
+
+ /**
+ * The test master PC
+ */
+ class TestMasterServerPluginContainer extends MasterServerPluginContainer {
+ @Override
+ protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
+ ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(1);
+ genericPC = new TestGenericServerPluginContainer(this);
+ pcs.add(genericPC);
+ return pcs;
+ }
+
+ @Override
+ protected ClassLoader createRootServerPluginClassLoader() {
+ return this.getClass().getClassLoader();
+ }
+
+ @Override
+ protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
+ // if our test never setup any plugins, ignore it and just return an empty map
+ File pluginDir = getConfiguration().getPluginDirectory();
+ if (pluginDir == null || pluginDir.listFiles() == null || pluginDir.listFiles().length == 0) {
+ return new HashMap<URL, ServerPluginDescriptorType>();
+ } else {
+ return super.preloadAllPlugins();
+ }
+ }
+
+ @Override
+ protected List<PluginKey> getDisabledPluginKeys() {
+ // in the real world, the db is checked for enable flag, here we say all plugins are enabled
+ return new ArrayList<PluginKey>();
+ }
+ }
+
+ /**
+ * The test generic PC.
+ */
+ class TestGenericServerPluginContainer extends GenericServerPluginContainer {
+ public State state = State.UNINITIALIZED;
+
+ public TestGenericServerPluginContainer(MasterServerPluginContainer master) {
+ super(master);
+ }
+
+ @Override
+ protected ServerPluginManager createPluginManager() {
+ TestGenericPluginManager pm = new TestGenericPluginManager(this);
+ return pm;
+ }
+
+ @Override
+ public synchronized void initialize() throws Exception {
+ if (state == State.UNINITIALIZED) {
+ state = State.INITIALIZED;
+ } else {
+ System.out.println("!!! PC LIFECYCLE WAS BAD - THIS IS A BUG !!!");
+ throw new IllegalStateException("not uninitialized: " + state);
+ }
+ super.initialize();
+ }
+
+ @Override
+ public synchronized void start() {
+ if (state == State.INITIALIZED) {
+ state = State.STARTED;
+ } else {
+ System.out.println("!!! PC LIFECYCLE WAS BAD - THIS IS A BUG !!!");
+ throw new IllegalStateException("not initialized: " + state);
+ }
+ super.start();
+ }
+
+ @Override
+ public synchronized void stop() {
+ if (state == State.STARTED) {
+ state = State.STOPPED;
+ } else {
+ System.out.println("!!! PC LIFECYCLE WAS BAD - THIS IS A BUG !!!");
+ throw new IllegalStateException("not started: " + state);
+ }
+ super.stop();
+ }
+
+ @Override
+ public synchronized void shutdown() {
+ if (state == State.STOPPED) {
+ state = State.UNINITIALIZED;
+ } else {
+ System.out.println("!!! PC LIFECYCLE WAS BAD - THIS IS A BUG !!!");
+ throw new IllegalStateException("not stopped: " + state);
+ }
+ super.shutdown();
+ }
+ }
+
+ /**
+ * The test plugin manager.
+ */
+ class TestGenericPluginManager extends ServerPluginManager {
+ public final Map<String, ServerPluginComponent> components;
+
+ public TestGenericPluginManager(TestGenericServerPluginContainer pc) {
+ super(pc);
+ components = new HashMap<String, ServerPluginComponent>();
+ }
+
+ @Override
+ protected ServerPlugin getPlugin(ServerPluginEnvironment env) {
+
+ try {
+ Configuration pluginConfig = null;
+ Configuration scheduledJobsConfig = null;
+ ConfigurationDefinition configDef;
+
+ ServerPluginDescriptorType pluginDescriptor = env.getPluginDescriptor();
+
+ configDef = ServerPluginDescriptorMetadataParser.getPluginConfigurationDefinition(pluginDescriptor);
+ if (configDef != null) {
+ pluginConfig = configDef.getDefaultTemplate().createConfiguration();
+ }
+
+ configDef = ServerPluginDescriptorMetadataParser.getScheduledJobsDefinition(pluginDescriptor);
+ if (configDef != null) {
+ scheduledJobsConfig = configDef.getDefaultTemplate().createConfiguration();
+ }
+
+ File pluginFile = new File(env.getPluginUrl().toURI());
+ ServerPlugin plugin = new ServerPlugin(0, env.getPluginKey().getPluginName(), pluginFile.getName(),
+ pluginDescriptor.getDisplayName(), true, PluginStatusType.INSTALLED, pluginDescriptor
+ .getDescription(), "", MessageDigestGenerator.getDigestString(pluginFile), pluginDescriptor
+ .getVersion(), pluginDescriptor.getVersion(), pluginConfig, scheduledJobsConfig,
+ new ServerPluginType(pluginDescriptor).stringify(), System.currentTimeMillis(), System
+ .currentTimeMillis());
+ return plugin;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected ServerPluginComponent createServerPluginComponent(ServerPluginEnvironment environment)
+ throws Exception {
+ ServerPluginComponent component = super.createServerPluginComponent(environment);
+ components.put(environment.getPluginKey().getPluginName(), component);
+ return component;
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginServiceMBean.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginServiceMBean.java
new file mode 100644
index 0000000..157583f
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginServiceMBean.java
@@ -0,0 +1,24 @@
+/*
+ * 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.enterprise.server.plugin.pc.generic;
+
+import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceMBean;
+
+public interface TestGenericServerPluginServiceMBean extends ServerPluginServiceMBean {
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestLifecycleListener.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestLifecycleListener.java
new file mode 100644
index 0000000..9b84ddd
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestLifecycleListener.java
@@ -0,0 +1,91 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc.generic;
+
+import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
+
+/**
+ * A sample lifecycle listener for the sample generic plugin. This listener will be
+ * the main interface the server uses to start and stop the plugin.
+ */
+public class TestLifecycleListener implements ServerPluginComponent {
+
+ public enum LifecycleState {
+ UNINITIALIZED, INITIALIZED, STARTED, STOPPED
+ };
+
+ public ServerPluginContext context;
+ public LifecycleState state = LifecycleState.UNINITIALIZED;
+
+ public void initialize(ServerPluginContext context) throws Exception {
+ this.context = context;
+ if (state == LifecycleState.UNINITIALIZED) {
+ state = LifecycleState.INITIALIZED;
+ } else {
+ println("!!! lifecycle listener is in a bad state - this is a BUG !!!: " + state);
+ }
+ println("test server plugin has been initialized");
+ }
+
+ public void start() {
+ if (state == LifecycleState.INITIALIZED) {
+ state = LifecycleState.STARTED;
+ } else {
+ println("!!! lifecycle listener is in a bad state - this is a BUG !!!: " + state);
+ }
+ println("test server plugin has started");
+ }
+
+ public void stop() {
+ if (state == LifecycleState.STARTED) {
+ state = LifecycleState.STOPPED;
+ } else {
+ println("!!! lifecycle listener is in a bad state - this is a BUG !!!: " + state);
+ }
+ println("test server plugin has stopped");
+ }
+
+ public void shutdown() {
+ if (state == LifecycleState.STOPPED) {
+ state = LifecycleState.UNINITIALIZED;
+ } else {
+ println("!!! lifecycle listener is in a bad state - this is a BUG !!!: " + state);
+ }
+ println("test server plugin has been shut down");
+ }
+
+ private void println(String msg) {
+ System.out.println(msg + "!!! : " + this);
+ }
+
+ @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()).append(",");
+ str.append("data-dir=").append(this.context.getDataDirectory()).append(",");
+ str.append("tmp-dir=").append(this.context.getTemporaryDirectory()); // do not append ,
+ return str.toString();
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/cluster/ClusterManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/cluster/ClusterManagerBeanTest.java
new file mode 100644
index 0000000..cf5583d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/cluster/ClusterManagerBeanTest.java
@@ -0,0 +1,213 @@
+/*
+ * 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.enterprise.server.resource.cluster;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.authz.Role;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.group.ClusterKey;
+import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.ResourceTreeHelper;
+import org.rhq.enterprise.server.util.SessionTestHelper;
+
+/**
+ * Test for {@link ClusterManagerBean} SLSB.
+ * @author jshaughnessy
+ *
+ */
+@Test(groups = { "resource.manager" })
+public class ClusterManagerBeanTest extends AbstractEJB3Test {
+ static private final boolean TESTS_ENABLED = true;
+
+ private ClusterManagerLocal clusterManager;
+ private ResourceGroupManagerLocal resourceGroupManager;
+ private ResourceManagerLocal resourceManager;
+
+ @BeforeMethod
+ @SuppressWarnings( { "unused" })
+ private void init() {
+ clusterManager = LookupUtil.getClusterManager();
+ resourceGroupManager = LookupUtil.getResourceGroupManager();
+ resourceManager = LookupUtil.getResourceManager();
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testClusterKey() throws Throwable {
+ getTransactionManager().begin();
+ try {
+ EntityManager em = getEntityManager();
+
+ // setup simple test structures
+ Subject subject = SessionTestHelper.createNewSubject(em, "subject-ClusterManagerBeanTest");
+ Role role = SessionTestHelper.createNewRoleForSubject(em, subject, "role-ClusterManagerBeanTest",
+ Permission.MANAGE_INVENTORY);
+
+ ResourceGroup clusterGroup = SessionTestHelper.createNewCompatibleGroupForRole(em, role,
+ "clusterGroup-ClusterManagerBeanTest");
+
+ // setup two test resource trees to make into a resource cluster. Two compatible root nodes
+ // with the exact same child hierarchy
+ List<Resource> treeA = ResourceTreeHelper.createTree(em,
+ "A=d1c1,d1c2; d1c1=d2c1,d2c2; d2c1=d3c1,d3c2; d2c2=d3c3,d3c4");
+ List<Resource> treeB = ResourceTreeHelper.createTree(em,
+ "B=d1c1,d1c2; d1c1=d2c1,d2c2; d2c1=d3c1,d3c2; d2c2=d3c3,d3c4");
+
+ // test simple implicit resources
+ Resource nodeA = ResourceTreeHelper.findNode(treeA, "A");
+ Resource nodeB = ResourceTreeHelper.findNode(treeB, "B");
+
+ resourceGroupManager.addResourcesToGroup(subject, clusterGroup.getId(), new int[] { nodeA.getId(),
+ nodeB.getId() });
+
+ PageList<Resource> AChildren = resourceManager.findChildResources(subject, nodeA.getId(), PageControl
+ .getUnlimitedInstance());
+ assert !AChildren.isEmpty() : "Expected Children for Node A";
+
+ int AChildResourceTypeId = AChildren.get(0).getResourceType().getId();
+ String AChildResourceKey = AChildren.get(0).getResourceKey();
+
+ ClusterKey clusterKey = new ClusterKey(clusterGroup.getId(), AChildResourceTypeId, AChildResourceKey);
+ assert clusterKey.getClusterGroupId() == clusterGroup.getId();
+ assert clusterKey.getDepth() == 1;
+ assert AChildResourceKey.equals(clusterKey.getHierarchy().get(0).getResourceKey());
+ assert AChildResourceTypeId == clusterKey.getHierarchy().get(0).getResourceTypeId();
+ assert AChildResourceTypeId == ClusterKey.getResourceType(clusterKey);
+ assert ClusterKey.valueOf(clusterKey.toString()) != null;
+
+ List<Resource> resources = clusterManager.getAutoClusterResources(subject, clusterKey);
+
+ assert resources.size() == 2;
+ assert resources.get(0).getId() != resources.get(1).getId();
+ assert resources.get(0).getParentResource().getId() != resources.get(1).getParentResource().getId();
+ assert resources.get(0).getParentResource().getId() == nodeA.getId()
+ || resources.get(0).getParentResource().getId() == nodeB.getId();
+ assert resources.get(1).getParentResource().getId() == nodeA.getId()
+ || resources.get(1).getParentResource().getId() == nodeB.getId();
+
+ assertNull(clusterManager.getAutoClusterBackingGroup(subject, clusterKey));
+
+ ResourceGroup backingGroup = clusterManager.createAutoClusterBackingGroup(subject, clusterKey, true);
+ assertNotNull(backingGroup);
+ assertEquals(backingGroup.getClusterKey(), clusterKey.toString());
+ assertEquals(backingGroup.getClusterResourceGroup(), clusterGroup);
+ //Set<Resource> backingGroupResources = backingGroup.getExplicitResources();
+ // explicitResources for backingGroup is lazy, so we need to hit resourceManager for the answer
+ List<Resource> backingGroupResources = resourceManager.findExplicitResourcesByResourceGroup(subject,
+ backingGroup, PageControl.getUnlimitedInstance());
+ assertEquals(backingGroupResources.size(), resources.size());
+ for (Resource resource : backingGroupResources) {
+ assert resources.contains(resource);
+ }
+
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw t;
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testClusterKeyDepth2() throws Throwable {
+ getTransactionManager().begin();
+ try {
+ EntityManager em = getEntityManager();
+
+ // setup simple test structures
+ Subject subject = SessionTestHelper.createNewSubject(em, "subject-ClusterManagerBeanTest");
+ Role role = SessionTestHelper.createNewRoleForSubject(em, subject, "role-ClusterManagerBeanTest",
+ Permission.MANAGE_INVENTORY);
+
+ ResourceGroup clusterGroup = SessionTestHelper.createNewCompatibleGroupForRole(em, role,
+ "clusterGroup-ClusterManagerBeanTest");
+
+ // setup two test resource trees to make into a resource cluster. Two compatible root nodes
+ // with the exact same child hierarchy
+ List<Resource> treeA = ResourceTreeHelper.createTree(em,
+ "A=d1c1,d1c2; d1c1=d2c1,d2c2; d2c1=d3c1,d3c2; d2c2=d3c3,d3c4");
+ List<Resource> treeB = ResourceTreeHelper.createTree(em,
+ "B=d1c1,d1c2; d1c1=d2c1,d2c2; d2c1=d3c1,d3c2; d2c2=d3c3,d3c4");
+
+ // test simple implicit resources
+ Resource nodeA = ResourceTreeHelper.findNode(treeA, "A");
+ Resource nodeB = ResourceTreeHelper.findNode(treeB, "B");
+
+ resourceGroupManager.addResourcesToGroup(subject, clusterGroup.getId(), new int[] { nodeA.getId(),
+ nodeB.getId() });
+
+ PageList<Resource> AChildren = resourceManager.findChildResources(subject, nodeA.getId(), PageControl
+ .getUnlimitedInstance());
+ assert !AChildren.isEmpty() : "Expected Children for Node A";
+
+ Resource AChild = AChildren.get(0);
+ int AChildResourceTypeId = AChild.getResourceType().getId();
+ String AChildResourceKey = AChild.getResourceKey();
+
+ PageList<Resource> AGrandChildren = resourceManager.findChildResources(subject, AChild.getId(), PageControl
+ .getUnlimitedInstance());
+
+ Resource AGrandChild = AGrandChildren.get(0);
+ int AGrandChildResourceTypeId = AGrandChild.getResourceType().getId();
+ String AGrandChildResourceKey = AGrandChild.getResourceKey();
+
+ ClusterKey clusterKey = new ClusterKey(clusterGroup.getId(), AChildResourceTypeId, AChildResourceKey);
+ clusterKey.addChildToHierarchy(AGrandChildResourceTypeId, AGrandChildResourceKey);
+ assert clusterKey.getClusterGroupId() == clusterGroup.getId();
+ assert clusterKey.getDepth() == 2;
+ assert AChildResourceKey.equals(clusterKey.getHierarchy().get(0).getResourceKey());
+ assert AChildResourceTypeId == clusterKey.getHierarchy().get(0).getResourceTypeId();
+ assert AGrandChildResourceKey.equals(clusterKey.getHierarchy().get(1).getResourceKey());
+ assert AGrandChildResourceTypeId == clusterKey.getHierarchy().get(1).getResourceTypeId();
+ assert AGrandChildResourceTypeId == ClusterKey.getResourceType(clusterKey);
+ assert ClusterKey.valueOf(clusterKey.toString()) != null;
+
+ List<Resource> resources = clusterManager.getAutoClusterResources(subject, clusterKey);
+
+ assert resources.size() == 2;
+ assert resources.get(0).getId() != resources.get(1).getId();
+ assert resources.get(0).getParentResource().getId() != resources.get(1).getParentResource().getId();
+ assert resources.get(0).getParentResource().getParentResource().getId() == nodeA.getId()
+ || resources.get(0).getParentResource().getParentResource().getId() == nodeB.getId();
+ assert resources.get(1).getParentResource().getParentResource().getId() == nodeA.getId()
+ || resources.get(1).getParentResource().getParentResource().getId() == nodeB.getId();
+
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw t;
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
new file mode 100644
index 0000000..a1c8a65
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
@@ -0,0 +1,964 @@
+/*
+ * 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.enterprise.server.resource.group.definition.framework.test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
+import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.QueryUtility;
+
+public class ExpressionEvaluatorTest extends AbstractEJB3Test {
+
+ // Due to initialization order could not call QueryUtility.getEscapeClauseCharacter() prior
+ // to this point. Did not work in class initializer, BeforeClass or even BeforeTest.
+ private String[][] getSuccessTestCases() {
+ String escapeChar = QueryUtility.getEscapeClauseCharacter();
+
+ return new String[][] {
+
+ { "resource.child.name = joseph",
+
+ "SELECT res.id FROM Resource res " + //
+ " JOIN res.childResources child " + //
+ "WHERE child.name = :arg1 " },
+
+ { "resource.name = joseph",
+
+ "SELECT res.id FROM Resource res " + //
+ "WHERE res.name = :arg1" },
+
+ { "resource.version = 1.0",
+
+ "SELECT res.id FROM Resource res " + //
+ "WHERE res.version = :arg1" },
+
+ { "resource.type.plugin = harry",
+
+ "SELECT res.id FROM Resource res " + //
+ "WHERE res.resourceType.plugin = :arg1" },
+
+ { "resource.type.name = sally",
+
+ "SELECT res.id FROM Resource res " + //
+ "WHERE res.resourceType.name = :arg1" },
+
+ { "resource.pluginConfiguration[partition] = cluster-1",
+
+ "SELECT res.id FROM Resource res " + //
+ " JOIN res.pluginConfiguration pluginConf, PropertySimple simple, PropertyDefinition simpleDef " + //
+ " JOIN res.resourceType.pluginConfigurationDefinition pluginConfDef " + //
+ " WHERE simple.name LIKE :arg1 ESCAPE '" + escapeChar + "'" + //
+ " AND simple.stringValue = :arg2 " + //
+ " AND simple.configuration = pluginConf " + //
+ " AND simpleDef.configurationDefinition = pluginConfDef " + //
+ " AND simple.name = simpleDef.name AND simpleDef.type != 'PASSWORD' " },
+
+ { "resource.resourceConfiguration[partition].contains = cluster-1",
+
+ "SELECT res.id FROM Resource res " + //
+ " JOIN res.resourceConfiguration conf, PropertySimple simple, PropertyDefinition simpleDef " + //
+ " JOIN res.resourceType.resourceConfigurationDefinition confDef " + //
+ " WHERE simple.name LIKE :arg1 ESCAPE '" + escapeChar + "'" + //
+ " AND simple.stringValue LIKE :arg2 ESCAPE '" + escapeChar + "'" + //
+ " AND simple.configuration = conf " + //
+ " AND simpleDef.configurationDefinition = confDef " + //
+ " AND simple.name = simpleDef.name AND simpleDef.type != 'PASSWORD' " },
+
+ { "groupBy resource.type.plugin; " + //
+ "groupBy resource.type.name",
+
+ " SELECT res.resourceType.plugin, res.resourceType.name " + //
+ " FROM Resource res " + //
+ "GROUP BY res.resourceType.plugin, res.resourceType.name",
+
+ " SELECT res.id FROM Resource res " + //
+ " WHERE res.resourceType.plugin = :arg1 " + //
+ " AND res.resourceType.name = :arg2 " },
+
+ { "groupBy resource.resourceConfiguration[partition-name]",
+
+ " SELECT simple.stringValue FROM Resource res " + //
+ " JOIN res.resourceConfiguration conf, PropertySimple simple, PropertyDefinition simpleDef " + //
+ " JOIN res.resourceType.resourceConfigurationDefinition confDef " + //
+ " WHERE simple.name LIKE :arg1 ESCAPE '" + escapeChar + "'" + //
+ " AND simple.configuration = conf " + //
+ " AND simpleDef.configurationDefinition = confDef " + //
+ " AND simple.name = simpleDef.name AND simpleDef.type != 'PASSWORD' " + //
+ "GROUP BY simple.stringValue ",
+
+ " SELECT res.id FROM Resource res " + //
+ " JOIN res.resourceConfiguration conf, PropertySimple simple, PropertyDefinition simpleDef " + //
+ " JOIN res.resourceType.resourceConfigurationDefinition confDef " + //
+ " WHERE simple.name LIKE :arg1 ESCAPE '" + escapeChar + "'" + //
+ " AND simple.stringValue = :arg2 " + //
+ " AND simple.configuration = conf " + //
+ " AND simpleDef.configurationDefinition = confDef " + //
+ " AND simple.name = simpleDef.name AND simpleDef.type != 'PASSWORD' " },
+
+ { "resource.type.name = Windows;" + //
+ "resource.trait[Trait.osversion] = 5.1",
+
+ " SELECT res.id " + //
+ " FROM Resource res JOIN res.schedules sched JOIN sched.definition def, MeasurementDataTrait trait" + //
+ " WHERE res.resourceType.name = :arg1 " + //
+ " AND def.name LIKE :arg2 ESCAPE '" + escapeChar + "'" + //
+ " AND trait.value = :arg3 " + //
+ " AND trait.schedule = sched " + //
+ " AND trait.id.timestamp = " + //
+ " (SELECT max(mdt.id.timestamp) FROM MeasurementDataTrait mdt WHERE sched.id = mdt.schedule.id)" },
+
+ { " ;" + // test empty first line, which should be allowed
+ "resource.name.contains = joseph; " + //
+ " ;" + // test empty intermediate line, which should be allowed
+ "resource.parent.name.contains = joseph; " + //
+ " ;", // test empty last line, which should be allowed,
+
+ "SELECT res.id FROM Resource res " + //
+ "WHERE res.name LIKE :arg1 ESCAPE '" + escapeChar + "'" + //
+ " AND res.parentResource.name LIKE :arg2 ESCAPE '" + escapeChar + "'" },
+
+ { "EMPTY resource.name",
+
+ "SELECT res.id FROM Resource res " + //
+ "WHERE res.name IS NULL" },
+
+ { "empty resource.pluginConfiguration[partition]",
+
+ "SELECT res.id FROM Resource res " + //
+ " JOIN res.pluginConfiguration pluginConf, PropertySimple simple, PropertyDefinition simpleDef " + //
+ " JOIN res.resourceType.pluginConfigurationDefinition pluginConfDef " + //
+ " WHERE simple.name LIKE :arg1 ESCAPE '" + escapeChar + "'" + //
+ " AND simple.stringValue IS NULL " + //
+ " AND simple.configuration = pluginConf " + //
+ " AND simpleDef.configurationDefinition = pluginConfDef " + //
+ " AND simple.name = simpleDef.name AND simpleDef.type != 'PASSWORD' " }, };
+ }
+
+ @Test(groups = "integration.session")
+ public void testWellFormedExpressions() throws Exception {
+
+ String[][] successTestCases = getSuccessTestCases();
+ List<Integer> suppressedCases = Collections.emptyList();
+
+ getTransactionManager().begin();
+ try {
+ for (int i = 0; i < successTestCases.length; i++) {
+ if (suppressedCases.contains(i)) {
+ continue;
+ }
+
+ String inputExpressions = successTestCases[i][0];
+ String expectedTopResult = successTestCases[i][1];
+ String expectedGroupResult = "";
+ if (successTestCases[i].length == 3) {
+ expectedGroupResult = successTestCases[i][2];
+ }
+
+ ExpressionEvaluator evaluator = new ExpressionEvaluator();
+ evaluator.setTestMode(true); // to prevent actual query from happening
+ for (String expression : inputExpressions.split(";")) {
+ try {
+ evaluator.addExpression(expression); // do not trim, evaluator must handle sloppy expressions
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ assert false : "Error in TestCase[" + i + "], could not add expression[" + expression
+ + "], input[" + inputExpressions + "]";
+ }
+ }
+
+ evaluator.execute(); // execute will compute the JPQL statements
+
+ String actualTopResult = evaluator.getComputedJPQLStatement();
+ String actualGroupResult = evaluator.getComputedJPQLGroupStatement();
+
+ expectedTopResult = cleanUp(expectedTopResult);
+ actualTopResult = cleanUp(actualTopResult);
+ expectedGroupResult = cleanUp(expectedGroupResult);
+ actualGroupResult = cleanUp(actualGroupResult);
+
+ boolean success = expectedTopResult.equalsIgnoreCase(actualTopResult)
+ && expectedGroupResult.equalsIgnoreCase(actualGroupResult);
+ if (!success) {
+ System.out.println("TestCase[" + i + "] = \"" + inputExpressions + "\" failed. \n"
+ + "Expected Top Result: \"" + expectedTopResult + "\"\n" + "Received Top Result: \""
+ + actualTopResult + "\"\n" + "Expected Group Result: \"" + expectedGroupResult + "\"\n"
+ + "Received Group Result: \"" + actualGroupResult + "\"\n");
+ }
+ assert success;
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test(groups = "integration.session")
+ public void testTokenizer() {
+
+ String[] input = { "resource.child.name", //
+ "resource.pluginConfiguration[partition]", //
+ "resource.pluginConfiguration[partition].contains", //
+ "resource.pluginConfiguration[partition.name].contains" };
+
+ String[][] expectedOutput = { { "resource", "child", "name" }, //
+ { "resource", "pluginConfiguration[partition]" }, //
+ { "resource", "pluginConfiguration[partition]", "contains" }, //
+ { "resource", "pluginConfiguration[partition.name]", "contains" } };
+
+ ExpressionEvaluator evaluator = new ExpressionEvaluator();
+ evaluator.setTestMode(true); // to prevent actual query from happening
+
+ for (int i = 0; i < input.length; i++) {
+ String nextInput = input[i];
+ String[] nextExpectedOutput = expectedOutput[i];
+
+ List<String> output = evaluator.tokenizeCondition(nextInput);
+ String[] outputArray = output.toArray(new String[0]);
+
+ if (nextExpectedOutput.length != outputArray.length) {
+ System.out.println("Expected (" + Arrays.asList(nextExpectedOutput) + "), Received (" + output + ")");
+ continue;
+ }
+
+ boolean failed = false;
+ for (int j = 0; j < nextExpectedOutput.length; j++) {
+ if (!nextExpectedOutput[j].equals(outputArray[j])) {
+ System.out.println("Expected (" + Arrays.asList(nextExpectedOutput) + "), Received (" + output
+ + ")");
+ failed = true;
+ }
+ }
+ if (!failed) {
+ System.out.println("Successfully tokenized (" + nextInput + ")");
+ }
+ }
+ }
+
+ private static interface ExpressionGenerator {
+ String[] getExpressions();
+ }
+
+ private void evaluateExpressions(ExpressionGenerator generator) throws Exception {
+ try {
+ getTransactionManager().begin();
+ ExpressionEvaluator evaluator = new ExpressionEvaluator();
+ for (String expression : generator.getExpressions()) {
+ evaluator.addExpression(expression);
+ }
+ evaluator.execute();
+ evaluator.iterator().next();
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleResourceTraitExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.trait[agentHomeDirectory] = /var/rhq-agent",
+ "resource.trait[reasonForLastRestart] = OOMError"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleChildResourceTraitExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.child.trait[agentHomeDirectory] = /var/rhq-agent",
+ "resource.child.trait[reasonForLastRestart] = OOMError"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleParentResourceTraitExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.parent.trait[agentHomeDirectory] = /var/rhq-agent",
+ "resource.parent.trait[reasonForLastRestart] = OOMError"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGrandParentResourceTraitExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.grandParent.trait[agentHomeDirectory] = /var/rhq-agent",
+ "resource.grandParent.trait[reasonForLastRestart] = OOMError"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGrandParentResourceTraitExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.greatGrandParent.trait[agentHomeDirectory] = /var/rhq-agent",
+ "resource.greatGrandParent.trait[reasonForLastRestart] = OOMError"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGreatGrandParentResourceTraitExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.greatGreatGrandParent.trait[agentHomeDirectory] = /var/rhq-agent",
+ "resource.greatGreatGrandParent.trait[reasonForLastRestart] = OOMError"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleResourceIdExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.id = 5",
+ "resource.id = 6"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleChildResourceIdExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.child.id = 5",
+ "resource.child.id = 6"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleParentResourceIdExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.parent.id = 5",
+ "resource.parent.id = 6"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = InvalidExpressionException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGrandParentResourceIdExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.grandParent.id = 5",
+ "resource.grandParent.id = 6"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGrandParentResourceIdExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.greatGrandParent.id = 5",
+ "resource.greatGrandParent.id = 6"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGreatGrandParentResourceIdExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.greatGreatGrandParent.id = 5",
+ "resource.greatGreatGrandParent.id = 6"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleResourceNameExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.name = foo",
+ "resource.name = bar"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleChildResourceNameExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.child.name = foo",
+ "resource.child.name = bar"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleParentResourceNameExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.parent.name = foo",
+ "resource.parent.name = bar"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGrandParentResourceNameExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.grandParent.name = foo",
+ "resource.grandParent.name = bar"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGrandParentResourceNameExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.greatGrandParent.name = foo",
+ "resource.greatGrandParent.name = bar"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGreatGrandParentResourceNameExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.greatGreatGrandParent.name = foo",
+ "resource.greatGreatGrandParent.name = bar"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleResourceTypeExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.type.plugin = rhq-agent",
+ "resource.type.name = RHQ Agent",
+ "resource.type.plugin = rhq-server",
+ "resource.type.name = RHQ Server"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleChildResourceTypeExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.child.type.plugin = rhq-agent",
+ "resource.child.type.name = RHQ Agent",
+ "resource.child.type.plugin = rhq-server",
+ "resource.child.type.name = RHQ Server"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleParentResourceTypeExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.parent.type.plugin = rhq-agent",
+ "resource.parent.type.name = RHQ Agent",
+ "resource.parent.type.plugin = rhq-server",
+ "resource.parent.type.name = RHQ Server"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGrandParentResourceTypeExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.grandParent.type.plugin = rhq-agent",
+ "resource.grandParent.type.name = RHQ Agent",
+ "resource.grandParent.type.plugin = rhq-server",
+ "resource.grandParent.type.name = RHQ Server"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGrandParentResourceTypeExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.greatGrandParent.type.plugin = rhq-agent",
+ "resource.greatGrandParent.type.name = RHQ Agent",
+ "resource.greatGrandParent.type.plugin = rhq-server",
+ "resource.greatGrandParent.type.name = RHQ Server"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGreatGrandParentResourceTypeExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.greatGreatGrandParent.type.plugin = rhq-agent",
+ "resource.greatGreatGrandParent.type.name = RHQ Agent",
+ "resource.greatGreatGrandParent.type.plugin = rhq-server",
+ "resource.greatGreatGrandParent.type.name = RHQ Server"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleResourceCategoryExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.type.category = PLATFORM",
+ "resource.type.category = SERVER"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleChildResourceCategoryExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.child.type.category = PLATFORM",
+ "resource.child.type.category = SERVER"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleParentResourceCategoryExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.parent.type.category = PLATFORM",
+ "resource.parent.type.category = SERVER"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGrandParentResourceCategoryExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.grandParent.type.category = PLATFORM",
+ "resource.grandParent.type.category = SERVER"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGrandParentResourceCategoryExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.greatGrandParent.type.category = PLATFORM",
+ "resource.greatGrandParent.type.category = SERVER"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGreatGrandParentResourceCategoryExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.greatGreatGrandParent.type.category = PLATFORM",
+ "resource.greatGreatGrandParent.type.category = SERVER"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleResourceAvailabilityExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.availability = UP",
+ "resource.availability = UNKNOWN"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleChildResourceAvailabilityExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.child.availability = UP",
+ "resource.child.availability = UNKNOWN"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleParentResourceAvailabilityExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.parent.availability = UP",
+ "resource.parent.availability = UNKNOWN"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGrandParentResourceAvailabilityExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.grandParent.availability = UP",
+ "resource.grandParent.availability = UNKNOWN"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGrandParentResourceAvailabilityExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.greatGrandParent.availability = UP",
+ "resource.greatGrandParent.availability = UNKNOWN"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGreatGrandParentResourceAvailabilityExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.greatGreatGrandParent.availability = UP",
+ "resource.greatGreatGrandParent.availability = UNKNOWN"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleResourcePluginConfigExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.pluginConfiguration[x] = 1",
+ "resource.pluginConfiguration[y] = 2"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleChildResourcePluginConfigExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.child.pluginConfiguration[x] = 1",
+ "resource.child.pluginConfiguration[y] = 2"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleParentResourcePluginConfigExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.parent.pluginConfiguration[x] = 1",
+ "resource.parent.pluginConfiguration[y] = 2"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGrandParentResourcePluginConfigExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.grandParent.pluginConfiguration[x] = 1",
+ "resource.grandParent.pluginConfiguration[y] = 2"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGrandParentResourcePluginConfigExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.greatGrandParent.pluginConfiguration[x] = 1",
+ "resource.greatGrandParent.pluginConfiguration[y] = 2"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGreatGrandParentResourcePluginConfigExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.greatGreatGrandParent.pluginConfiguration[x] = 1",
+ "resource.greatGreatGrandParent.pluginConfiguration[y] = 2"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleResourceConfigExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.resourceConfiguration[x] = 1",
+ "resource.resourceConfiguration[y] = 2"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleChildResourceConfigExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.child.resourceConfiguration[x] = 1",
+ "resource.child.resourceConfiguration[y] = 2"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleParentResourceConfigExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.parent.resourceConfiguration[x] = 1",
+ "resource.parent.resourceConfiguration[y] = 2"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGrandParentResourceConfigExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.grandParent.resourceConfiguration[x] = 1",
+ "resource.grandParent.resourceConfiguration[y] = 2"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGrandParentResourceConfigExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.greatGrandParent.resourceConfiguration[x] = 1",
+ "resource.greatGrandParent.resourceConfiguration[y] = 2"
+ };
+ }
+ });
+ }
+
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleGreatGreatGrandParentResourceConfigExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
+ @Override
+ public String[] getExpressions() {
+ return new String[]{
+ "resource.greatGreatGrandParent.resourceConfiguration[x] = 1",
+ "resource.greatGreatGrandParent.resourceConfiguration[y] = 2"
+ };
+ }
+ });
+ }
+
+ private String cleanUp(String result) {
+ return result.replaceAll("\\s+", " ").trim();
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/GroupWithUncommittedTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/GroupWithUncommittedTest.java
new file mode 100644
index 0000000..3c57e5c
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/GroupWithUncommittedTest.java
@@ -0,0 +1,273 @@
+/*
+ * 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.resource.group.test;
+
+import java.util.Collections;
+import java.util.List;
+
+import javax.persistence.Query;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.common.composite.IntegerOptionItem;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
+import org.rhq.core.domain.server.PersistenceUtility;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.test.LargeGroupTestBase;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.SessionTestHelper;
+
+@Test
+public class GroupWithUncommittedTest extends LargeGroupTestBase {
+
+ private static final boolean TESTS_ENABLED = true;
+ private LargeGroupEnvironment env;
+
+ private class GroupAvailCounts {
+ public final int up;
+ public final int down;
+ public final int unknown;
+ public final int disabled;
+ public final int uncommitted;
+ public final int total;
+ public final int visibleTotal;
+
+ GroupAvailCounts(int up, int down, int unknown, int disabled, int uncommitted) {
+ this.up = up;
+ this.down = down;
+ this.unknown = unknown;
+ this.disabled = disabled;
+ this.uncommitted = uncommitted;
+ this.total = up + down + unknown + disabled + uncommitted;
+ this.visibleTotal = up + down + unknown + disabled; // uncommitted is not included
+ assert this.visibleTotal != this.total : "all of our tests should have at least 1 uncommitted resource";
+ }
+ }
+
+ @Override
+ protected void setupMockAgentServices(TestServerCommunicationsService agentServiceContainer) {
+ }
+
+ /**
+ * Remove the group and all its members.
+ */
+ @AfterMethod(alwaysRun = true)
+ public void teardownEnv() throws Exception {
+ if (env != null) {
+ tearDownLargeGroupWithNormalUserRoleAccess(env, false);
+ SessionTestHelper.simulateLogout(env.normalSubject);
+ }
+ env = null;
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testResourceGroupQueries() throws Exception {
+ GroupAvailCounts gac = new GroupAvailCounts(1, 1, 1, 1, 1);
+ env = createLargeGroupWithNormalUserRoleAccessWithInventoryStatus(null, gac.total, gac.down, gac.unknown,
+ gac.disabled, gac.uncommitted, Permission.CONFIGURE_READ);
+ assert null != pickUncommittedResource(env.platformResource) : "there should have been an uncommitted resource";
+
+ SessionTestHelper.simulateLogin(env.normalSubject);
+
+ // these queries were tweeked to filter uncommitted - see BZ 820981
+ PageList<ResourceGroupComposite> results = resourceGroupManager.findResourceGroupComposites(env.normalSubject,
+ null, null,
+ null, null, null, null, env.compatibleGroup.getId(), new PageControl(0, 50));
+ int count = results.size();
+ assert count == 1 : "results=" + results;
+ ResourceGroupComposite rgc = results.get(0);
+ assert rgc.getExplicitCount() == gac.visibleTotal;
+ assert rgc.getImplicitCount() == gac.visibleTotal;
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testGetResourceNameOptionItems() {
+ GroupAvailCounts gac = new GroupAvailCounts(1, 1, 1, 1, 1);
+ env = createLargeGroupWithNormalUserRoleAccessWithInventoryStatus(null, gac.total, gac.down, gac.unknown,
+ gac.disabled, gac.uncommitted, Permission.CONFIGURE_READ);
+ assert null != pickUncommittedResource(env.platformResource) : "there should have been an uncommitted resource";
+
+ SessionTestHelper.simulateLogin(env.normalSubject);
+
+ // this uses ResourceGroup.QUERY_FIND_RESOURCE_NAMES_BY_GROUP_ID which was tweeked due to BZ 820981
+ List<IntegerOptionItem> results = LookupUtil.getOperationManager().getResourceNameOptionItems(
+ env.compatibleGroup.getId());
+ int count = results.size();
+ assert count == gac.visibleTotal : "results=" + results;
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testAnotherResourceGroupQuery() throws Exception {
+ GroupAvailCounts gac = new GroupAvailCounts(1, 1, 1, 1, 1);
+ env = createLargeGroupWithNormalUserRoleAccessWithInventoryStatus(null, gac.total, gac.down, gac.unknown,
+ gac.disabled, gac.uncommitted, Permission.CONFIGURE_READ);
+ assert null != pickUncommittedResource(env.platformResource) : "there should have been an uncommitted resource";
+
+ SessionTestHelper.simulateLogin(env.normalSubject);
+
+ // this query was tweeked to filter uncommitted - see BZ 820981
+ // we aren't really testing recursive groups - so we don't have any resources in implicit list that isn't in explicit
+ // but run this query anyway to make sure it can successfully run - we'll check that we get back 0 rows.
+ Query q = getEntityManager().createNamedQuery(ResourceGroup.QUERY_FIND_RESOURCE_IDS_NOT_IN_GROUP_EXPLICIT);
+ q.setParameter("groupId", env.compatibleGroup.getId());
+ q.setParameter("resourceIds",
+ Collections.singletonList(env.platformResource.getChildResources().iterator().next().getId())); // just pick any ID, it won't match anyway
+ List<?> results = q.getResultList();
+ assert results.isEmpty() : "results should have been empty" + results;
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testResourceTypeQueries() throws Exception {
+ GroupAvailCounts gac = new GroupAvailCounts(1, 1, 1, 1, 1);
+ env = createLargeGroupWithNormalUserRoleAccessWithInventoryStatus(null, gac.total, gac.down, gac.unknown,
+ gac.disabled, gac.uncommitted, Permission.CONFIGURE_READ);
+ assert null != pickUncommittedResource(env.platformResource) : "there should have been an uncommitted resource";
+
+ SessionTestHelper.simulateLogin(env.normalSubject);
+
+ // these queries were tweeked to filter uncommitted - see BZ 820981
+ Query q = getEntityManager().createNamedQuery(ResourceType.QUERY_GET_EXPLICIT_RESOURCE_TYPE_COUNTS_BY_GROUP);
+ q.setParameter("groupId", env.compatibleGroup.getId());
+ List<?> results = q.getResultList();
+ int count = results.size();
+ assert count == 1 : "results=" + results;
+
+ q = getEntityManager().createNamedQuery(ResourceType.QUERY_GET_IMPLICIT_RESOURCE_TYPE_COUNTS_BY_GROUP);
+ q.setParameter("groupId", env.compatibleGroup.getId());
+ results = q.getResultList();
+ count = results.size();
+ assert count == 1 : "results=" + results;
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testResourceQueries() throws Exception {
+ GroupAvailCounts gac = new GroupAvailCounts(1, 1, 1, 1, 1);
+ env = createLargeGroupWithNormalUserRoleAccessWithInventoryStatus(null, gac.total, gac.down, gac.unknown,
+ gac.disabled, gac.uncommitted, Permission.CONFIGURE_READ);
+ assert null != pickUncommittedResource(env.platformResource) : "there should have been an uncommitted resource";
+
+ SessionTestHelper.simulateLogin(env.normalSubject);
+
+ // these queries were tweeked to filter uncommitted - see BZ 820981
+ Query q = getEntityManager().createNamedQuery(Resource.QUERY_FIND_EXPLICIT_IDS_BY_RESOURCE_GROUP_ADMIN);
+ q.setParameter("groupId", env.compatibleGroup.getId());
+ List<?> results = q.getResultList();
+ int count = results.size();
+ assert count == gac.visibleTotal : "results=" + results;
+
+ q = getEntityManager().createNamedQuery(Resource.QUERY_FIND_IMPLICIT_IDS_BY_RESOURCE_GROUP_ADMIN);
+ q.setParameter("groupId", env.compatibleGroup.getId());
+ results = q.getResultList();
+ count = results.size();
+ assert count == gac.visibleTotal : "results=" + results;
+
+ q = getEntityManager().createNamedQuery(Resource.QUERY_FIND_BY_EXPLICIT_RESOURCE_GROUP);
+ q.setParameter("group", env.compatibleGroup);
+ q.setParameter("subject", env.normalSubject);
+ results = q.getResultList();
+ count = results.size();
+ assert count == gac.visibleTotal : "results=" + results;
+
+ q = getEntityManager().createNamedQuery(Resource.QUERY_FIND_BY_EXPLICIT_RESOURCE_GROUP_ADMIN);
+ q.setParameter("group", env.compatibleGroup);
+ results = q.getResultList();
+ count = results.size();
+ assert count == gac.visibleTotal : "results=" + results;
+
+ q = getEntityManager().createNamedQuery(Resource.QUERY_FIND_BY_IMPLICIT_RESOURCE_GROUP);
+ q.setParameter("group", env.compatibleGroup);
+ q.setParameter("subject", env.normalSubject);
+ results = q.getResultList();
+ count = results.size();
+ assert count == gac.visibleTotal : "results=" + results;
+
+ q = getEntityManager().createNamedQuery(Resource.QUERY_FIND_BY_IMPLICIT_RESOURCE_GROUP_ADMIN);
+ q.setParameter("group", env.compatibleGroup);
+ results = q.getResultList();
+ count = results.size();
+ assert count == gac.visibleTotal : "results=" + results;
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testAvailGroupQueries() throws Exception {
+ GroupAvailCounts gac = new GroupAvailCounts(1, 1, 1, 1, 1);
+ env = createLargeGroupWithNormalUserRoleAccessWithInventoryStatus(null, gac.total, gac.down, gac.unknown,
+ gac.disabled, gac.uncommitted, Permission.CONFIGURE_READ);
+ assert null != pickUncommittedResource(env.platformResource) : "there should have been an uncommitted resource";
+
+ SessionTestHelper.simulateLogin(env.normalSubject);
+
+ // this query was tweeked to filter uncommitted - see BZ 820981
+ Query q = getEntityManager().createNamedQuery(Availability.FIND_FOR_RESOURCE_GROUP_WITHIN_INTERVAL);
+ q.setParameter("groupId", env.compatibleGroup.getId());
+ q.setParameter("start", 0L);
+ q.setParameter("end", System.currentTimeMillis());
+ List<?> results = q.getResultList();
+ int availCount = results.size();
+ assert availCount == gac.visibleTotal : "availCount=" + availCount;
+ }
+
+ @Test(enabled = TESTS_ENABLED)
+ public void testConfigGroupQueries() throws Exception {
+ GroupAvailCounts gac = new GroupAvailCounts(5, 4, 3, 2, 1);
+ env = createLargeGroupWithNormalUserRoleAccessWithInventoryStatus(null, gac.total, gac.down, gac.unknown,
+ gac.disabled, gac.uncommitted, Permission.CONFIGURE_READ);
+ assert null != pickUncommittedResource(env.platformResource) : "there should have been an uncommitted resource";
+
+ SessionTestHelper.simulateLogin(env.normalSubject);
+
+ // these queries were tweeked to filter uncommitted - see BZ 820981
+ Query resConfigCountQuery = PersistenceUtility.createCountQuery(getEntityManager(),
+ Configuration.QUERY_GET_RESOURCE_CONFIG_MAP_BY_GROUP_ID);
+ resConfigCountQuery.setParameter("resourceGroupId", env.compatibleGroup.getId());
+ long resConfigCount = (Long) resConfigCountQuery.getSingleResult();
+
+ Query pluginConfigCountQuery = PersistenceUtility.createCountQuery(getEntityManager(),
+ Configuration.QUERY_GET_PLUGIN_CONFIG_MAP_BY_GROUP_ID);
+ pluginConfigCountQuery.setParameter("resourceGroupId", env.compatibleGroup.getId());
+ long pluginConfigCount = (Long) pluginConfigCountQuery.getSingleResult();
+
+ assert resConfigCount == gac.visibleTotal;
+ assert pluginConfigCount == gac.visibleTotal;
+
+ int groupSize = resourceGroupManager.getExplicitGroupMemberCount(env.compatibleGroup.getId());
+ assert resConfigCount == groupSize;
+ assert pluginConfigCount == groupSize;
+
+ }
+
+ private Resource pickUncommittedResource(Resource platformResource) {
+ for (Resource r : platformResource.getChildResources()) {
+ if (r.getInventoryStatus() == InventoryStatus.NEW) {
+ return r;
+ }
+ }
+ return null;
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/LDAPStringUtilTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/LDAPStringUtilTest.java
new file mode 100644
index 0000000..a6e50cb
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/LDAPStringUtilTest.java
@@ -0,0 +1,50 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 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.resource.group.test;
+
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.Test;
+
+import org.rhq.enterprise.server.resource.group.LDAPStringUtil;
+
+/**
+ * Test various methods of the {@link LDAPStringUtil} class.
+ *
+ * @author loleary
+ * @since 4.0.1
+ *
+ */
+public class LDAPStringUtilTest {
+
+ /**
+ * Test method for {@link org.rhq.core.domain.util.LDAPStringUtil#encodeForFilter(java.lang.String)}.
+ */
+ @Test
+ public void testEncodeForFilter() {
+ assertEquals(LDAPStringUtil.encodeForFilter("\\, (, ), and *"), "\\5c, \\28, \\29, and \\2a",
+ "Failed to encode \"\\, (, ), and *\"");
+ assertEquals(LDAPStringUtil.encodeForFilter("A " + '\0' + " empty value"), "A \\00 empty value",
+ "Failed to encode \"A <null> empty value\"");
+ assertEquals(LDAPStringUtil.encodeForFilter("A " + '\u00E9' + " value"), "A \\c3\\a9 value",
+ "Failed to encode \"A <letter e with acute> value\"");
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/LargeGroupCriteriaTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/LargeGroupCriteriaTest.java
new file mode 100644
index 0000000..323cf5c
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/LargeGroupCriteriaTest.java
@@ -0,0 +1,350 @@
+/*
+ * 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.resource.group.test;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.criteria.ResourceCriteria;
+import org.rhq.core.domain.criteria.ResourceGroupCriteria;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.authz.AuthorizationManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
+import org.rhq.enterprise.server.test.LargeGroupTestBase;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.SessionTestHelper;
+
+@Test
+public class LargeGroupCriteriaTest extends LargeGroupTestBase {
+
+ private static final boolean TEST_ENABLED = true;
+
+ private ArrayList<LargeGroupEnvironment> env;
+
+ private class GroupAvailCounts {
+ public final int up;
+ public final int down;
+ public final int unknown;
+ public final int disabled;
+ public final int uncommitted;
+ public final int total;
+ public final int visibleTotal;
+
+ GroupAvailCounts(int up, int down, int unknown, int disabled) {
+ this(up, down, unknown, disabled, 0);
+ }
+
+ GroupAvailCounts(int up, int down, int unknown, int disabled, int uncommitted) {
+ this.up = up;
+ this.down = down;
+ this.unknown = unknown;
+ this.disabled = disabled;
+ this.uncommitted = uncommitted;
+ this.total = up + down + unknown + disabled + uncommitted;
+ this.visibleTotal = up + down + unknown + disabled; // uncommitted is not included
+ }
+ }
+
+ @Override
+ protected void setupMockAgentServices(TestServerCommunicationsService agentServiceContainer) {
+ }
+
+ /**
+ * Remove the group and all its members.
+ */
+ @AfterMethod(alwaysRun = true)
+ public void tearDownGroups() throws Exception {
+ if (env != null) {
+ System.out.println("Tearing down groups...");
+ Iterator<LargeGroupEnvironment> iter = env.iterator();
+ while (iter.hasNext()) {
+ LargeGroupEnvironment doomed = iter.next();
+ tearDownLargeGroupWithNormalUserRoleAccess(doomed, iter.hasNext());
+ SessionTestHelper.simulateLogout(doomed.normalSubject);
+ }
+ env = null;
+ }
+ }
+
+ @Test(enabled = TEST_ENABLED)
+ public void testSearchBarAvailabilityQueryUP() throws Exception {
+ GroupAvailCounts gac = new GroupAvailCounts(5, 0, 0, 0);
+ PageList<ResourceGroupComposite> pageList = testGroupQueriesWithSearchBar(gac, "availability=up");
+ assert pageList.size() == 1;
+
+ tearDownGroups();
+ pageList = testGroupQueriesWithSearchBar(gac, "availability != up");
+ assert pageList.size() == 0;
+ }
+
+ @Test(enabled = TEST_ENABLED)
+ public void testSearchBarAvailabilityQueryDOWN() throws Exception {
+ GroupAvailCounts gac = new GroupAvailCounts(0, 5, 0, 0);
+ PageList<ResourceGroupComposite> pageList = testGroupQueriesWithSearchBar(gac, "availability=down");
+ assert pageList.size() == 1;
+
+ tearDownGroups();
+ pageList = testGroupQueriesWithSearchBar(gac, "availability != down");
+ assert pageList.size() == 0;
+ }
+
+ @Test(enabled = TEST_ENABLED)
+ public void testSearchBarAvailabilityQueryDISABLED() throws Exception {
+ GroupAvailCounts gac = new GroupAvailCounts(0, 0, 0, 5);
+ PageList<ResourceGroupComposite> pageList = testGroupQueriesWithSearchBar(gac, "availability=disabled");
+ assert pageList.size() == 1;
+
+ tearDownGroups();
+ pageList = testGroupQueriesWithSearchBar(gac, "availability != disabled");
+ assert pageList.size() == 0;
+ }
+
+ @Test(enabled = TEST_ENABLED)
+ public void testSearchBarAvailabilityQueryMIXED() throws Exception {
+ // when a group has a mix of up/down/disabled resources, it will not be returned with the avail search expression
+ GroupAvailCounts gac = new GroupAvailCounts(2, 2, 0, 2);
+ PageList<ResourceGroupComposite> pageList = testGroupQueriesWithSearchBar(gac, "availability=up");
+ assert pageList.size() == 0;
+
+ tearDownGroups();
+ pageList = testGroupQueriesWithSearchBar(gac, "availability=down");
+ assert pageList.size() == 0;
+
+ tearDownGroups();
+ pageList = testGroupQueriesWithSearchBar(gac, "availability=disabled");
+ assert pageList.size() == 0;
+ }
+
+ @Test(enabled = TEST_ENABLED)
+ public void testUncommitted() throws Exception {
+ ArrayList<GroupAvailCounts> gacs = new ArrayList<LargeGroupCriteriaTest.GroupAvailCounts>();
+ gacs.add(new GroupAvailCounts(1, 1, 1, 1, 1));
+ testGroupQueries(gacs);
+ }
+
+ @Test(enabled = TEST_ENABLED)
+ public void testSmallGroupsWithUncommitted() throws Exception {
+ ArrayList<GroupAvailCounts> gacs = new ArrayList<LargeGroupCriteriaTest.GroupAvailCounts>();
+ gacs.add(new GroupAvailCounts(8, 4, 2, 1, 1));
+ gacs.add(new GroupAvailCounts(2, 4, 6, 8, 10));
+ testGroupQueries(gacs);
+ }
+
+ @Test(enabled = TEST_ENABLED)
+ public void testSmallGroups() throws Exception {
+ ArrayList<GroupAvailCounts> gacs = new ArrayList<LargeGroupCriteriaTest.GroupAvailCounts>();
+ gacs.add(new GroupAvailCounts(8, 4, 2, 1));
+ gacs.add(new GroupAvailCounts(2, 4, 6, 8));
+ testGroupQueries(gacs);
+ }
+
+ @Test(enabled = TEST_ENABLED)
+ public void testLotsOfSmallGroups() throws Exception {
+ ArrayList<GroupAvailCounts> gacs = new ArrayList<LargeGroupCriteriaTest.GroupAvailCounts>();
+ for (int i = 0; i < 50; i++) {
+ gacs.add(new GroupAvailCounts(1, 1, 1, 1));
+ gacs.add(new GroupAvailCounts(2, 2, 2, 2));
+ }
+ testGroupQueries(gacs);
+ }
+
+ @Test(enabled = TEST_ENABLED)
+ public void testLargeGroup() throws Exception {
+ ArrayList<GroupAvailCounts> gacs = new ArrayList<LargeGroupCriteriaTest.GroupAvailCounts>();
+ gacs.add(new GroupAvailCounts(500, 250, 150, 110)); // purposefully over 1,000
+ testGroupQueries(gacs);
+ }
+
+ @Test(enabled = TEST_ENABLED)
+ public void testLotsOfLargeGroups() throws Exception {
+ ArrayList<GroupAvailCounts> gacs = new ArrayList<LargeGroupCriteriaTest.GroupAvailCounts>();
+ for (int i = 0; i < 5; i++) {
+ gacs.add(new GroupAvailCounts(10, 10, 10, 10));
+ gacs.add(new GroupAvailCounts(20, 20, 20, 20));
+ }
+ testGroupQueries(gacs);
+ }
+
+ // test findResourcesByCriteriaBounded here instead of ResourceGroupManagerBeanTest because we want
+ // to work with a decent # or resources.
+ @Test(enabled = TEST_ENABLED)
+ public void testResourceCriteriaBounded() throws Exception {
+ ArrayList<GroupAvailCounts> gacs = new ArrayList<LargeGroupCriteriaTest.GroupAvailCounts>();
+ gacs.add(new GroupAvailCounts(1100, 0, 0, 0)); // purposefully over 1,000, avails don't really matter
+
+ ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+ AuthorizationManagerLocal authManager = LookupUtil.getAuthorizationManager();
+
+ env = new ArrayList<LargeGroupEnvironment>(gacs.size());
+
+ LargeGroupEnvironment lgeWithTypes = null;
+ for (GroupAvailCounts gac : gacs) {
+ env.add(createLargeGroupWithNormalUserRoleAccessWithInventoryStatus(lgeWithTypes, gac.total, gac.down,
+ gac.unknown, gac.disabled, gac.uncommitted, Permission.CONFIGURE_READ));
+ lgeWithTypes = env.get(0);
+ }
+
+ ResourceCriteria criteria = new ResourceCriteria();
+ List<Resource> result;
+
+ SessionTestHelper.simulateLogin(env.get(0).normalSubject);
+
+ criteria.addFilterParentResourceId(lgeWithTypes.platformResource.getId());
+ criteria.setPageControl(PageControl.getUnlimitedInstance());
+ result = resourceManager.findResourcesByCriteria(env.get(0).normalSubject, criteria);
+ assert null != result;
+ assert result.size() == 1100 : "Expected unbounded query to return all 1100 resources";
+
+ result = resourceManager.findResourcesByCriteriaBounded(env.get(0).normalSubject, criteria, 2000, 100);
+ assert null != result;
+ assert result.size() == 1100 : "Expected 2000/100 bounded query to return all 1100 resources";
+
+ result = resourceManager.findResourcesByCriteriaBounded(env.get(0).normalSubject, criteria, 1100, 100);
+ assert null != result;
+ assert result.size() == 1100 : "Expected 1100/100 bounded query to return all 1100 resources";
+
+ result = resourceManager.findResourcesByCriteriaBounded(env.get(0).normalSubject, criteria, 0, 0);
+ assert null != result;
+ assert result.size() == 200 : "Expected default (1000/200) bounded query to return 200 resources";
+
+ result = resourceManager.findResourcesByCriteriaBounded(env.get(0).normalSubject, criteria, 0, 500);
+ assert null != result;
+ assert result.size() == 500 : "Expected default (1000)/500) bounded query to return 500 resources";
+
+ result = resourceManager.findResourcesByCriteriaBounded(env.get(0).normalSubject, criteria, 100, 200);
+ assert null != result;
+ assert result.size() == 100 : "Expected 100/200 bounded query to return 100 resources";
+ }
+
+ private PageList<ResourceGroupComposite> testGroupQueriesWithSearchBar(GroupAvailCounts gac, String searchExpression)
+ throws Exception {
+ ResourceGroupManagerLocal groupManager = LookupUtil.getResourceGroupManager();
+
+ env = new ArrayList<LargeGroupEnvironment>(1);
+
+ LargeGroupEnvironment lgeWithTypes = null;
+ env.add(createLargeGroupWithNormalUserRoleAccessWithInventoryStatus(lgeWithTypes, gac.total, gac.down,
+ gac.unknown, gac.disabled, gac.uncommitted, Permission.CONFIGURE_READ));
+
+ ResourceGroupCriteria criteria;
+ PageList<ResourceGroupComposite> pageList;
+ long start;
+
+ // test findResourceGroupCompositesByCriteria where the criteria will use the search bar feature
+ SessionTestHelper.simulateLogin(env.get(0).normalSubject);
+ criteria = new ResourceGroupCriteria();
+ criteria.setSearchExpression(searchExpression);
+ start = System.currentTimeMillis();
+ pageList = groupManager.findResourceGroupCompositesByCriteria(env.get(0).normalSubject, criteria);
+ System.out.println("criteria with search==>" + (System.currentTimeMillis() - start) + "ms");
+ return pageList;
+ }
+
+ private void testGroupQueries(ArrayList<GroupAvailCounts> groupAvailCounts) throws Exception {
+ ResourceGroupManagerLocal groupManager = LookupUtil.getResourceGroupManager();
+ AuthorizationManagerLocal authManager = LookupUtil.getAuthorizationManager();
+
+ env = new ArrayList<LargeGroupEnvironment>(groupAvailCounts.size());
+
+ LargeGroupEnvironment lgeWithTypes = null;
+ for (GroupAvailCounts gac : groupAvailCounts) {
+ env.add(createLargeGroupWithNormalUserRoleAccessWithInventoryStatus(lgeWithTypes, gac.total, gac.down,
+ gac.unknown, gac.disabled, gac.uncommitted, Permission.CONFIGURE_READ));
+ lgeWithTypes = env.get(0);
+ }
+
+ ResourceGroupCriteria criteria;
+ PageList<ResourceGroupComposite> pageList;
+ ResourceGroupComposite groupComp;
+ long start;
+
+ // test findResourceGroupCompositesByCriteria
+ for (int i = 0; i < groupAvailCounts.size(); i++) {
+ LargeGroupEnvironment lge = env.get(i);
+ GroupAvailCounts gac = groupAvailCounts.get(i);
+
+ SessionTestHelper.simulateLogin(lge.normalSubject);
+ criteria = new ResourceGroupCriteria();
+ start = System.currentTimeMillis();
+ pageList = groupManager.findResourceGroupCompositesByCriteria(lge.normalSubject, criteria);
+ System.out.println("findResourceGroupCompositesByCriteria #" + i + "==>"
+ + (System.currentTimeMillis() - start) + "ms");
+ assert pageList.size() == 1 : "the query should only have selected the one group for our user";
+ groupComp = pageList.get(0);
+ System.out.println("-->" + groupComp);
+ assert groupComp.getExplicitCount() == gac.visibleTotal;
+ assert groupComp.getExplicitCount() == groupComp.getImplicitCount(); // we aren't testing recursive groups
+ assert groupComp.getExplicitUp() == gac.up;
+ assert groupComp.getExplicitDown() == gac.down;
+ assert groupComp.getExplicitUnknown() == gac.unknown;
+ assert groupComp.getExplicitDisabled() == gac.disabled;
+
+ // mainly to help test when there are uncommitted resources in the group - see BZ 820981
+ Resource committed = pickAResourceWithInventoryStatus(lge.platformResource, InventoryStatus.COMMITTED);
+ assert true == authManager.hasResourcePermission(lge.normalSubject, Permission.CONFIGURE_READ,
+ Collections.singletonList(committed.getId()));
+ assert false == authManager.hasResourcePermission(lge.normalSubject, Permission.CONTROL,
+ Collections.singletonList(committed.getId())); // we weren't given CONTROL perms on the committed resource
+ Resource uncommitted = pickAResourceWithInventoryStatus(lge.platformResource, InventoryStatus.NEW);
+ if (uncommitted != null) {
+ assert false == authManager.hasResourcePermission(lge.normalSubject, Permission.CONFIGURE_READ,
+ Collections.singletonList(uncommitted.getId())); // no permissions for uncommitted resource
+ }
+ }
+
+ // test getResourceGroupComposite
+ for (int i = 0; i < groupAvailCounts.size(); i++) {
+ LargeGroupEnvironment lge = env.get(i);
+ GroupAvailCounts gac = groupAvailCounts.get(i);
+
+ SessionTestHelper.simulateLogin(lge.normalSubject);
+ start = System.currentTimeMillis();
+ groupComp = groupManager.getResourceGroupComposite(lge.normalSubject, lge.compatibleGroup.getId());
+ System.out.println("getResourceGroupComposite #" + i + "==>" + (System.currentTimeMillis() - start) + "ms");
+ System.out.println("-->" + groupComp);
+ assert groupComp.getExplicitCount() == gac.visibleTotal;
+ assert groupComp.getExplicitCount() == groupComp.getImplicitCount(); // we aren't testing recursive groups
+ assert groupComp.getExplicitUp() == gac.up;
+ assert groupComp.getExplicitDown() == gac.down;
+ assert groupComp.getExplicitUnknown() == gac.unknown;
+ assert groupComp.getExplicitDisabled() == gac.disabled;
+ }
+ }
+
+ private Resource pickAResourceWithInventoryStatus(Resource platformResource, InventoryStatus status) {
+ for (Resource r : platformResource.getChildResources()) {
+ if (r.getInventoryStatus() == status) {
+ return r;
+ }
+ }
+ return null;
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/LdapGroupManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/LdapGroupManagerBeanTest.java
new file mode 100644
index 0000000..aaa0808
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/LdapGroupManagerBeanTest.java
@@ -0,0 +1,511 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 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.resource.group.test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Properties;
+
+import javax.persistence.Query;
+
+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.common.SystemConfiguration;
+import org.rhq.core.domain.common.composite.SystemSetting;
+import org.rhq.enterprise.server.RHQConstants;
+import org.rhq.enterprise.server.resource.group.LdapGroupManagerBean;
+import org.rhq.enterprise.server.resource.group.LdapGroupManagerLocal;
+import org.rhq.enterprise.server.system.SystemManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestServerPluginService;
+import org.rhq.enterprise.server.test.TransactionCallback;
+import org.rhq.enterprise.server.test.ldap.FakeLdapCtxFactory;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Integration tests for methods and operations performed by {@link LdapGroupManagerBean}.
+ * which require an LDAP server.
+ *
+ * When executing these tests, the LDAP source can be changed using the following
+ * system properties:
+ *
+ * <table>
+ * <tr><th align="left">Property</th><th align="left">Desc</th><th align="left">Default</th></tr>
+ * <tr>
+ * <td valign="top">rhq.test.ldap.url</td><td>The URL to use for an LDAP connection.</td><td valign="top">ldap://localhost:389</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">rhq.test.ldap.LDAPFactory</td><td>The ContextFactory class that will create the initial
+ * DirContext object for running the tests. This allows a mock or fake directory context to be
+ * created by another test class helper. For example, this could be {@link FakeLdapCtxFactory}
+ * or if you want to use a real LDAP server, you could specify com.sun.jndi.ldap.LdapCtxFactory
+ * which would then perform real LDAP operations with an LDAP server.</td><td valign="top">{@link FakeLdapCtxFactory}</td>
+ * </tr>
+ * </table>
+ *
+ * @author loleary
+ *
+ */
+@SuppressWarnings("deprecation")
+public class LdapGroupManagerBeanTest extends AbstractEJB3Test {
+
+ /**
+ * The property name that represents the LDAP URL to use. If using a real
+ * LDAP instance, this property's value should be the complete URL of the
+ * LDAP server to use for these integration tests.
+ */
+ public static String RHQ_TEST_LDAP_URL_PROPERTY = "rhq.test.ldap.url";
+ /**
+ * The property name that represents the LDAP Context Factory to use. If
+ * testing against a real LDAP instance, this property's value should be
+ * a valid context factory name as provided by a JNDI implementation.
+ *
+ * If no value is specified for this property, {@link #RHQ_TEST_LDAP_DEFAULT_CONTEXT_FACTORY}
+ * is used.
+ */
+ public static String RHQ_TEST_LDAP_LDAPFACTORY_PROPERTY = "rhq.test.ldap.LDAPFactory";
+
+ /**
+ * Default LDAP Context Factory value if a value is not defined by {@link #RHQ_TEST_LDAP_LDAPFACTORY_PROPERTY}
+ */
+ public static String RHQ_TEST_LDAP_DEFAULT_CONTEXT_FACTORY = FakeLdapCtxFactory.class.getCanonicalName();
+ /**
+ * Default LDAP URL value if a value is not defined by {@link #RHQ_TEST_LDAP_URL_PROPERTY}
+ */
+ public static String RHQ_TEST_LDAP_DEFAULT_URL = "ldap://localhost:389";
+
+ private LdapGroupManagerLocal ldapGroupManager = null;
+ private SystemManagerLocal systemManager = null;
+ private TestServerPluginService testServerPluginService = null;
+
+ // private Subject overlord = null;
+
+ @BeforeClass
+ @SuppressWarnings({ "unused" })
+ private void init() throws Throwable {
+ // overlord = LookupUtil.getSubjectManager().getOverlord();
+ systemManager = LookupUtil.getSystemManager();
+ ldapGroupManager = LookupUtil.getLdapGroupManager();
+ }
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ //we need this because the drift plugins are referenced from the system settings that we use in our tests
+ testServerPluginService = new TestServerPluginService();
+ prepareCustomServerPluginService(testServerPluginService);
+ testServerPluginService.startMasterPluginContainer();
+
+ // get our Maven properties for LDAP testing
+ java.net.URL url = LdapGroupManagerBeanTest.class.getClassLoader().getResource("test-ldap.properties");
+ Properties mvnProps = new Properties();
+ try {
+ if (url == null) {
+ throw new IOException("Unable to find test-ldap.properties in test envrionment's class loader");
+ }
+ mvnProps.load(url.openStream());
+ } catch (IOException e) {
+ System.err.println(" !!! Unable to load test-ldap.properties - All defaults are in place !!! ");
+ e.printStackTrace();
+ }
+
+ // Was an LDAP factory given?
+ String LDAPFactory = mvnProps.getProperty(RHQ_TEST_LDAP_LDAPFACTORY_PROPERTY);
+ if ((LDAPFactory == null) || ("${" + RHQ_TEST_LDAP_LDAPFACTORY_PROPERTY + "}").equals(LDAPFactory)) {
+ LDAPFactory = RHQ_TEST_LDAP_DEFAULT_CONTEXT_FACTORY; // none set use the default
+ }
+ this.setLdapCtxFactory(LDAPFactory);
+ System.out.println("!! Initial LDAP Context Factory is " + LDAPFactory + " !!");
+
+ String ldapUrl = mvnProps.getProperty(RHQ_TEST_LDAP_URL_PROPERTY);
+ if ((ldapUrl == null) || ("${" + RHQ_TEST_LDAP_URL_PROPERTY + "}").equals(ldapUrl)) {
+ ldapUrl = RHQ_TEST_LDAP_DEFAULT_URL; // none set so use default
+ }
+ this.setLdapUrl(ldapUrl);
+
+ this.setLdapBaseDN("dc=test,dc=rhq,dc=redhat,dc=com");
+ this.setLdapBindDN("uid=admin,ou=system");
+ this.setLdapBindPassword("secret");
+ this.setLdapUserFilter("objectClass=person");
+ this.setLdapLoginAttribute("uid");
+ this.setLdapGroupFilter("objectClass=groupOfNames");
+ this.setLdapGroupMemberAttribute("member");
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ unprepareServerPluginService();
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who does not exist in the test LDAP instance.
+ *
+ * The test verifies that no groups are returned for the non-existent user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForNonUser() throws Throwable {
+ // non-existent user
+ assertEquals(new HashSet<String>(), ldapGroupManager.findAvailableGroupsFor("gsmith"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has a no special characters in their cn attribute value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUserSimpleUseCase() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("rjosmith"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("jsmith"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("ssmith"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has a comma (,) in their cn attribute value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUserCommaChar() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("bcannon"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("ghause"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("bwalsh"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has a backslash (\) in their cn attribute value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUserBackslashChar() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("csamlin"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("cgroober"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("jkirk"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has a hash or pound sign (#) in their cn attribute value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUserHashChar() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("csellers"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("brogers"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("sphillips"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has a plus sign (+) in their cn attribute value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUserPlusChar() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("bbalanger"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("sreed"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("woverture"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has a less-than and greater-than sign (<>) in their cn
+ * attribute value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUserGTLTChar() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("bwallace"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("ltoller"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("callen"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has a semicolon (;) in their cn attribute value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUserSemiColonChar() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("zbalanger"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("hsimpsonite"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("wfredrick"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has a quote (") in their cn attribute value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUserQuoteChar() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("acallen"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("jmathers"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("smein"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has a equal sign (=) in their cn attribute value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUserEqualChar() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("ssmitherson"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("hrein"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("nsadler"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has a leading and trailing space (cn= My User ) in their
+ * cn attribute value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUserLTSpaceChar() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("bkiddough"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("sferguson"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("ssmiley"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has slash or forward slash (/) in their cn attribute
+ * value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUserSlashChar() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("sysapi"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("pscarlson"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("sysapi2"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has a hyphen or dash (-) in their cn attribute value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUserHyphenChar() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("lecroutche"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("samathers"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("sajeopardy"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has an asterisk or star (*) in their cn attribute value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUserAsteriskChar() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("sjeopardy"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("lcroutche"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("smathers"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has a open and close parenthesis () in their cn
+ * attribute value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUserParenthesisChar() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("bstrafford"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("kkrawford"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("jwilbright"));
+ }
+
+ /**
+ * Test {@link LdapGroupManagerBean#findAvailableGroupsFor(String)} method
+ * using a user who has an extended ASCII or non 7-bit ASCII character in
+ * their cn attribute value.
+ *
+ * The test verifies that an expected group list is returned for each user.
+ *
+ * @throws Throwable
+ */
+ @Test(groups = "integration.session")
+ public void testFindGroupsForUser8BitAsciiChar() throws Throwable {
+ assertEquals(new HashSet<String>(Arrays.asList("RHQ Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("mmechura"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Admin Group")),
+ ldapGroupManager.findAvailableGroupsFor("wsequerl"));
+ assertEquals(new HashSet<String>(Arrays.asList("JBoss Monitor Group")),
+ ldapGroupManager.findAvailableGroupsFor("pbrady"));
+ }
+
+ /*---------------
+ * Helper methods
+ ---------------*/
+ private void setSystemConfigProperty(final String name, final String value) throws Exception {
+ Properties sysConfig = systemManager.getSystemConfiguration(LookupUtil.getSubjectManager().getOverlord());
+ sysConfig.setProperty(name, value);
+ systemManager.setSystemConfiguration(LookupUtil.getSubjectManager().getOverlord(), sysConfig, true);
+ }
+
+ private void setLdapGroupFilter(String filter) throws Exception {
+ setSystemConfigProperty(RHQConstants.LDAPGroupFilter, filter);
+ }
+
+ private void setLdapGroupMemberAttribute(String attributeName) throws Exception {
+ setSystemConfigProperty(RHQConstants.LDAPGroupMember, attributeName);
+ }
+
+ private void setLdapBaseDN(String dn) throws Exception {
+ setSystemConfigProperty(RHQConstants.LDAPBaseDN, dn);
+ }
+
+ private void setLdapLoginAttribute(String attributeName) throws Exception {
+ setSystemConfigProperty(RHQConstants.LDAPLoginProperty, attributeName);
+ }
+
+ private void setLdapBindDN(String dn) throws Exception {
+ setSystemConfigProperty(RHQConstants.LDAPBindDN, dn);
+ }
+
+ private void setLdapBindPassword(String password) throws Exception {
+ setSystemConfigProperty(RHQConstants.LDAPBindPW, password);
+ }
+
+ private void setLdapUserFilter(String filter) throws Exception {
+ setSystemConfigProperty(RHQConstants.LDAPFilter, filter);
+ }
+
+ private void setLdapUrl(String url) throws Exception {
+ setSystemConfigProperty(RHQConstants.LDAPUrl, url);
+ }
+
+ private void setLdapCtxFactory(final String name) throws Exception {
+ //this is a readonly system property that we are trying to override, so we
+ //need to be a little bit more persuasive...
+ executeInTransaction(new TransactionCallback() {
+ @Override
+ public void execute() throws Exception {
+ Query q = getEntityManager().createNamedQuery(SystemConfiguration.FIND_PROPERTY_BY_KEY);
+ q.setParameter("key", SystemSetting.LDAP_NAMING_FACTORY.getInternalName());
+
+ SystemConfiguration config = (SystemConfiguration) q.getSingleResult();
+ config.setPropertyValue(name);
+
+ getEntityManager().merge(config);
+
+ getEntityManager().flush();
+ }
+ });
+
+ //reload the system settings cache so that the new value is reflected there immediately
+ systemManager.loadSystemConfigurationCache();
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/RecursiveResourceGroupTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/RecursiveResourceGroupTest.java
new file mode 100644
index 0000000..597cb26
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/group/test/RecursiveResourceGroupTest.java
@@ -0,0 +1,476 @@
+/*
+ * 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.enterprise.server.resource.group.test;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+
+import javax.persistence.EntityManager;
+import javax.transaction.Status;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.authz.Role;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.util.jdbc.JDBCUtil;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.authz.RoleManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.ResourceTreeHelper;
+import org.rhq.enterprise.server.util.SessionTestHelper;
+
+public class RecursiveResourceGroupTest extends AbstractEJB3Test {
+
+ private ResourceGroupManagerLocal resourceGroupManager;
+ private ResourceManagerLocal resourceManager;
+ private RoleManagerLocal roleManager;
+ private SubjectManagerLocal subjectManager;
+
+ @BeforeMethod
+ protected void init() {
+ resourceGroupManager = LookupUtil.getResourceGroupManager();
+ resourceManager = LookupUtil.getResourceManager();
+ roleManager = LookupUtil.getRoleManager();
+ subjectManager = LookupUtil.getSubjectManager();
+ prepareScheduler();
+ }
+
+ @AfterMethod
+ protected void after() throws Exception {
+ unprepareScheduler();
+ }
+
+ @Test(groups = "integration.session")
+ public void testImplicitGroupMembershipFromInventoryUpdate() throws Throwable {
+ getTransactionManager().begin();
+ try {
+ EntityManager em = getEntityManager();
+
+ // setup simple test structures
+ Subject subject = SessionTestHelper.createNewSubject(em, "fake subject");
+ Role role = SessionTestHelper
+ .createNewRoleForSubject(em, subject, "fake role", Permission.MANAGE_INVENTORY);
+
+ ResourceGroup recursiveGroup = SessionTestHelper.createNewMixedGroupForRole(em, role, "fake group", true);
+
+ // setup the test tree
+ List<Resource> fullTree = getSimpleTree(em);
+
+ // test simple implicit resources
+ Resource nodeA = ResourceTreeHelper.findNode(fullTree, "A");
+
+ List<Resource> resourcesFromTreeA = ResourceTreeHelper.getSubtree(nodeA);
+
+ resourceGroupManager.addResourcesToGroup(subject, recursiveGroup.getId(), new int[] { nodeA.getId() });
+ List<Resource> initialExplicitResources = resourceManager.findExplicitResourcesByResourceGroup(subject,
+ recursiveGroup, PageControl.getUnlimitedInstance());
+
+ assert initialExplicitResources.size() == 1 : "Failed: initial explicit resources, size was "
+ + initialExplicitResources.size();
+ assert initialExplicitResources.get(0).getId() == nodeA.getId() : "Failed: initial explicit resources id, found "
+ + initialExplicitResources.get(0).getId() + ", expected " + nodeA.getId();
+
+ List<Resource> initialImplicitResources = resourceManager.findImplicitResourcesByResourceGroup(subject,
+ recursiveGroup, PageControl.getUnlimitedInstance());
+ verifyEqualByIds("Failed: initial implicit resources", resourcesFromTreeA, initialImplicitResources);
+
+ // test update implicit resources
+ Resource newChildOfNodeA = new Resource("new nodeOne child", "new nodeOne child", nodeA.getResourceType());
+ newChildOfNodeA.setUuid("" + new Random().nextInt());
+ newChildOfNodeA.setInventoryStatus(InventoryStatus.COMMITTED);
+
+ resourceManager.createResource(subject, newChildOfNodeA, nodeA.getId()); // sets up implicit relationships
+
+ List<Resource> updatedImplicitResources = resourceManager.findImplicitResourcesByResourceGroup(subject,
+ recursiveGroup, PageControl.getUnlimitedInstance());
+
+ resourcesFromTreeA.add(newChildOfNodeA);
+ verifyEqualByIds("Failed: simple implicit resources", resourcesFromTreeA, updatedImplicitResources);
+ } catch (Throwable t) {
+ handleThrowable(t);
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test(groups = "integration.session")
+ public void testUpdateImplicitGroupMembership() throws Throwable {
+ getTransactionManager().begin();
+ try {
+ EntityManager em = getEntityManager();
+
+ // setup simple test structures
+ Subject subject = SessionTestHelper.createNewSubject(em, "fake subject");
+ Role role = SessionTestHelper
+ .createNewRoleForSubject(em, subject, "fake role", Permission.MANAGE_INVENTORY);
+
+ ResourceGroup lineageG1 = SessionTestHelper.createNewMixedGroupForRole(em, role, "gen1", true);
+ ResourceGroup lineageG2 = SessionTestHelper.createNewMixedGroupForRole(em, role, "gen2", true);
+ ResourceGroup lineageG3 = SessionTestHelper.createNewMixedGroupForRole(em, role, "gen3", true);
+ ResourceGroup lineageG4 = SessionTestHelper.createNewMixedGroupForRole(em, role, "gen4", true);
+
+ // setup the test tree
+ List<Resource> fullTree = ResourceTreeHelper.createTree(em, "A=1; 1=a; a=i;"); // resource chain
+ Resource gen1 = ResourceTreeHelper.findNode(fullTree, "A");
+ Resource gen2 = ResourceTreeHelper.findNode(fullTree, "1");
+ Resource gen3 = ResourceTreeHelper.findNode(fullTree, "a");
+ Resource gen4 = ResourceTreeHelper.findNode(fullTree, "i");
+
+ resourceGroupManager.addResourcesToGroup(subject, lineageG1.getId(), new int[] { gen1.getId() });
+ resourceGroupManager.addResourcesToGroup(subject, lineageG2.getId(), new int[] { gen2.getId() });
+ resourceGroupManager.addResourcesToGroup(subject, lineageG3.getId(), new int[] { gen3.getId() });
+ resourceGroupManager.addResourcesToGroup(subject, lineageG4.getId(), new int[] { gen4.getId() });
+
+ // test update implicit resources
+ Resource gen5 = new Resource("g5", "g5", gen4.getResourceType());
+ gen5.setUuid("" + new Random().nextInt());
+ gen5.setInventoryStatus(InventoryStatus.COMMITTED);
+ resourceManager.createResource(subject, gen5, gen4.getId()); // sets up implicit relationships
+
+ // confirm results
+ List<Integer> newLineageG1 = resourceManager.findImplicitResourceIdsByResourceGroup(lineageG1.getId());
+ List<Integer> newLineageG2 = resourceManager.findImplicitResourceIdsByResourceGroup(lineageG2.getId());
+ List<Integer> newLineageG3 = resourceManager.findImplicitResourceIdsByResourceGroup(lineageG3.getId());
+ List<Integer> newLineageG4 = resourceManager.findImplicitResourceIdsByResourceGroup(lineageG4.getId());
+
+ List<Resource> treeGen1 = ResourceTreeHelper.getSubtree(gen1);
+ List<Resource> treeGen2 = ResourceTreeHelper.getSubtree(gen2);
+ List<Resource> treeGen3 = ResourceTreeHelper.getSubtree(gen3);
+ List<Resource> treeGen4 = ResourceTreeHelper.getSubtree(gen4);
+
+ // gen5 resource should have been added to all of them
+ treeGen1.add(gen5);
+ treeGen2.add(gen5);
+ treeGen3.add(gen5);
+ treeGen4.add(gen5);
+
+ verifyEqual("Failed: updateImplicitGroupMembership gen1", getIds(treeGen1), newLineageG1);
+ verifyEqual("Failed: updateImplicitGroupMembership gen2", getIds(treeGen2), newLineageG2);
+ verifyEqual("Failed: updateImplicitGroupMembership gen3", getIds(treeGen3), newLineageG3);
+ verifyEqual("Failed: updateImplicitGroupMembership gen4", getIds(treeGen4), newLineageG4);
+ } catch (Throwable t) {
+ handleThrowable(t);
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test(groups = "integration.session")
+ public void testImplicitGroupMembershipFromComplexGroupUpdates() throws Throwable {
+ Subject subject = null;
+ Role role = null;
+ ResourceGroup recursiveGroup = null;
+ List<Resource> fullTree = null;
+
+ Resource nodeBigA = null;
+ Resource nodeOne = null;
+ Resource nodeThree = null;
+ Resource nodeLittleA = null;
+ Resource nodeTripleLittleI = null;
+
+ List<Resource> resultsExplicit = null;
+
+ List<Resource> expectedImplicit = null;
+ List<Resource> expectedExplicit = new ArrayList<Resource>();
+
+ try {
+ try {
+ getTransactionManager().begin();
+
+ EntityManager em = getEntityManager();
+ // setup simple test structures
+ subject = SessionTestHelper.createNewSubject(em, "fake subject");
+ role = SessionTestHelper.createNewRoleForSubject(em, subject, "fake role", Permission.MANAGE_INVENTORY);
+ recursiveGroup = SessionTestHelper.createNewMixedGroupForRole(em, role, "fake group", true);
+
+ // setup the test tree
+ fullTree = getSimpleTree(em);
+
+ ResourceTreeHelper.printForest(fullTree);
+
+ // get the resources from the tree we want to explicitly add
+ nodeBigA = ResourceTreeHelper.findNode(fullTree, "A");
+ nodeOne = ResourceTreeHelper.findNode(fullTree, "1");
+ nodeThree = ResourceTreeHelper.findNode(fullTree, "3");
+ nodeLittleA = ResourceTreeHelper.findNode(fullTree, "a");
+ nodeTripleLittleI = ResourceTreeHelper.findNode(fullTree, "iii");
+
+ // adding nodeLittleA should give us the subtree under nodeLittleA
+ expectedImplicit = ResourceTreeHelper.getSubtree(nodeLittleA);
+ implicitGroupMembershipAddHelper(subject, recursiveGroup, nodeLittleA, expectedImplicit);
+ resultsExplicit = resourceManager.findExplicitResourcesByResourceGroup(subject, recursiveGroup,
+ PageControl.getUnlimitedInstance());
+ expectedExplicit.add(nodeLittleA);
+ verifyEqualByIds("explicit add 1", expectedExplicit, resultsExplicit);
+
+ // adding nodeThree should give us the union of the subtrees under nodeLittleA and nodeThree
+ expectedImplicit.add(nodeThree);
+ implicitGroupMembershipAddHelper(subject, recursiveGroup, nodeThree, expectedImplicit);
+ resultsExplicit = resourceManager.findExplicitResourcesByResourceGroup(subject, recursiveGroup,
+ PageControl.getUnlimitedInstance());
+ expectedExplicit.add(nodeThree);
+ verifyEqualByIds("explicit add 2", expectedExplicit, resultsExplicit);
+
+ // adding nodeBigA should give us the union of the entire A tree with the nodeThree subtree
+ expectedImplicit = ResourceTreeHelper.getSubtree(nodeBigA);
+ expectedImplicit.addAll(ResourceTreeHelper.getSubtree(nodeThree));
+ implicitGroupMembershipAddHelper(subject, recursiveGroup, nodeBigA, expectedImplicit);
+ resultsExplicit = resourceManager.findExplicitResourcesByResourceGroup(subject, recursiveGroup,
+ PageControl.getUnlimitedInstance());
+ expectedExplicit.add(nodeBigA);
+ verifyEqualByIds("explicit add 3", expectedExplicit, resultsExplicit);
+
+ // adding nodeOne, which is a child of nodeBigA, shouldn't effect the expected results
+ implicitGroupMembershipAddHelper(subject, recursiveGroup, nodeOne, expectedImplicit);
+ resultsExplicit = resourceManager.findExplicitResourcesByResourceGroup(subject, recursiveGroup,
+ PageControl.getUnlimitedInstance());
+ expectedExplicit.add(nodeOne);
+ verifyEqualByIds("explicit add 4", expectedExplicit, resultsExplicit);
+
+ // adding nodeTripleLittleI shouldn't effect the expected results either
+ implicitGroupMembershipAddHelper(subject, recursiveGroup, nodeTripleLittleI, expectedImplicit);
+ resultsExplicit = resourceManager.findExplicitResourcesByResourceGroup(subject, recursiveGroup,
+ PageControl.getUnlimitedInstance());
+ expectedExplicit.add(nodeTripleLittleI);
+ verifyEqualByIds("explicit add 5", expectedExplicit, resultsExplicit);
+ } catch (Throwable t) {
+ handleThrowable(t);
+ } finally {
+ handleTransaction();
+ }
+
+ try {
+ getTransactionManager().begin();
+ // removing the subtree nodeTripleLittleI shouldn't affect the expected set
+ implicitGroupMembershipRemoveHelper(subject, recursiveGroup, nodeTripleLittleI, expectedImplicit);
+ } catch (Throwable t) {
+ handleThrowable(t);
+ } finally {
+ handleTransaction();
+ }
+
+ try {
+ getTransactionManager().begin();
+
+ // removing a descendant of a node that is also in the explicit list should be a no-op
+ implicitGroupMembershipRemoveHelper(subject, recursiveGroup, nodeOne, expectedImplicit);
+
+ expectedImplicit.remove(nodeThree);
+ // removing the wandering nodeThree, so that results will be the complete nodeBigA subtree
+ implicitGroupMembershipRemoveHelper(subject, recursiveGroup, nodeThree, expectedImplicit);
+
+ // removing a root node should remove all descendants that aren't still in the explicit list
+ implicitGroupMembershipRemoveHelper(subject, recursiveGroup, nodeBigA,
+ ResourceTreeHelper.getSubtree(nodeLittleA));
+ } catch (Throwable t) {
+ handleThrowable(t);
+ } finally {
+ handleTransaction();
+ }
+
+ try {
+ getTransactionManager().begin();
+
+ // remove a node that wasn't in the group - negative testing
+ try {
+ // passing the "real" expected list for the results; this way, if the exception doesn't happen, the helper returns true
+ implicitGroupMembershipRemoveHelper(subject, recursiveGroup, nodeBigA,
+ ResourceTreeHelper.getSubtree(nodeLittleA));
+ assert false : "Failed: removed non-existent successfully: node = " + nodeBigA.getName();
+ } catch (Throwable t) {
+ // expected
+ }
+ } catch (Throwable t) {
+ handleThrowable(t);
+ } finally {
+ handleTransaction();
+ }
+
+ try {
+ getTransactionManager().begin();
+
+ // removing the last resource should leave an empty list
+ implicitGroupMembershipRemoveHelper(subject, recursiveGroup, nodeLittleA, new ArrayList<Resource>());
+ } catch (Throwable t) {
+ handleThrowable(t);
+ } finally {
+ handleTransaction();
+ }
+
+ try {
+ getTransactionManager().begin();
+ // remove a node that wasn't in the group - negative testing
+ try {
+ // passing the "real" expected list for the results; this way, if the exception doesn't happen, the helper returns true
+ Resource nodeBigB = ResourceTreeHelper.findNode(fullTree, "B");
+ implicitGroupMembershipRemoveHelper(subject, recursiveGroup, nodeBigB,
+ ResourceTreeHelper.getSubtree(nodeBigA));
+ assert false : "Failed: removed non-existent successfully: node = " + nodeBigB.getName();
+ } catch (Throwable t) {
+ // expected
+ }
+ } catch (Throwable t) {
+ handleThrowable(t);
+ } finally {
+ handleTransaction();
+ }
+
+ try {
+ getTransactionManager().begin();
+ resultsExplicit = resourceManager.findExplicitResourcesByResourceGroup(subject, recursiveGroup,
+ PageControl.getUnlimitedInstance());
+ verifyEqualByIds("explicit remove 0", new ArrayList<Resource>(), resultsExplicit);
+ } catch (Throwable t) {
+ handleThrowable(t);
+ } finally {
+ handleTransaction();
+ }
+
+ } finally {
+ // clean up anything that may have gotten created
+ try {
+ getTransactionManager().begin();
+
+ EntityManager em = getEntityManager();
+
+ Subject overlord = subjectManager.getOverlord();
+
+ if (null != subject) {
+ subjectManager.deleteUsers(overlord, new int[] { subject.getId() });
+ }
+ if (null != role) {
+ roleManager.deleteRoles(overlord, new int[] { role.getId() });
+ }
+ if (null != recursiveGroup) {
+ resourceGroupManager.deleteResourceGroup(overlord, recursiveGroup.getId());
+ }
+
+ if (null != fullTree) {
+ ResourceTreeHelper.deleteForest(em, fullTree);
+ }
+
+ } catch (Throwable t) {
+ handleThrowable(t);
+ } finally {
+ handleTransaction();
+ }
+ }
+ }
+
+ private void handleTransaction() {
+ try {
+ if (getTransactionManager().getTransaction().getStatus() == Status.STATUS_MARKED_ROLLBACK) {
+ getTransactionManager().rollback();
+ } else {
+ getTransactionManager().commit();
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+ private void handleThrowable(Throwable t) throws Throwable {
+ if (t instanceof SQLException) {
+ String error = JDBCUtil.convertSQLExceptionToString((SQLException) t);
+ System.err.println(error);
+ } else {
+ t.printStackTrace();
+ }
+ throw t;
+ }
+
+ private void printGroup(String prefix, Subject subject, ResourceGroup group) {
+ print(prefix + ": exp",
+ resourceManager.findExplicitResourcesByResourceGroup(subject, group, PageControl.getUnlimitedInstance()));
+ print(prefix + ": imp",
+ resourceManager.findImplicitResourcesByResourceGroup(subject, group, PageControl.getUnlimitedInstance()));
+ }
+
+ private void print(String prefix, List<Resource> resources) {
+ System.out.print(prefix + ": ");
+ for (Resource res : resources) {
+ System.out.print(res.getName() + " ");
+ }
+ System.out.println();
+ }
+
+ private void implicitGroupMembershipAddHelper(Subject subject, ResourceGroup recursiveGroup, Resource node,
+ List<Resource> expectedResults) {
+ printGroup("complex implicit before add: node = " + node.getName() + " [" + node.getId() + "]", subject,
+ recursiveGroup);
+ resourceGroupManager.addResourcesToGroup(subject, recursiveGroup.getId(), new int[] { node.getId() });
+ printGroup("complex implicit after add: node = " + node.getName() + " [" + node.getId() + "]", subject,
+ recursiveGroup);
+ List<Resource> implicitResources = resourceManager.findImplicitResourcesByResourceGroup(subject,
+ recursiveGroup, PageControl.getUnlimitedInstance());
+ verifyEqualByIds("Failed: complex implicit add: node = " + node.getName() + " [" + node.getId() + "]",
+ expectedResults, implicitResources);
+ }
+
+ private void implicitGroupMembershipRemoveHelper(Subject subject, ResourceGroup recursiveGroup, Resource node,
+ List<Resource> expectedResults) {
+ printGroup("complex implicit before remove: node = " + node.getName() + " [" + node.getId() + "]", subject,
+ recursiveGroup);
+ resourceGroupManager.removeResourcesFromGroup(subject, recursiveGroup.getId(), new int[] { node.getId() });
+ printGroup("complex implicit after remove: node = " + node.getName() + " [" + node.getId() + "]", subject,
+ recursiveGroup);
+ List<Resource> implicitResources = resourceManager.findImplicitResourcesByResourceGroup(subject,
+ recursiveGroup, PageControl.getUnlimitedInstance());
+ verifyEqualByIds("Failed: complex implicit remove: node = " + node.getName() + " [" + node.getId() + "]",
+ expectedResults, implicitResources);
+ }
+
+ private void verifyEqualByIds(String errorMessage, List<Resource> expected, List<Resource> results) {
+ List<Integer> expectedIds = getIds(expected);
+ List<Integer> resultsIds = getIds(results);
+ verifyEqual(errorMessage, expectedIds, resultsIds);
+ }
+
+ private void verifyEqual(String errorMessage, List<Integer> expectedIds, List<Integer> resultsIds) {
+ assert (expectedIds.containsAll(resultsIds) && resultsIds.containsAll(expectedIds)) : errorMessage
+ + "\nexpected = " + expectedIds + "\nresults = " + resultsIds;
+ }
+
+ private List<Integer> getIds(List<Resource> resources) {
+ List<Integer> results = new ArrayList<Integer>();
+ for (Resource res : resources) {
+ results.add(res.getId());
+ }
+ Collections.sort(results);
+ return results;
+ }
+
+ private List<Resource> getSimpleTree(EntityManager em) {
+ return ResourceTreeHelper.createTree(em, "A=1,2; 1=a,b; a=i,ii; b=iii,iv; B=3");
+ }
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/AlertMetadataManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/AlertMetadataManagerBeanTest.java
new file mode 100644
index 0000000..29c146f
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/AlertMetadataManagerBeanTest.java
@@ -0,0 +1,64 @@
+package org.rhq.enterprise.server.resource.metadata;
+
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.alert.AlertDampening;
+import org.rhq.core.domain.alert.AlertDefinition;
+import org.rhq.core.domain.alert.AlertPriority;
+import org.rhq.core.domain.alert.BooleanExpression;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.alert.AlertTemplateManagerLocal;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+public class AlertMetadataManagerBeanTest extends MetadataBeanTest {
+
+ @Test(groups = {"plugin.metadata", "Alerts.NewPlugin"})
+ public void registerAlertsPlugin() throws Exception {
+ createPlugin("alert-test-plugin", "1.0", "plugin_v1.xml");
+ }
+
+ @Test(groups = {"plugin.metadata", "Alerts.NewPlugin"}, dependsOnMethods = {"registerAlertsPlugin"})
+ public void createAlertTemplates() throws Exception {
+ createAlertTemplate("AlertServer Template 1", "AlertServer", "AlertMetadataManagerBeanTestPlugin");
+ createAlertTemplate("AlertServer Template 2", "AlertServer", "AlertMetadataManagerBeanTestPlugin");
+ }
+
+ @Test(groups = {"plugin.metadata", "UpgradePlugin"}, dependsOnGroups = {"Alerts.NewPlugin"})
+ public void upgradeAlertsPlugin() throws Exception {
+ createPlugin("alert-test-plugin", "2.0", "plugin_v2.xml");
+ }
+
+ @Test(groups = {"plugin.metadata", "Alerts.UpgradePlugin"}, dependsOnMethods = {"upgradeAlertsPlugin"})
+ public void deleteAlertTemplates() {
+ List templates = getEntityManager().createQuery("from AlertDefinition a where a.resourceType.name = :type")
+ .setParameter("type", "AlertServer")
+ .getResultList();
+
+ assertEquals("Alert templates should have been deleted.", 0, templates.size());
+ }
+
+ void createAlertTemplate(String name, String resourceTypeName, String pluginName) throws Exception {
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+ ResourceTypeManagerLocal resourceTypeMgr = LookupUtil.getResourceTypeManager();
+ AlertTemplateManagerLocal alertTemplateMgr = LookupUtil.getAlertTemplateManager();
+
+ ResourceType resourceType = resourceTypeMgr.getResourceTypeByNameAndPlugin(resourceTypeName, pluginName);
+ assertNotNull("Cannot create alert template. Unable to find resource type for [name: " + resourceTypeName +
+ ", plugin: " + pluginName + "]", resourceType);
+
+ AlertDefinition alertDef = new AlertDefinition();
+ alertDef.setName(name);
+ alertDef.setPriority(AlertPriority.MEDIUM);
+ alertDef.setResourceType(resourceType);
+ alertDef.setConditionExpression(BooleanExpression.ALL);
+ alertDef.setAlertDampening(new AlertDampening(AlertDampening.Category.NONE));
+ alertDef.setRecoveryId(0);
+
+ alertTemplateMgr.createAlertTemplate(subjectMgr.getOverlord(), alertDef, resourceType.getId());
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ContentMetadataManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ContentMetadataManagerBeanTest.java
new file mode 100644
index 0000000..6f5582a
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ContentMetadataManagerBeanTest.java
@@ -0,0 +1,127 @@
+package org.rhq.enterprise.server.resource.metadata;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.EMPTY_LIST;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.bundle.BundleType;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.resource.ResourceType;
+
+public class ContentMetadataManagerBeanTest extends MetadataBeanTest {
+
+ @Test(groups = { "plugin.metadata", "Content.NewPlugin" })
+ public void registerContentPlugin() throws Exception {
+ createPlugin("content-test-plugin", "1.0", "plugin_v1.xml");
+ }
+
+ @Test(groups = { "plugin.metadata", "Content.UpgradePlugin" }, dependsOnGroups = { "Content.NewPlugin" })
+ public void upgradeContentPlugin() throws Exception {
+ createPlugin("content-test-plugin", "2.0", "plugin_v2.xml");
+ }
+
+ @Test(groups = { "plugin.metadata", "Content.UpgradePlugin" }, dependsOnMethods = { "upgradeContentPlugin" })
+ public void addPackageTypes() throws Exception {
+ assertResourceTypeAssociationEquals("ContentServer1", "ContentMetadataManagerBeanTestPlugin", "packageTypes",
+ asList("ContentServer1.Content.1", "ContentServer1.Content.2"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Content.UpgradePlugin" }, dependsOnMethods = { "upgradeContentPlugin" })
+ public void deletePackageTypes() throws Exception {
+ assertResourceTypeAssociationEquals("ContentServer2", "ContentMetadataManagerBeanTestPlugin", "packageTypes",
+ EMPTY_LIST);
+ }
+
+ @Test(groups = { "plugin.metadata", "Content.UpgradePlugin" }, dependsOnMethods = { "upgradeContentPlugin" })
+ public void deletePackageTypesThatExistsInOldResourceTypeButNotInNewResourceType() throws Exception {
+ assertResourceTypeAssociationEquals("ContentServer3", "ContentMetadataManagerBeanTestPlugin", "packageTypes",
+ asList("ContentServer3.Content.2", "ContentServer3.Content.3"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Content.UpgradePlugin" }, dependsOnMethods = { "upgradeContentPlugin" })
+ public void addPackageThatAreAddedInNewResourceType() throws Exception {
+ assertResourceTypeAssociationEquals("ContentServer4", "ContentMetadataManagerBeanTestPlugin", "packageTypes",
+ asList("ContentServer4.Content.1", "ContentServer4.Content.2"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Content.UpgradePlugin" }, dependsOnMethods = { "upgradeContentPlugin" })
+ public void addNewDeploymentConfigurationDefinition() throws Exception {
+ PackageType packageType = loadPackageType("ContentServer", "ContentMetadataManagerBeanTestPlugin",
+ "ContentServer.Content.1");
+
+ ConfigurationDefinition deploymentConfigDef = packageType.getDeploymentConfigurationDefinition();
+
+ assertNotNull(
+ "Failed to create new deployment configuration definition for package type that previously did not have one",
+ deploymentConfigDef);
+ assertEquals("Expected to find 1 property definition in new deployment configuration definition", 1,
+ deploymentConfigDef.getPropertyDefinitions().size());
+ assertNotNull("Expected to find 1 property definition, <version>, in new deployment configuration definition",
+ deploymentConfigDef.get("version"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Content.UpgradePlugin" }, dependsOnMethods = { "upgradeContentPlugin" })
+ public void updateDeploymentConfigDefThatExistsInOldAndNewResourceType() throws Exception {
+ PackageType packageType = loadPackageType("ContentServer5", "ContentMetadataManagerBeanTestPlugin",
+ "ContentServer5.Content.1");
+ ConfigurationDefinition deploymentConfigDef = packageType.getDeploymentConfigurationDefinition();
+
+ assertNotNull("Failed to update deployment configuration definition for package type", deploymentConfigDef);
+ assertEquals("Expected to find 2 property definitions in updated deployment configuration definition", 2,
+ deploymentConfigDef.getPropertyDefinitions().size());
+ assertNotNull("Expected existing property definition to be retained across update",
+ deploymentConfigDef.get("x"));
+ assertNotNull("Expected new property definition to be added during update", deploymentConfigDef.get("y"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Content.UpgradePlugin" }, dependsOnMethods = { "upgradeContentPlugin" })
+ public void deleteDeploymentConfigDefThatIsRemovedInNewResourceType() {
+ PackageType packageType = loadPackageType("ContentServer5", "ContentMetadataManagerBeanTestPlugin",
+ "ContentServer5.Content.2");
+
+ assertNull(
+ "Expected deployment configuration definition to be removed since it was removed from new resource type",
+ packageType.getDeploymentConfigurationDefinition());
+ }
+
+ @Test(groups = { "plugin.metadata", "Content.UpgradePlugin" }, dependsOnMethods = { "upgradeContentPlugin" })
+ public void updateBundleType() {
+ ResourceType resourceType = loadResourceTypeWithBundleType("ContentServer7",
+ "ContentMetadataManagerBeanTestPlugin");
+ BundleType bundleType = resourceType.getBundleType();
+
+ assertNotNull("Failed to upgrade bundle type", bundleType);
+ assertEquals("Failed to upgrade bundle type correctly. The bundle type name is wrong",
+ "ContentServer.Bundle.2", bundleType.getName());
+ }
+
+ @Test(groups = { "plugin.metadata", "Content.UpgradePlugin" }, dependsOnMethods = { "upgradeContentPlugin" })
+ public void addBundleTypeThatOnlyExistsInNewResourceType() {
+ ResourceType resourceType = loadResourceTypeWithBundleType("ContentServer6",
+ "ContentMetadataManagerBeanTestPlugin");
+ BundleType bundleType = resourceType.getBundleType();
+
+ assertNotNull("Expected to find bundle type added during upgrade", bundleType);
+ assertEquals("Failed to correctly add bundle type during upgrade", "ContentServer6.Bundle.1",
+ bundleType.getName());
+ }
+
+ PackageType loadPackageType(String resourceType, String plugin, String packageType) {
+ return (PackageType) getEntityManager()
+ .createQuery(
+ "from PackageType p left join fetch p.deploymentConfigurationDefinition pdcd "
+ + "where p.name = :packageType and " + "p.resourceType.name = :resourceType and "
+ + "p.resourceType.plugin = :plugin").setParameter("packageType", packageType)
+ .setParameter("plugin", plugin).setParameter("resourceType", resourceType).getSingleResult();
+ }
+
+ ResourceType loadResourceTypeWithBundleType(String resourceType, String plugin) {
+ return (ResourceType) getEntityManager()
+ .createQuery(
+ "from ResourceType t left join fetch t.bundleType tbt where t.name = :resourceType and t.plugin = :plugin")
+ .setParameter("resourceType", resourceType).setParameter("plugin", plugin).getSingleResult();
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/EventMetadataManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/EventMetadataManagerBeanTest.java
new file mode 100644
index 0000000..99e1e22
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/EventMetadataManagerBeanTest.java
@@ -0,0 +1,69 @@
+package org.rhq.enterprise.server.resource.metadata;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.EMPTY_LIST;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.event.EventDefinition;
+
+public class EventMetadataManagerBeanTest extends MetadataBeanTest {
+
+ @Test(groups = { "plugin.metadata", "Events.NewPlugin" })
+ public void registerEventsPlugin() throws Exception {
+ createPlugin("event-test-plugin", "1.0", "plugin_v1.xml");
+ }
+
+ @Test(groups = { "plugin.metadata", "Events.NewPlugin" }, dependsOnMethods = { "registerEventsPlugin" })
+ public void persistNewEventDefs() throws Exception {
+ assertResourceTypeAssociationEquals("EventServer1", "EventMetadataManagerBeanTestPlugin", "eventDefinitions",
+ asList("event1", "event2"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Events.NewPlugin" }, dependsOnMethods = { "persistNewEventDefs" })
+ public void persistNewEventDefProperties() {
+ EventDefinition eventDef = loadEventDef("event1", "EventServer1");
+
+ assertEquals("Failed to set EventDefinition.name", "event1", eventDef.getName());
+ assertEquals("Failed to set EventDefinition.description", "Event 1", eventDef.getDescription());
+ }
+
+ @Test(groups = { "plugin.metadata", "Events.UpgradePlugin" }, dependsOnGroups = { "Events.NewPlugin" })
+ public void upgradeEventsPlugin() throws Exception {
+ createPlugin("event-test-plugin", "2.0", "plugin_v2.xml");
+ }
+
+ @Test(groups = { "plugin.metadata", "Events.UpgradePlugin" }, dependsOnMethods = { "upgradeEventsPlugin" })
+ public void retainEventDefsOfTypeThatIsNotChangedDuringUpgrade() throws Exception {
+ assertResourceTypeAssociationEquals("EventServer1", "EventMetadataManagerBeanTestPlugin", "eventDefinitions",
+ asList("event1", "event2"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Events.UpgradePlugin" }, dependsOnMethods = { "upgradeEventsPlugin" })
+ public void addNewEventDefs() throws Exception {
+ assertResourceTypeAssociationEquals("EventServer2", "EventMetadataManagerBeanTestPlugin", "eventDefinitions",
+ asList("event1", "event2"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Events.UpgradePlugin" }, dependsOnMethods = { "upgradeEventsPlugin" })
+ public void deleteEventDefsThatHaveBeenRemovedInUpgradedType() throws Exception {
+ assertResourceTypeAssociationEquals("EventServer3", "EventMetadataManagerBeanTestPlugin", "eventDefinitions",
+ EMPTY_LIST);
+ }
+
+ @Test(groups = { "plugin.metadata", "Events.UpgradePlugin" }, dependsOnMethods = { "upgradeEventsPlugin" })
+ public void updateExistingEventDefs() throws Exception {
+ assertResourceTypeAssociationEquals("EventServer4", "EventMetadataManagerBeanTestPlugin", "eventDefinitions",
+ asList("event1", "event3"));
+
+ EventDefinition eventDef = loadEventDef("event1", "EventServer4");
+ assertEquals("The description property should have been updated", "EVENT ONE", eventDef.getDescription());
+ }
+
+ EventDefinition loadEventDef(String name, String resourceType) {
+ return (EventDefinition) getEntityManager()
+ .createQuery("from EventDefinition e where e.name = :name and e.resourceType.name = :resourceType")
+ .setParameter("name", name).setParameter("resourceType", resourceType).getSingleResult();
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MeasurementMetadataManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MeasurementMetadataManagerBeanTest.java
new file mode 100644
index 0000000..22834fa
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MeasurementMetadataManagerBeanTest.java
@@ -0,0 +1,238 @@
+package org.rhq.enterprise.server.resource.metadata;
+
+import static java.util.Arrays.asList;
+
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.DisplayType;
+import org.rhq.core.domain.measurement.MeasurementCategory;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.measurement.NumericType;
+import org.rhq.test.AssertUtils;
+
+public class MeasurementMetadataManagerBeanTest extends MetadataBeanTest {
+
+ @Test(groups = { "plugin.metadata", "Metrics.NewPlugin" })
+ void registerMetricsPlugin() throws Exception {
+ createPlugin("metric-test-plugin", "1.0", "plugin_v1.xml");
+ }
+
+ @Test(groups = { "plugin.metadata", "Metrics.NewPlugin" }, dependsOnMethods = { "registerMetricsPlugin" })
+ public void persistNewMetrics() throws Exception {
+ assertResourceTypeAssociationEquals("MetricServer1", "MeasurementMetadataManagerBeanTestPlugin",
+ "metricDefinitions", asList("metric1", "metric2", "metric3", "rhq.availability"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Metrics.NewPlugin" }, dependsOnMethods = { "persistNewMetrics" })
+ public void persistNewTraitDefinitionProperties() {
+ MeasurementDefinition traitDef = loadMeasurementDef("metric1", "MetricServer1");
+
+ MeasurementDefinition expected = new MeasurementDefinition("metric1", MeasurementCategory.AVAILABILITY,
+ MeasurementUnits.MILLISECONDS, DataType.TRAIT, NumericType.DYNAMIC, true, 30000, DisplayType.SUMMARY);
+ expected.setDescription("Metric 1");
+ expected.setDisplayName("metric1");
+ expected.setDisplayOrder(1);
+
+ AssertUtils.assertPropertiesMatch("Failed to persist properties for a trait metric definition", expected,
+ traitDef, asList("id", "resourceType"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Metrics.NewPlugin" }, dependsOnMethods = { "persistNewMetrics" })
+ public void persistNewNumericMeasurementDef() {
+ MeasurementDefinition measurementDef = loadMeasurementDef("metric2", "MetricServer1");
+
+ MeasurementDefinition expected = new MeasurementDefinition("metric2", MeasurementCategory.PERFORMANCE,
+ MeasurementUnits.MEGABYTES, NumericType.TRENDSUP, false, 30000, DisplayType.DETAIL);
+ expected.setRawNumericType(null);
+ expected.setDescription("Metric 2");
+ expected.setDisplayName("metric2");
+ expected.setDisplayOrder(2);
+
+ AssertUtils.assertPropertiesMatch("Failed to persist properties for numeric metric definition", expected,
+ measurementDef, asList("id", "resourceType"));
+
+ MeasurementDefinition perMinuteDef = loadMeasurementDef("metric2", "MetricServer1", "metric2 per Minute");
+
+ expected = new MeasurementDefinition(measurementDef);
+ expected.setDisplayName("metric2 per Minute");
+ expected.setDisplayOrder(3);
+ expected.setDefaultOn(true);
+ expected.setNumericType(NumericType.DYNAMIC);
+ expected.setRawNumericType(measurementDef.getNumericType());
+
+ AssertUtils.assertPropertiesMatch(
+ "Failed to create and persist per minute metric definition for numeric metric definition", expected,
+ perMinuteDef, asList("id", "resourceType"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Metrics.NewPlugin" }, dependsOnMethods = { "persistNewMetrics" })
+ public void persistNewCallTimeDef() {
+ MeasurementDefinition calltimeDef = loadMeasurementDef("metric3", "MetricServer1");
+
+ MeasurementDefinition expected = new MeasurementDefinition("metric3", MeasurementCategory.THROUGHPUT,
+ MeasurementUnits.MILLISECONDS, DataType.CALLTIME, true, 30000, DisplayType.DETAIL);
+ expected.setNumericType(NumericType.DYNAMIC);
+ expected.setDestinationType("myMethod");
+ expected.setDescription("Metric 3");
+ expected.setDisplayName("metric3");
+ expected.setDisplayOrder(4);
+
+ AssertUtils.assertPropertiesMatch("Failed to create calltime metric definition", expected, calltimeDef,
+ asList("id", "resourceType"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Metrics.NewPlugin" }, dependsOnMethods = { "persistNewMetrics" })
+ public void availabilityDefaultTest() {
+ MeasurementDefinition serverAvailDef = loadMeasurementDef("rhq.availability", "MetricServer1",
+ MeasurementDefinition.AVAILABILITY_DISPLAY_NAME);
+
+ MeasurementDefinition expected = new MeasurementDefinition("rhq.availability",
+ MeasurementCategory.AVAILABILITY, MeasurementUnits.NONE, DataType.AVAILABILITY, true,
+ MeasurementDefinition.AVAILABILITY_DEFAULT_PERIOD_SERVER, DisplayType.DETAIL);
+ expected.setNumericType(NumericType.DYNAMIC);
+ expected.setDisplayName(MeasurementDefinition.AVAILABILITY_DISPLAY_NAME);
+ expected.setDescription(MeasurementDefinition.AVAILABILITY_DESCRIPTION);
+
+ AssertUtils.assertPropertiesMatch("Failed to create avail metric definition", expected, serverAvailDef,
+ asList("id", "resourceType", "destinationType", "displayOrder"));
+
+ MeasurementDefinition serviceAvailDef = loadMeasurementDef("rhq.availability", "MetricService1",
+ MeasurementDefinition.AVAILABILITY_DISPLAY_NAME);
+
+ expected = new MeasurementDefinition("rhq.availability", MeasurementCategory.AVAILABILITY,
+ MeasurementUnits.NONE, DataType.AVAILABILITY, false, 120000, DisplayType.DETAIL);
+ expected.setNumericType(NumericType.DYNAMIC);
+ expected.setDisplayName(MeasurementDefinition.AVAILABILITY_DISPLAY_NAME);
+ expected.setDescription(MeasurementDefinition.AVAILABILITY_DESCRIPTION);
+
+ AssertUtils.assertPropertiesMatch("Failed to create avail metric definition", expected, serviceAvailDef,
+ asList("id", "resourceType", "destinationType", "displayOrder"));
+
+ serviceAvailDef = loadMeasurementDef("rhq.availability", "MetricService2",
+ MeasurementDefinition.AVAILABILITY_DISPLAY_NAME);
+
+ expected = new MeasurementDefinition("rhq.availability", MeasurementCategory.AVAILABILITY,
+ MeasurementUnits.NONE, DataType.AVAILABILITY, true,
+ MeasurementDefinition.AVAILABILITY_DEFAULT_PERIOD_SERVICE, DisplayType.DETAIL);
+ expected.setNumericType(NumericType.DYNAMIC);
+ expected.setDisplayName(MeasurementDefinition.AVAILABILITY_DISPLAY_NAME);
+ expected.setDescription(MeasurementDefinition.AVAILABILITY_DESCRIPTION);
+
+ AssertUtils.assertPropertiesMatch("Failed to create avail metric definition", expected, serviceAvailDef,
+ asList("id", "resourceType", "destinationType", "displayOrder"));
+
+ }
+
+ @Test(groups = { "plugin.metadata", "Metrics.UpgradePlugin" }, dependsOnGroups = { "Metrics.NewPlugin" })
+ public void upgradeMetricsPlugin() throws Exception {
+ createPlugin("metric-test-plugin", "2.0", "plugin_v2.xml");
+ }
+
+ @Test(groups = { "plugin.metadata", "Metrics.UpradePlugin" }, dependsOnMethods = { "upgradeMetricsPlugin" })
+ public void addNewMetricDef() throws Exception {
+ assertResourceTypeAssociationEquals("MetricServer2", "MeasurementMetadataManagerBeanTestPlugin",
+ "metricDefinitions", asList("metric1", "rhq.availability"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Metrics.UpradePlugin" }, dependsOnMethods = { "upgradeMetricsPlugin" })
+ public void changeTraitDefToMeasurementDef() {
+ MeasurementDefinition measurementDef = loadMeasurementDef("metric1", "MetricServer3");
+
+ MeasurementDefinition expected = new MeasurementDefinition("metric1", MeasurementCategory.PERFORMANCE,
+ MeasurementUnits.MILLISECONDS, DataType.MEASUREMENT, NumericType.TRENDSUP, false, 30000, DisplayType.DETAIL);
+ expected.setRawNumericType(null);
+ expected.setDefaultInterval(30000);
+ expected.setDescription("Metric One");
+ expected.setDisplayName("metric1");
+ expected.setDisplayOrder(1);
+
+ AssertUtils.assertPropertiesMatch("Failed to change trait definition to a measurement defintion", expected,
+ measurementDef, asList("id", "resourceType"));
+
+ MeasurementDefinition perMinuteDef = loadMeasurementDef("metric1", "MetricServer3", "metric1 per Minute");
+ expected.setDisplayName("metric1 per Minute");
+ expected.setDisplayOrder(2);
+ expected.setDefaultInterval(60000);
+ expected.setDefaultOn(false);
+ expected.setNumericType(NumericType.DYNAMIC);
+ expected.setRawNumericType(measurementDef.getNumericType());
+
+ AssertUtils.assertPropertiesMatch(
+ "Failed to create and persist per minute metric definition for updated metric definition", expected,
+ perMinuteDef, asList("id", "resourceType"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Metrics.UpradePlugin" }, dependsOnMethods = { "upgradeMetricsPlugin" })
+ public void deleteMetricDefThatHasBeenRemovedFromResourceType() throws Exception {
+ assertResourceTypeAssociationEquals("MetricServer4", "MeasurementMetadataManagerBeanTestPlugin",
+ "metricDefinitions", asList("rhq.availability"));
+ }
+
+ @Test(groups = { "plugin.metadata", "Metrics.UpradePlugin" }, dependsOnMethods = { "upgradeMetricsPlugin" })
+ public void deleteMetricDefsForResourceTypeThatIsRemoved() {
+ List metricDefs = getEntityManager()
+ .createQuery("from MeasurementDefinition m where m.name = :metric1Name or name = :metric2Name")
+ .setParameter("metric1Name", "MetricServer5.metric1").setParameter("metric2Name", "MetricServer5.metric3")
+ .getResultList();
+
+ assertEquals("Failed to delete metric definitions", 0, metricDefs.size());
+ }
+
+ @Test(groups = { "plugin.metadata", "Metrics.UpradePlugin" }, dependsOnMethods = { "upgradeMetricsPlugin" })
+ public void availabilityOverrideTest() {
+ MeasurementDefinition serverAvailDef = loadMeasurementDef("rhq.availability", "MetricServer1",
+ MeasurementDefinition.AVAILABILITY_DISPLAY_NAME);
+
+ MeasurementDefinition expected = new MeasurementDefinition("rhq.availability",
+ MeasurementCategory.AVAILABILITY, MeasurementUnits.NONE, DataType.AVAILABILITY, true, 120000,
+ DisplayType.DETAIL);
+ expected.setNumericType(NumericType.DYNAMIC);
+ expected.setDisplayName(MeasurementDefinition.AVAILABILITY_DISPLAY_NAME);
+ expected.setDescription(MeasurementDefinition.AVAILABILITY_DESCRIPTION);
+
+ AssertUtils.assertPropertiesMatch("Failed to create avail metric definition", expected, serverAvailDef,
+ asList("id", "resourceType", "destinationType", "displayOrder"));
+
+ MeasurementDefinition serviceAvailDef = loadMeasurementDef("rhq.availability", "MetricService1",
+ MeasurementDefinition.AVAILABILITY_DISPLAY_NAME);
+
+ // interval can not be changed by new plugin version if not at the category default
+ expected = new MeasurementDefinition("rhq.availability", MeasurementCategory.AVAILABILITY,
+ MeasurementUnits.NONE, DataType.AVAILABILITY, true, 120000, DisplayType.DETAIL);
+ expected.setNumericType(NumericType.DYNAMIC);
+ expected.setDisplayName(MeasurementDefinition.AVAILABILITY_DISPLAY_NAME);
+ expected.setDescription(MeasurementDefinition.AVAILABILITY_DESCRIPTION);
+
+ AssertUtils.assertPropertiesMatch("Failed to create avail metric definition", expected, serviceAvailDef,
+ asList("id", "resourceType", "destinationType", "displayOrder"));
+
+ serviceAvailDef = loadMeasurementDef("rhq.availability", "MetricService2",
+ MeasurementDefinition.AVAILABILITY_DISPLAY_NAME);
+
+ expected = new MeasurementDefinition("rhq.availability", MeasurementCategory.AVAILABILITY,
+ MeasurementUnits.NONE, DataType.AVAILABILITY, true, 480000, DisplayType.DETAIL);
+ expected.setNumericType(NumericType.DYNAMIC);
+ expected.setDisplayName(MeasurementDefinition.AVAILABILITY_DISPLAY_NAME);
+ expected.setDescription(MeasurementDefinition.AVAILABILITY_DESCRIPTION);
+
+ AssertUtils.assertPropertiesMatch("Failed to create avail metric definition", expected, serviceAvailDef,
+ asList("id", "resourceType", "destinationType", "displayOrder"));
+ }
+
+ MeasurementDefinition loadMeasurementDef(String name, String resourceType) {
+ return loadMeasurementDef(name, resourceType, name);
+ }
+
+ MeasurementDefinition loadMeasurementDef(String name, String resourceType, String displayName) {
+ return (MeasurementDefinition) getEntityManager()
+ .createQuery(
+ "from MeasurementDefinition m " + "where m.name = :name and " + "m.displayName = :displayName and "
+ + "m.resourceType.name = :resourceType").setParameter("name", name)
+ .setParameter("displayName", displayName).setParameter("resourceType", resourceType).getSingleResult();
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MetadataBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MetadataBeanTest.java
new file mode 100644
index 0000000..755f910
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MetadataBeanTest.java
@@ -0,0 +1,321 @@
+package org.rhq.enterprise.server.resource.metadata;
+
+import static org.rhq.core.clientapi.shared.PluginDescriptorUtil.loadPluginDescriptor;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.sql.Connection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+
+import org.apache.commons.beanutils.MethodUtils;
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.lang.WordUtils;
+import org.apache.maven.artifact.versioning.ComparableVersion;
+import org.dbunit.database.DatabaseConfig;
+import org.dbunit.database.DatabaseConnection;
+import org.dbunit.database.IDatabaseConnection;
+import org.dbunit.dataset.DataSetException;
+import org.dbunit.dataset.IDataSet;
+import org.dbunit.dataset.datatype.IDataTypeFactory;
+import org.dbunit.dataset.xml.FlatXmlDataSet;
+import org.dbunit.dataset.xml.FlatXmlProducer;
+import org.dbunit.operation.DatabaseOperation;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeGroups;
+import org.testng.annotations.BeforeMethod;
+import org.xml.sax.InputSource;
+
+import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.criteria.ResourceTypeCriteria;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.bundle.TestBundleServerPluginService;
+import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
+import org.rhq.enterprise.server.scheduler.jobs.PurgePluginsJob;
+import org.rhq.enterprise.server.scheduler.jobs.PurgeResourceTypesJob;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+public class MetadataBeanTest extends AbstractEJB3Test {
+
+ private List<Integer> pluginIds = new ArrayList<Integer>();
+
+
+ @BeforeGroups(groups = { "plugin.metadata" }, dependsOnGroups = { "integration.ejb3" })
+ public void beforeGroups() throws Exception {
+ setupDB();
+ }
+
+ /**
+ * Need to delete rows from RHQ_PLUGINS because subsequent tests in server/jar would otherwise fail. Some tests look
+ * at what plugins are in the database, and then look for corresponding plugin files on the file system. MetadataTest
+ * however removes the generated plugin files during each test run.
+ */
+ @AfterClass(alwaysRun = true, groups = { "plugin.metadata" })
+ void afterClass() throws Exception {
+ PluginManagerLocal pluginMgr = LookupUtil.getPluginManager();
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ pluginMgr.deletePlugins(overlord, pluginIds);
+ pluginMgr.markPluginsForPurge(overlord, pluginIds);
+ new PurgePluginsJob().executeJobCode(null);
+ new PurgeResourceTypesJob().executeJobCode(null);
+ }
+
+ @BeforeMethod(groups = { "plugin.metadata" }, dependsOnGroups = { "integration.ejb3" })
+ public void before() throws Exception {
+ if (!inContainer()) {
+ return;
+ }
+
+ TestBundleServerPluginService bundleService = new TestBundleServerPluginService();
+ prepareCustomServerPluginService(bundleService);
+ bundleService.startMasterPluginContainerWithoutSchedulingJobs();
+ prepareScheduler();
+ preparePluginScannerService();
+ }
+
+ /**
+ * Need to delete rows from RHQ_PLUGINS because subsequent tests in server/jar would otherwise fail. Some tests look
+ * at what plugins are in the database, and then look for corresponding plugin files on the file system. MetadataTest
+ * however removes the generated plugin files during each test run.
+ */
+ @AfterMethod(alwaysRun = true, groups = { "plugin.metadata" })
+ void after() throws Exception {
+ if (!inContainer()) {
+ return;
+ }
+
+ unprepareServerPluginService();
+ unprepareScheduler();
+ unpreparePluginScannerService();
+ }
+
+ protected void setupDB() throws Exception {
+ Connection connection = null;
+
+ try {
+ connection = getConnection();
+ DatabaseConnection dbunitConnection = new DatabaseConnection(connection);
+ setDbType(dbunitConnection);
+ // note - this info should already be in the db as part of dbsetup, but just in case
+ // perform the refresh. Do not DELETE this data set as it may be assumed in other tests.
+ DatabaseOperation.REFRESH.execute(dbunitConnection, getDataSet());
+ } finally {
+ if (connection != null) {
+ connection.close();
+ }
+ }
+ }
+
+ private void setDbType(IDatabaseConnection connection) throws Exception {
+ DatabaseConfig config = connection.getConfig();
+ String name = connection.getConnection().getMetaData().getDatabaseProductName().toLowerCase();
+ int major = connection.getConnection().getMetaData().getDatabaseMajorVersion();
+ IDataTypeFactory type = null;
+ if (name.contains("postgres")) {
+ type = new org.dbunit.ext.postgresql.PostgresqlDataTypeFactory();
+ } else if (name.contains("oracle")) {
+ if (major >= 10) {
+ type = new org.dbunit.ext.oracle.Oracle10DataTypeFactory();
+ } else {
+ type = new org.dbunit.ext.oracle.OracleDataTypeFactory();
+ }
+ }
+ if (type != null) {
+ config.setProperty("http://www.dbunit.org/properties/datatypeFactory", type);
+ }
+ }
+
+ private IDataSet getDataSet() throws DataSetException {
+ FlatXmlProducer xmlProducer = new FlatXmlProducer(new InputSource(getClass().getResourceAsStream(
+ getDataSetFile())));
+ xmlProducer.setColumnSensing(true);
+ return new FlatXmlDataSet(xmlProducer);
+ }
+
+ protected String getDataSetFile() {
+ return "MetadataTest.xml";
+ }
+
+ protected void createPlugin(String pluginFileName, String version, String descriptorFileName) throws Exception {
+ URL descriptorURL = getDescriptorURL(descriptorFileName);
+ PluginDescriptor pluginDescriptor = loadPluginDescriptor(descriptorURL);
+ String pluginFilePath = getCurrentWorkingDir() + "/" + pluginFileName + ".jar";
+ File pluginFile = new File(pluginFilePath);
+
+ Plugin plugin = new Plugin(pluginDescriptor.getName(), pluginFilePath);
+ plugin.setDisplayName(pluginDescriptor.getName());
+ plugin.setEnabled(true);
+ plugin.setDescription(pluginDescriptor.getDescription());
+ plugin.setAmpsVersion(getAmpsVersion(pluginDescriptor));
+ plugin.setVersion(pluginDescriptor.getVersion());
+ plugin.setMD5(MessageDigestGenerator.getDigestString(descriptorURL));
+
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+ PluginManagerLocal pluginMgr = LookupUtil.getPluginManager();
+
+ pluginMgr.registerPlugin(plugin, pluginDescriptor, null, true);
+
+ pluginIds.add(plugin.getId());
+ }
+
+ private URL getDescriptorURL(String descriptor) {
+ String dir = getClass().getSimpleName();
+ return getClass().getResource(dir + "/" + descriptor);
+ }
+
+ protected String getPluginWorkDir() throws Exception {
+ return getCurrentWorkingDir() + "/work";
+ }
+
+ protected String getCurrentWorkingDir() throws Exception {
+ return getClass().getResource(".").toURI().getPath();
+ }
+
+ String getAmpsVersion(PluginDescriptor pluginDescriptor) {
+ if (pluginDescriptor.getAmpsVersion() == null) {
+ return "2.0";
+ }
+
+ ComparableVersion version = new ComparableVersion(pluginDescriptor.getAmpsVersion());
+ ComparableVersion version2 = new ComparableVersion("2.0");
+
+ if (version.compareTo(version2) <= 0) {
+ return "2.0";
+ }
+
+ return pluginDescriptor.getAmpsVersion();
+ }
+
+ protected ResourceType assertResourceTypeAssociationEquals(String resourceTypeName, String plugin,
+ String propertyName, List<String> expected) throws Exception {
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+ ResourceTypeManagerLocal resourceTypeMgr = LookupUtil.getResourceTypeManager();
+
+ String fetch = "fetch" + WordUtils.capitalize(propertyName);
+ ResourceTypeCriteria criteria = new ResourceTypeCriteria();
+ criteria.addFilterName(resourceTypeName);
+ criteria.addFilterPluginName(plugin);
+ criteria.setStrict(true);
+ MethodUtils.invokeMethod(criteria, fetch, true);
+
+ List<ResourceType> resourceTypes = resourceTypeMgr.findResourceTypesByCriteria(subjectMgr.getOverlord(),
+ criteria);
+ ResourceType resourceType = resourceTypes.get(0);
+ Set<String> expectedSet = new HashSet<String>(expected);
+ List<String> missing = new ArrayList<String>();
+ List<String> unexpected = new ArrayList<String>();
+
+ for (String expectedProperty : expectedSet) {
+ if (!contains(resourceType, propertyName, expectedProperty)) {
+ missing.add(expectedProperty);
+ }
+ }
+
+ Collection<?> actualPropertyValues = (Collection<?>) PropertyUtils.getProperty(resourceType, propertyName);
+ for (Object actualPropertyValue : actualPropertyValues) {
+ String actualName = (String) PropertyUtils.getProperty(actualPropertyValue, "name");
+ if (!expectedSet.contains(actualName)) {
+ unexpected.add(actualName);
+ }
+ }
+
+ String errors = "";
+ if (!missing.isEmpty()) {
+ errors = "Failed to find the following " + propertyName + "(s) for type " + resourceTypeName + ": "
+ + missing;
+ }
+
+ if (unexpected.size() > 0) {
+ errors += "\nFound unexpected " + propertyName + "(s) for type " + resourceTypeName + ": " + unexpected;
+ }
+
+ assert errors.isEmpty() : errors;
+
+ return resourceType;
+ }
+
+ private boolean contains(ResourceType type, String propertyName, String expected) throws Exception {
+ Collection<?> actualPropertyValues = (Collection<?>) PropertyUtils.getProperty(type, propertyName);
+ for (Object actualPropertyValue : actualPropertyValues) {
+ String actualName = (String) PropertyUtils.getProperty(actualPropertyValue, "name");
+ if (actualName.equals(expected)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * This actually creates a .jar file on the file system but doesn't register it.
+ *
+ * @param jarName the name to be given to the new jar file
+ * @param descriptorXmlFilename where the descriptor XML can be found on the test classloader
+ * @return the location of the new jar file
+ * @throws Exception
+ */
+ protected File createPluginJarFile(String jarName, String descriptorXmlFilename) throws Exception {
+ FileOutputStream stream = null;
+ JarOutputStream out = null;
+ InputStream in = null;
+
+ try {
+ String pluginDirPath = getPluginWorkDir();
+ File pluginDir = new File(pluginDirPath);
+ pluginDir.mkdirs();
+ File jarFile = new File(pluginDir, jarName);
+ jarFile.delete(); // in case some older file is hanging around, get rid of it
+ stream = new FileOutputStream(jarFile);
+ out = new JarOutputStream(stream);
+
+ // Add archive entry for the descriptor
+ JarEntry jarAdd = new JarEntry("META-INF/rhq-plugin.xml");
+ jarAdd.setTime(System.currentTimeMillis());
+ out.putNextEntry(jarAdd);
+
+ // Write the descriptor - note that we assume the xml file is in the test classloader
+ URL descriptorURL = getDescriptorURL(descriptorXmlFilename);
+ in = descriptorURL.openStream();
+ StreamUtil.copy(in, out, false);
+
+ return jarFile;
+ } finally {
+ if (in != null) {
+ in.close();
+ }
+ if (out != null) {
+ out.close();
+ }
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ }
+
+ /**
+ * Tests can use this to let us know that a plugin has been deployed and needs to
+ * be cleaned up/removed at the end of the test.
+ *
+ * @param pluginName
+ */
+ protected void pluginDeployed(String pluginName) {
+ PluginManagerLocal pluginMgr = LookupUtil.getPluginManager();
+ Plugin plugin = pluginMgr.getPlugin(pluginName);
+ if (plugin != null) {
+ this.pluginIds.add(plugin.getId());
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest.java
new file mode 100644
index 0000000..b395120
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest.java
@@ -0,0 +1,152 @@
+package org.rhq.enterprise.server.resource.metadata;
+
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.criteria.ResourceTypeCriteria;
+import org.rhq.core.domain.operation.OperationDefinition;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * This test shows a plugin extended multiple times via the embedded extension model.
+ * There is one parent plugin and two child plugins. This test makes sure multiple
+ * plugins can extend and be updated; it won't test a full comprehensive set of
+ * metadata being upgraded. See {@link PluginExtensionMetadataTest} for a
+ * comprehensive test showing all the different kinds of metadata being updated.
+ *
+ * @author John Mazzitelli
+ */
+@Test(groups = { "plugin.multiple.extension.metadata", "plugin.metadata" })
+public class MultiplePluginExtensionMetadataTest extends MetadataBeanTest {
+
+ private static final String PLUGIN_NAME_PARENT = "MultiplePluginExtensionMetadataParentTestPlugin";
+ private static final String PLUGIN_NAME_CHILD1 = "PluginExtensionMetadataChild1TestPlugin";
+ private static final String PLUGIN_NAME_CHILD2 = "PluginExtensionMetadataChild2TestPlugin";
+ private static final String TYPE_NAME_PARENT = "ParentServerA";
+ private static final String TYPE_NAME_CHILD1 = "Child1ServerA";
+ private static final String TYPE_NAME_CHILD2 = "Child2ServerA";
+
+ // names of things from the first version of the plugin metadata
+ private static final String OP_NAME = "A-op";
+ private static final int OP_TIMEOUT = 123456;
+ private static final String OP_DESC = "a op";
+
+ // names of things from the second, updated version of the plugin metadata
+ // updated operations
+ private static final String NEW_OP_NAME = "A-op-NEW";
+ private static final int NEW_OP_TIMEOUT = 987654;
+ private static final String NEW_OP_DESC = "a new op";
+
+ private SubjectManagerLocal subjectMgr;
+ private ResourceTypeManagerLocal resourceTypeMgr;
+
+ public void testRegisterPlugins() throws Exception {
+ subjectMgr = LookupUtil.getSubjectManager();
+ resourceTypeMgr = LookupUtil.getResourceTypeManager();
+
+ registerParentPluginV1(); // create an initial type (called the parent)
+ registerChild1PluginV1(); // using plugin extension mechanism, create child #1 type that extends that parent type
+ registerChild2PluginV1(); // using plugin extension mechanism, create child #2 type that extends that parent type
+ registerParentPluginV2(); // update the parent type
+ checkChild1Plugin(); // check that the changes to the parent type propogated to the child #1
+ checkChild2Plugin(); // check that the changes to the parent type propogated to the child #2
+ }
+
+ private void registerParentPluginV1() throws Exception {
+ // register the plugin, load the new type and test to make sure its what we expect
+ createPlugin("parent-plugin.jar", "1.0", "parent_plugin_v1.xml");
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_PARENT, PLUGIN_NAME_PARENT);
+ assert resourceType.getName().equals(TYPE_NAME_PARENT);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_PARENT);
+ assertVersion1(resourceType);
+ }
+
+ private void registerChild1PluginV1() throws Exception {
+ // register the plugin, load the new type and test to make sure its what we expect
+ createPlugin("child1-plugin.jar", "1.0", "child1_plugin_v1.xml");
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_CHILD1, PLUGIN_NAME_CHILD1);
+ assert resourceType.getName().equals(TYPE_NAME_CHILD1);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_CHILD1);
+ assertVersion1(resourceType);
+
+ // in our child #1 plugin, our extended type is actually a child of child #1 plugin's root type
+ // here we want to make sure that hierarchy remains intact with our extended type - the parent
+ // of our extended type should be this child #1 root type
+ assert resourceType.getParentResourceTypes() != null;
+ assert resourceType.getParentResourceTypes().size() == 1;
+ assert resourceType.getParentResourceTypes().iterator().next().getName().equals("OuterServerA");
+ }
+
+ private void registerChild2PluginV1() throws Exception {
+ // register the plugin, load the new type and test to make sure its what we expect
+ createPlugin("child2-plugin.jar", "1.0", "child2_plugin_v1.xml");
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_CHILD2, PLUGIN_NAME_CHILD2);
+ assert resourceType.getName().equals(TYPE_NAME_CHILD2);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_CHILD2);
+ assertVersion1(resourceType);
+ }
+
+ private void registerParentPluginV2() throws Exception {
+ // register the plugin, load the new type and test to make sure its what we expect
+ createPlugin("parent-plugin.jar", "2.0", "parent_plugin_v2.xml");
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_PARENT, PLUGIN_NAME_PARENT);
+ assert resourceType.getName().equals(TYPE_NAME_PARENT);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_PARENT);
+ assertVersion2(resourceType);
+ }
+
+ private void checkChild1Plugin() throws Exception {
+ // load the child #1 type and test to make sure it has been updated to what we expect
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_CHILD1, PLUGIN_NAME_CHILD1);
+ assert resourceType.getName().equals(TYPE_NAME_CHILD1);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_CHILD1);
+ assertVersion2(resourceType);
+
+ // in our child #1 plugin, our extended type is actually a child of child #1 plugin's root type
+ // here we want to make sure that hierarchy remains intact with our extended type - the parent
+ // of our extended type should be this child #1 root type
+ assert resourceType.getParentResourceTypes() != null;
+ assert resourceType.getParentResourceTypes().size() == 1;
+ assert resourceType.getParentResourceTypes().iterator().next().getName().equals("OuterServerA");
+ }
+
+ private void checkChild2Plugin() throws Exception {
+ // load the child #2 type and test to make sure it has been updated to what we expect
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_CHILD2, PLUGIN_NAME_CHILD2);
+ assert resourceType.getName().equals(TYPE_NAME_CHILD2);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_CHILD2);
+ assertVersion2(resourceType);
+ }
+
+ private void assertVersion1(ResourceType resourceType) {
+ assert resourceType.getOperationDefinitions().size() == 1;
+ OperationDefinition op = resourceType.getOperationDefinitions().iterator().next();
+ assert op.getName().equals(OP_NAME);
+ assert op.getTimeout().intValue() == OP_TIMEOUT;
+ assert op.getDescription().equals(OP_DESC);
+ }
+
+ private void assertVersion2(ResourceType resourceType) {
+ assert resourceType.getOperationDefinitions().size() == 1;
+ OperationDefinition op = resourceType.getOperationDefinitions().iterator().next();
+ assert op.getName().equals(NEW_OP_NAME);
+ assert op.getTimeout().intValue() == NEW_OP_TIMEOUT;
+ assert op.getDescription().equals(NEW_OP_DESC);
+ }
+
+ private ResourceType loadResourceTypeFully(String typeName, String typePlugin) {
+ ResourceTypeCriteria c = new ResourceTypeCriteria();
+ c.addFilterName(typeName);
+ c.addFilterPluginName(typePlugin);
+ c.setStrict(true);
+ c.fetchParentResourceTypes(true);
+ c.fetchOperationDefinitions(true);
+ List<ResourceType> t = resourceTypeMgr.findResourceTypesByCriteria(subjectMgr.getOverlord(), c);
+ ResourceType resourceType = t.get(0);
+ return resourceType;
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest.java
new file mode 100644
index 0000000..e381168
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest.java
@@ -0,0 +1,169 @@
+package org.rhq.enterprise.server.resource.metadata;
+
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.criteria.ResourceTypeCriteria;
+import org.rhq.core.domain.operation.OperationDefinition;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * This test shows a plugin extended multiple times in the same plugin descriptor
+ * (one plugin descriptor, multiple resource types extending the same parent type).
+ *
+ * @author John Mazzitelli
+ */
+@Test(groups = { "plugin.multiple.extension.single.descriptor.metadata", "plugin.metadata" })
+public class MultiplePluginExtensionSinglePluginDescriptorMetadataTest extends MetadataBeanTest {
+
+ private static final String PLUGIN_NAME_PARENT = "MultiplePluginExtensionSinglePluginDescriptorMetadataParentTestPlugin";
+ private static final String PLUGIN_NAME_CHILD = "MultiplePluginExtensionSinglePluginDescriptorMetadataChildTestPlugin";
+ private static final String TYPE_NAME_PARENT = "ParentServerA";
+ private static final String TYPE_NAME_CHILD1 = "Child1ServerA";
+ private static final String TYPE_NAME_CHILD2 = "Child2ServerA";
+
+ // names of things from the first version of the plugin metadata
+ private static final String OP_NAME = "A-op";
+ private static final int OP_TIMEOUT = 123456;
+ private static final String OP_DESC = "a op";
+
+ // names of things from the second, updated version of the plugin metadata
+ // updated operations
+ private static final String NEW_OP_NAME = "A-op-NEW";
+ private static final int NEW_OP_TIMEOUT = 987654;
+ private static final String NEW_OP_DESC = "a new op";
+
+ private SubjectManagerLocal subjectMgr;
+ private ResourceTypeManagerLocal resourceTypeMgr;
+
+ public void testRegisterPlugins() throws Exception {
+ subjectMgr = LookupUtil.getSubjectManager();
+ resourceTypeMgr = LookupUtil.getResourceTypeManager();
+
+ registerParentPluginV1(); // create an initial type (called the parent)
+ registerChildPluginV1(); // using plugin extension mechanism, create child #1 and #2 types that extends that parent type
+ registerParentPluginV2(); // update the parent type
+ checkChildPlugin(); // check that the changes to the parent type propogated to the child #1 and #2
+ }
+
+ private void registerParentPluginV1() throws Exception {
+ // register the plugin, load the new type and test to make sure its what we expect
+ createPlugin("parent-plugin.jar", "1.0", "parent_plugin_v1.xml");
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_PARENT, PLUGIN_NAME_PARENT);
+ assert resourceType.getName().equals(TYPE_NAME_PARENT);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_PARENT);
+ assertVersion1(resourceType);
+ }
+
+ private void registerChildPluginV1() throws Exception {
+ createPlugin("child-plugin.jar", "1.0", "child_plugin_v1.xml");
+ afterRegisterChild1PluginV1();
+ afterRegisterChild2PluginV1();
+ }
+
+ private void afterRegisterChild1PluginV1() throws Exception {
+ // load the new type and test to make sure its what we expect
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_CHILD1, PLUGIN_NAME_CHILD);
+ assert resourceType.getName().equals(TYPE_NAME_CHILD1);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_CHILD);
+ assertVersion1(resourceType);
+
+ // in our child #1 plugin, our extended type is actually a child of an outer parent.
+ // here we want to make sure that hierarchy remains intact with our extended type - the parent
+ // of our extended type should be this child's parent as defined in the child descriptor.
+ assert resourceType.getParentResourceTypes() != null;
+ assert resourceType.getParentResourceTypes().size() == 1;
+ assert resourceType.getParentResourceTypes().iterator().next().getName().equals("OuterServerA");
+ }
+
+ private void afterRegisterChild2PluginV1() throws Exception {
+ // load the new type and test to make sure its what we expect
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_CHILD2, PLUGIN_NAME_CHILD);
+ assert resourceType.getName().equals(TYPE_NAME_CHILD2);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_CHILD);
+ assertVersion1(resourceType);
+
+ // in our child #2 plugin, our extended type is actually a child of an outer parent.
+ // here we want to make sure that hierarchy remains intact with our extended type - the parent
+ // of our extended type should be this child's parent as defined in the child descriptor.
+ assert resourceType.getParentResourceTypes() != null;
+ assert resourceType.getParentResourceTypes().size() == 1;
+ assert resourceType.getParentResourceTypes().iterator().next().getName().equals("OuterServerB");
+ }
+
+ private void registerParentPluginV2() throws Exception {
+ // register the plugin, load the new type and test to make sure its what we expect
+ createPlugin("parent-plugin.jar", "2.0", "parent_plugin_v2.xml");
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_PARENT, PLUGIN_NAME_PARENT);
+ assert resourceType.getName().equals(TYPE_NAME_PARENT);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_PARENT);
+ assertVersion2(resourceType);
+ }
+
+ private void checkChildPlugin() throws Exception {
+ checkChild1Plugin();
+ checkChild2Plugin();
+ }
+
+ private void checkChild1Plugin() throws Exception {
+ // load the child #1 type and test to make sure it has been updated to what we expect
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_CHILD1, PLUGIN_NAME_CHILD);
+ assert resourceType.getName().equals(TYPE_NAME_CHILD1);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_CHILD);
+ assertVersion2(resourceType);
+
+ // in our child #1 plugin, our extended type is actually a child of an outer parent.
+ // here we want to make sure that hierarchy remains intact with our extended type - the parent
+ // of our extended type should be this child's parent as defined in the child descriptor.
+ assert resourceType.getParentResourceTypes() != null;
+ assert resourceType.getParentResourceTypes().size() == 1;
+ assert resourceType.getParentResourceTypes().iterator().next().getName().equals("OuterServerA");
+ }
+
+ private void checkChild2Plugin() throws Exception {
+ // load the child #2 type and test to make sure it has been updated to what we expect
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_CHILD2, PLUGIN_NAME_CHILD);
+ assert resourceType.getName().equals(TYPE_NAME_CHILD2);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_CHILD);
+ assertVersion2(resourceType);
+
+ // in our child #2 plugin, our extended type is actually a child of an outer parent.
+ // here we want to make sure that hierarchy remains intact with our extended type - the parent
+ // of our extended type should be this child's parent as defined in the child descriptor.
+ assert resourceType.getParentResourceTypes() != null;
+ assert resourceType.getParentResourceTypes().size() == 1;
+ assert resourceType.getParentResourceTypes().iterator().next().getName().equals("OuterServerB");
+ }
+
+ private void assertVersion1(ResourceType resourceType) {
+ assert resourceType.getOperationDefinitions().size() == 1;
+ OperationDefinition op = resourceType.getOperationDefinitions().iterator().next();
+ assert op.getName().equals(OP_NAME);
+ assert op.getTimeout().intValue() == OP_TIMEOUT;
+ assert op.getDescription().equals(OP_DESC);
+ }
+
+ private void assertVersion2(ResourceType resourceType) {
+ assert resourceType.getOperationDefinitions().size() == 1;
+ OperationDefinition op = resourceType.getOperationDefinitions().iterator().next();
+ assert op.getName().equals(NEW_OP_NAME);
+ assert op.getTimeout().intValue() == NEW_OP_TIMEOUT;
+ assert op.getDescription().equals(NEW_OP_DESC);
+ }
+
+ private ResourceType loadResourceTypeFully(String typeName, String typePlugin) {
+ ResourceTypeCriteria c = new ResourceTypeCriteria();
+ c.addFilterName(typeName);
+ c.addFilterPluginName(typePlugin);
+ c.setStrict(true);
+ c.fetchParentResourceTypes(true);
+ c.fetchOperationDefinitions(true);
+ List<ResourceType> t = resourceTypeMgr.findResourceTypesByCriteria(subjectMgr.getOverlord(), c);
+ ResourceType resourceType = t.get(0);
+ return resourceType;
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/OperationMetadataManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/OperationMetadataManagerBeanTest.java
new file mode 100644
index 0000000..59f5d44
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/OperationMetadataManagerBeanTest.java
@@ -0,0 +1,134 @@
+package org.rhq.enterprise.server.resource.metadata;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.EMPTY_LIST;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.operation.OperationDefinition;
+import org.rhq.core.domain.resource.ResourceType;
+
+public class OperationMetadataManagerBeanTest extends MetadataBeanTest {
+
+ @Test(groups = {"plugin.metadata", "Operations.NewPlugin"})
+ public void registerOperationsPlugin() throws Exception {
+ createPlugin("operation-test-plugin", "1.0", "plugin_v1.xml");
+ }
+
+ @Test(groups = {"plugin.metadata", "Operations.NewPlugin"}, dependsOnMethods = {"registerOperationsPlugin"})
+ public void createTypeWithOperationDefWithNoParamsAndNoResults() throws Exception {
+ assertResourceTypeAssociationEquals(
+ "OperationServer1",
+ "OperationMetadataManagerBeanTestPlugin",
+ "operationDefinitions",
+ asList("OperationServer1.Operation1")
+ );
+ }
+
+ @Test(groups = {"plugin.metadata", "Operations.NewPlugin"}, dependsOnMethods = {"registerOperationsPlugin"})
+ public void createTypeWithOperationDefWithParams() {
+ ResourceType resourceType = loadResourceTypeWithOperationDefs("OperationServer11",
+ "OperationMetadataManagerBeanTestPlugin");
+ List<OperationDefinition> operationDefs =
+ new ArrayList<OperationDefinition>(resourceType.getOperationDefinitions());
+
+ assertEquals("Expected to find an operation definition", 1, operationDefs.size());
+
+ ConfigurationDefinition params = operationDefs.get(0).getParametersConfigurationDefinition();
+
+ assertNotNull("Expected to find parameters for operation definition", params);
+ assertEquals("Expected to find 2 parameters", 2, params.getPropertyDefinitions().size());
+ assertNotNull("Expected to find parameter named <param1>", params.get("param1"));
+ assertNotNull("Expected to find parameter named <param2>", params.get("param2"));
+ }
+
+ @Test(groups = {"plugin.metadata", "Operations.UpgradePlugin"}, dependsOnGroups = {"Operations.NewPlugin"})
+ public void upgradeOperationsPlugin() throws Exception {
+ createPlugin("operation-test-plugin", "2.0", "plugin_v2.xml");
+ }
+
+ @Test(groups = {"plugin.metadata", "Operations.UpgradePlugin"}, dependsOnMethods = {"upgradeOperationsPlugin"})
+ public void addOperationToTypeThatPreviouslyHadNoOperations() throws Exception {
+ assertResourceTypeAssociationEquals(
+ "OperationServer2",
+ "OperationMetadataManagerBeanTestPlugin",
+ "operationDefinitions",
+ asList("OperationServer2.Operation1")
+ );
+ }
+
+ @Test(groups = {"plugin.metadata", "Operations.UpgradePlugin"}, dependsOnMethods = {"upgradeOperationsPlugin"})
+ public void removeOperationDefFromTypeThatPreviouslyDefinedOperationDef() throws Exception {
+ assertResourceTypeAssociationEquals(
+ "OperationServer21",
+ "OperationMetadataManagerBeanTestPlugin",
+ "operationDefinitions",
+ EMPTY_LIST
+ );
+ }
+
+ @Test(groups = {"plugin.metadata", "Operations.UpgradePlugin"}, dependsOnMethods = {"upgradeOperationsPlugin"})
+ public void removeParamsFromUpgradedOperationDef() {
+ OperationDefinition operationDef = loadOperationDefinition("OperationServer22.Operation1", "OperationServer22",
+ "OperationMetadataManagerBeanTestPlugin");
+
+ assertNull("Operation parameters should have been removed", operationDef.getParametersConfigurationDefinition());
+ }
+
+ @Test(groups = {"plugin.metadata", "Operations.UpgradePlugin"}, dependsOnMethods = {"upgradeOperationsPlugin"})
+ public void addResultsToUpgradedOperationDef() {
+ OperationDefinition operationDef = loadOperationDefinition("OperationServer23.Operation1", "OperationServer23",
+ "OperationMetadataManagerBeanTestPlugin");
+ ConfigurationDefinition resultsDef = operationDef.getResultsConfigurationDefinition();
+
+ assertNotNull("Results definition should have been added", resultsDef);
+ assertEquals("Expected results to contain one property", 1, resultsDef.getPropertyDefinitions().size());
+ assertNotNull("Expected results to contain property named <exitCode>", resultsDef.get("exitCode"));
+ }
+
+ @Test(groups = {"plugin.metadata", "Operations.UpgradePlugin"}, dependsOnMethods = {"upgradeOperationsPlugin"})
+ public void addParamsToUpgradedOperationDef() {
+ OperationDefinition operationDef = loadOperationDefinition("OperationServer24.Operation1", "OperationServer24",
+ "OperationMetadataManagerBeanTestPlugin");
+ ConfigurationDefinition paramsDef = operationDef.getParametersConfigurationDefinition();
+
+ assertNotNull("Operation parameters definition should have been added.", paramsDef);
+ assertEquals("Expected to find one parameter definition.", 1, paramsDef.getPropertyDefinitions().size());
+ assertNotNull("Expected parameters to contain property named <param1>",
+ paramsDef.getPropertyDefinitions().get("param1"));
+ }
+
+ @Test(groups = {"plugin.metadata", "Operations.UpgradePlugin"}, dependsOnMethods = {"upgradeOperationsPlugin"})
+ public void removeResultsInUpgradedOperationDef() {
+ OperationDefinition operationDef = loadOperationDefinition("OperationServer24.Operation1", "OperationServer24",
+ "OperationMetadataManagerBeanTestPlugin");
+ ConfigurationDefinition resultsDef = operationDef.getResultsConfigurationDefinition();
+
+ assertNull("Results definition should have been removed", resultsDef);
+ }
+
+ ResourceType loadResourceTypeWithOperationDefs(String resourceType, String plugin) {
+ return (ResourceType) getEntityManager().createQuery(
+ "from ResourceType t left join fetch t.operationDefinitions tod "
+ +
+ "where t.name = :resourceType and t.plugin = :plugin")
+ .setParameter("resourceType", resourceType)
+ .setParameter("plugin", plugin)
+ .getSingleResult();
+ }
+
+ OperationDefinition loadOperationDefinition(String opName, String resourceType, String plugin) {
+ return (OperationDefinition) getEntityManager().createQuery(
+ "from OperationDefinition o " +
+ "where o.name = :operationName and o.resourceType.name = :resourceType and o.resourceType.plugin = :plugin")
+ .setParameter("operationName", opName)
+ .setParameter("resourceType", resourceType)
+ .setParameter("plugin", plugin)
+ .getSingleResult();
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest.java
new file mode 100644
index 0000000..fedd45e
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest.java
@@ -0,0 +1,407 @@
+package org.rhq.enterprise.server.resource.metadata;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration;
+import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory;
+import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory.Context;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyGroupDefinition;
+import org.rhq.core.domain.criteria.ResourceTypeCriteria;
+import org.rhq.core.domain.drift.DriftConfigurationDefinition.BaseDirValueContext;
+import org.rhq.core.domain.drift.DriftDefinition;
+import org.rhq.core.domain.drift.DriftDefinition.BaseDirectory;
+import org.rhq.core.domain.drift.DriftDefinitionTemplate;
+import org.rhq.core.domain.event.EventDefinition;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.operation.OperationDefinition;
+import org.rhq.core.domain.resource.ProcessScan;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+@Test(groups = { "plugin.extension.metadata", "plugin.metadata" })
+public class PluginExtensionMetadataTest extends MetadataBeanTest {
+
+ private static final String PLUGIN_NAME_PARENT = "PluginExtensionMetadataParentTestPlugin";
+ private static final String PLUGIN_NAME_CHILD = "PluginExtensionMetadataChildTestPlugin";
+ private static final String TYPE_NAME_PARENT = "ParentServerA";
+ private static final String TYPE_NAME_CHILD = "ChildServerA";
+
+ // names of things from the first version of the plugin metadata
+ private static final String SUBCAT = "A-subcat";
+ private static final String SUBCAT_DISPLAYNAME = "a subcat";
+ private static final String PC_GROUP = "A-pc-group";
+ private static final boolean PC_GROUP_HIDDEN = true;
+ private static final String PC_PROP = "A-pc-prop";
+ private static final boolean PC_PROP_REQUIRED = false;
+ private static final String PROCESS_SCAN_NAME = "A-process-scan";
+ private static final String PROCESS_SCAN_QUERY = "process|basename|match=A.exe";
+ private static final String OP_NAME = "A-op";
+ private static final int OP_TIMEOUT = 123456;
+ private static final String OP_DESC = "a op";
+ private static final String METRIC_PROP = "A-metric";
+ private static final long METRIC_DEFAULT_INTERVAL = 123456L;
+ private static final String EVENT_NAME = "A-event";
+ private static final String EVENT_DESC = "a event";
+ private static final String RC_PROP = "A-rc-prop";
+ private static final boolean RC_PROP_REQUIRED = false;
+ private static final String DRIFT_DEF_NAME = "A-drift-def";
+ private static final BaseDirValueContext DRIFT_DEF_BASEDIR_CONTEXT = BaseDirValueContext.pluginConfiguration;
+ private static final String DRIFT_DEF_BASEDIR_VALUE = PC_PROP;
+ private static final String BUNDLE_TARGET_NAME = "A-bundle-basedir";
+ private static final Context BUNDLE_BASEDIR_CONTEXT = Context.resourceConfiguration;
+ private static final String BUNDLE_BASEDIR_VALUE = RC_PROP;
+
+ // names of things from the second, updated version of the plugin metadata
+ // updated plugin config
+ private static final String CHANGED_PC_GROUP = PC_GROUP; // we only change its members, not the name itself
+ private static final boolean CHANGED_PC_GROUP_HIDDEN = false;
+ private static final String CHANGED_PC_PROP = "A-pc-prop-CHANGED";
+ private static final boolean CHANGED_PC_PROP_REQUIRED = true;
+ private static final String NEW_PC_GROUP = "A-pc-group-NEW";
+ private static final boolean NEW_PC_GROUP_HIDDEN = true;
+ private static final String NEW_PC_PROP = "A-pc-prop-NEW";
+ private static final boolean NEW_PC_PROP_REQUIRED = false;
+ // updated process scans
+ private static final String CHANGED_PROCESS_SCAN_NAME = "A-process-scan";
+ private static final String CHANGED_PROCESS_SCAN_QUERY = "process|basename|match=CHANGED.exe";
+ private static final String NEW_PROCESS_SCAN_NAME = "A-process-scan-NEW";
+ private static final String NEW_PROCESS_SCAN_QUERY = "process|basename|match=NEW.exe";
+ // updated operations
+ private static final String CHANGED_OP_NAME = OP_NAME; // we don't actually change its name in our test
+ private static final int CHANGED_OP_TIMEOUT = 987654;
+ private static final String CHANGED_OP_DESC = "a changed op";
+ private static final String NEW_OP_NAME = "A-op-NEW";
+ private static final int NEW_OP_TIMEOUT = 111111;
+ private static final String NEW_OP_DESC = "a new op";
+ // updated metrics
+ private static final String CHANGED_METRIC_PROP = METRIC_PROP; // we don't actually change its name in our test
+ private static final String NEW_METRIC_PROP = "A-metric-NEW";
+ private static final long NEW_METRIC_DEFAULT_INTERVAL = 98765L;
+ // updated events
+ private static final String CHANGED_EVENT_NAME = "A-event-CHANGED";
+ private static final String CHANGED_EVENT_DESC = "a changed event";
+ private static final String NEW_EVENT_NAME = "A-event-NEW";
+ private static final String NEW_EVENT_DESC = "a new event";
+ // updated resource config
+ private static final String CHANGED_RC_PROP = "A-rc-prop-CHANGED";
+ private static final boolean CHANGED_RC_PROP_REQUIRED = true;
+ private static final String NEW_RC_PROP = "A-rc-prop-NEW";
+ private static final boolean NEW_RC_PROP_REQUIRED = false;
+ // updated drift
+ private static final String CHANGED_DRIFT_DEF_NAME = "A-drift-def-CHANGED";
+ private static final BaseDirValueContext CHANGED_DRIFT_DEF_BASEDIR_CONTEXT = BaseDirValueContext.pluginConfiguration;
+ private static final String CHANGED_DRIFT_DEF_BASEDIR_VALUE = PC_PROP;
+ private static final String NEW_DRIFT_DEF_NAME = "A-drift-def-NEW";
+ private static final BaseDirValueContext NEW_DRIFT_DEF_BASEDIR_CONTEXT = BaseDirValueContext.resourceConfiguration;
+ private static final String NEW_DRIFT_DEF_BASEDIR_VALUE = RC_PROP;
+ // updated bundle
+ private static final String CHANGED_BUNDLE_TARGET_NAME = "A-bundle-basedir-CHANGED";
+ private static final Context CHANGED_BUNDLE_BASEDIR_CONTEXT = Context.resourceConfiguration;
+ private static final String CHANGED_BUNDLE_BASEDIR_VALUE = RC_PROP;
+ private static final String NEW_BUNDLE_TARGET_NAME = "A-bundle-basedir-NEW";
+ private static final Context NEW_BUNDLE_BASEDIR_CONTEXT = Context.pluginConfiguration;
+ private static final String NEW_BUNDLE_BASEDIR_VALUE = PC_PROP;
+
+ private SubjectManagerLocal subjectMgr;
+ private ResourceTypeManagerLocal resourceTypeMgr;
+
+ public void testRegisterPlugins() throws Exception {
+ subjectMgr = LookupUtil.getSubjectManager();
+ resourceTypeMgr = LookupUtil.getResourceTypeManager();
+
+ registerParentPluginV1(); // create an initial type (called the parent)
+ registerChildPluginV1(); // using plugin extension mechanism, create a child type that extends that parent type
+ registerParentPluginV2(); // update the parent type
+ checkChildPlugin(); // check that the changes to the parent type propogated to the child
+ }
+
+ private void registerParentPluginV1() throws Exception {
+ // register the plugin, load the new type and test to make sure its what we expect
+ createPlugin("parent-plugin.jar", "1.0", "parent_plugin_v1.xml");
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_PARENT, PLUGIN_NAME_PARENT);
+ assert resourceType.getName().equals(TYPE_NAME_PARENT);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_PARENT);
+ assertVersion1(resourceType);
+ }
+
+ private void registerChildPluginV1() throws Exception {
+ // register the plugin, load the new type and test to make sure its what we expect
+ createPlugin("child-plugin.jar", "1.0", "child_plugin_v1.xml");
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_CHILD, PLUGIN_NAME_CHILD);
+ assert resourceType.getName().equals(TYPE_NAME_CHILD);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_CHILD);
+ assertVersion1(resourceType);
+ }
+
+ private void registerParentPluginV2() throws Exception {
+ // register the plugin, load the new type and test to make sure its what we expect
+ createPlugin("parent-plugin.jar", "2.0", "parent_plugin_v2.xml");
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_PARENT, PLUGIN_NAME_PARENT);
+ assert resourceType.getName().equals(TYPE_NAME_PARENT);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_PARENT);
+ assertVersion2(resourceType);
+ }
+
+ private void checkChildPlugin() throws Exception {
+ // load the child type and test to make sure it has been updated to what we expect
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_CHILD, PLUGIN_NAME_CHILD);
+ assert resourceType.getName().equals(TYPE_NAME_CHILD);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_CHILD);
+ assertVersion2(resourceType);
+ }
+
+ private void assertVersion1(ResourceType resourceType) {
+ PropertyGroupDefinition group;
+ PropertyDefinition prop;
+ ProcessScan processScan;
+ OperationDefinition op;
+ MeasurementDefinition metric;
+ EventDefinition event;
+ DriftDefinitionTemplate drift;
+ BaseDirectory driftBasedir;
+ ResourceTypeBundleConfiguration bundle;
+ BundleDestinationBaseDirectory bundleBasedir;
+
+ assert resourceType.getChildSubCategories().size() == 1;
+ assert resourceType.getChildSubCategories().get(0).getName().equals(SUBCAT);
+ assert resourceType.getChildSubCategories().get(0).getDisplayName().equals(SUBCAT_DISPLAYNAME);
+
+ assert resourceType.getPluginConfigurationDefinition().getGroupDefinitions().size() == 1;
+ group = resourceType.getPluginConfigurationDefinition().getGroupDefinitions().get(0);
+ assert group.getName().equals(PC_GROUP);
+ assert group.isDefaultHidden() == PC_GROUP_HIDDEN;
+ prop = resourceType.getPluginConfigurationDefinition().get(PC_PROP);
+ assert prop != null;
+ assert prop.getName().equals(PC_PROP);
+ assert prop.isRequired() == PC_PROP_REQUIRED;
+ assert prop.getPropertyGroupDefinition().getName().equals(PC_GROUP);
+
+ assert resourceType.getProcessScans().size() == 1;
+ processScan = resourceType.getProcessScans().iterator().next();
+ assert processScan.getName().equals(PROCESS_SCAN_NAME);
+ assert processScan.getQuery().equals(PROCESS_SCAN_QUERY);
+
+ assert resourceType.getOperationDefinitions().size() == 1;
+ op = resourceType.getOperationDefinitions().iterator().next();
+ assert op.getName().equals(OP_NAME);
+ assert op.getTimeout().intValue() == OP_TIMEOUT;
+ assert op.getDescription().equals(OP_DESC);
+
+ assert resourceType.getMetricDefinitions().size() == 2; // include built-in Availability metric
+ metric = resourceType.getMetricDefinitions().iterator().next();
+ assert metric.getName().equals(METRIC_PROP);
+ assert metric.getDefaultInterval() == METRIC_DEFAULT_INTERVAL;
+
+ assert resourceType.getEventDefinitions().size() == 1;
+ event = resourceType.getEventDefinitions().iterator().next();
+ assert event.getName().equals(EVENT_NAME);
+ assert event.getDescription().equals(EVENT_DESC);
+
+ assert resourceType.getResourceConfigurationDefinition().getGroupDefinitions().size() == 0;
+ prop = resourceType.getResourceConfigurationDefinition().get(RC_PROP);
+ assert prop != null;
+ assert prop.getName().equals(RC_PROP);
+ assert prop.isRequired() == RC_PROP_REQUIRED;
+
+ assert resourceType.getDriftDefinitionTemplates().size() == 1;
+ drift = resourceType.getDriftDefinitionTemplates().iterator().next();
+ assert drift.getTemplateDefinition().getName().equals(DRIFT_DEF_NAME);
+ driftBasedir = drift.getTemplateDefinition().getBasedir();
+ assert driftBasedir.getValueContext().equals(DRIFT_DEF_BASEDIR_CONTEXT);
+ assert driftBasedir.getValueName().equals(DRIFT_DEF_BASEDIR_VALUE);
+
+ bundle = resourceType.getResourceTypeBundleConfiguration();
+ assert bundle.getBundleDestinationBaseDirectories().size() == 1;
+ bundleBasedir = bundle.getBundleDestinationBaseDirectories().iterator().next();
+ assert bundleBasedir.getName().equals(BUNDLE_TARGET_NAME);
+ assert bundleBasedir.getValueContext().equals(BUNDLE_BASEDIR_CONTEXT);
+ assert bundleBasedir.getValueName().equals(BUNDLE_BASEDIR_VALUE);
+ }
+
+ private void assertVersion2(ResourceType resourceType) {
+ PropertyDefinition prop;
+ Set<String> seen = new HashSet<String>(2); // we use to this remember names of the things that we've seen
+
+ assert resourceType.getChildSubCategories().size() == 1;
+ assert resourceType.getChildSubCategories().get(0).getName().equals(SUBCAT);
+ assert resourceType.getChildSubCategories().get(0).getDisplayName().equals(SUBCAT_DISPLAYNAME);
+
+ seen.clear();
+ ConfigurationDefinition pcDef = resourceType.getPluginConfigurationDefinition();
+ assert pcDef.getGroupDefinitions().size() == 2;
+ for (PropertyGroupDefinition group : pcDef.getGroupDefinitions()) {
+ seen.add(group.getName());
+ if (group.getName().equals(CHANGED_PC_GROUP)) {
+ assert group.isDefaultHidden() == CHANGED_PC_GROUP_HIDDEN;
+ } else if (group.getName().equals(NEW_PC_GROUP)) {
+ assert group.isDefaultHidden() == NEW_PC_GROUP_HIDDEN;
+ } else {
+ assert false : "Unexpected group [" + group.getName() + "]:" + group;
+ }
+ }
+ if (seen.size() != 2) {
+ assert false : "did not see what we expected to see: " + seen;
+ }
+
+ prop = pcDef.get(CHANGED_PC_PROP);
+ assert prop != null;
+ assert prop.getName().equals(CHANGED_PC_PROP);
+ assert prop.isRequired() == CHANGED_PC_PROP_REQUIRED;
+ assert prop.getPropertyGroupDefinition().getName().equals(CHANGED_PC_GROUP);
+ prop = pcDef.get(NEW_PC_PROP);
+ assert prop != null;
+ assert prop.getName().equals(NEW_PC_PROP);
+ assert prop.isRequired() == NEW_PC_PROP_REQUIRED;
+ assert prop.getPropertyGroupDefinition().getName().equals(NEW_PC_GROUP);
+
+ seen.clear();
+ assert resourceType.getProcessScans().size() == 2;
+ for (ProcessScan processScan : resourceType.getProcessScans()) {
+ seen.add(processScan.getName());
+ if (processScan.getName().equals(CHANGED_PROCESS_SCAN_NAME)) {
+ assert processScan.getQuery().equals(CHANGED_PROCESS_SCAN_QUERY);
+ } else if (processScan.getName().equals(NEW_PROCESS_SCAN_NAME)) {
+ assert processScan.getQuery().equals(NEW_PROCESS_SCAN_QUERY);
+ } else {
+ assert false : "Unexpected process scan[" + processScan.getName() + "]:" + processScan;
+ }
+ }
+ if (seen.size() != 2) {
+ assert false : "did not see what we expected to see: " + seen;
+ }
+
+ seen.clear();
+ assert resourceType.getOperationDefinitions().size() == 2;
+ for (OperationDefinition op : resourceType.getOperationDefinitions()) {
+ seen.add(op.getName());
+ if (op.getName().equals(CHANGED_OP_NAME)) {
+ assert op.getTimeout().intValue() == CHANGED_OP_TIMEOUT;
+ assert op.getDescription().equals(CHANGED_OP_DESC);
+ } else if (op.getName().equals(NEW_OP_NAME)) {
+ assert op.getTimeout().intValue() == NEW_OP_TIMEOUT;
+ assert op.getDescription().equals(NEW_OP_DESC);
+ } else {
+ assert false : "Unexpected operation [" + op.getName() + "]:" + op;
+ }
+ }
+ if (seen.size() != 2) {
+ assert false : "did not see what we expected to see: " + seen;
+ }
+
+ seen.clear();
+ assert resourceType.getMetricDefinitions().size() == 3; // include built-in Availability metric
+ for (MeasurementDefinition metric : resourceType.getMetricDefinitions()) {
+ if (metric.getName().equals(MeasurementDefinition.AVAILABILITY_NAME)) {
+ // expected, ignore
+ continue;
+ }
+
+ seen.add(metric.getName());
+ if (metric.getName().equals(CHANGED_METRIC_PROP)) {
+ // even though our _v2 plugin set this to something different, our upgrade doesn't change it because
+ // we don't want to overwrite changes a user possibly made to the defaut interval (aka metric template)
+ assert metric.getDefaultInterval() == METRIC_DEFAULT_INTERVAL;
+ } else if (metric.getName().equals(NEW_METRIC_PROP)) {
+ assert metric.getDefaultInterval() == NEW_METRIC_DEFAULT_INTERVAL;
+ } else {
+ assert false : "Unexpected metric [" + metric.getName() + "]:" + metric;
+ }
+ }
+ if (seen.size() != 2) {
+ assert false : "did not see what we expected to see: " + seen;
+ }
+
+ seen.clear();
+ assert resourceType.getEventDefinitions().size() == 2;
+ for (EventDefinition event : resourceType.getEventDefinitions()) {
+ seen.add(event.getName());
+ if (event.getName().equals(CHANGED_EVENT_NAME)) {
+ assert event.getDescription().equals(CHANGED_EVENT_DESC);
+ } else if (event.getName().equals(NEW_EVENT_NAME)) {
+ assert event.getDescription().equals(NEW_EVENT_DESC);
+ } else {
+ assert false : "Unexpected event [" + event.getName() + "]:" + event;
+ }
+ }
+ if (seen.size() != 2) {
+ assert false : "did not see what we expected to see: " + seen;
+ }
+
+ assert resourceType.getResourceConfigurationDefinition().getGroupDefinitions().size() == 0;
+ prop = resourceType.getResourceConfigurationDefinition().get(CHANGED_RC_PROP);
+ assert prop != null;
+ assert prop.getName().equals(CHANGED_RC_PROP);
+ assert prop.isRequired() == CHANGED_RC_PROP_REQUIRED;
+ prop = resourceType.getResourceConfigurationDefinition().get(NEW_RC_PROP);
+ assert prop != null;
+ assert prop.getName().equals(NEW_RC_PROP);
+ assert prop.isRequired() == NEW_RC_PROP_REQUIRED;
+
+ seen.clear();
+ assert resourceType.getDriftDefinitionTemplates().size() == 2;
+ for (DriftDefinitionTemplate drift : resourceType.getDriftDefinitionTemplates()) {
+ DriftDefinition def = drift.getTemplateDefinition();
+ seen.add(def.getName());
+ if (def.getName().equals(CHANGED_DRIFT_DEF_NAME)) {
+ BaseDirectory driftBasedir = def.getBasedir();
+ assert driftBasedir.getValueContext().equals(CHANGED_DRIFT_DEF_BASEDIR_CONTEXT);
+ assert driftBasedir.getValueName().equals(CHANGED_DRIFT_DEF_BASEDIR_VALUE);
+ } else if (def.getName().equals(NEW_DRIFT_DEF_NAME)) {
+ BaseDirectory driftBasedir = def.getBasedir();
+ assert driftBasedir.getValueContext().equals(NEW_DRIFT_DEF_BASEDIR_CONTEXT);
+ assert driftBasedir.getValueName().equals(NEW_DRIFT_DEF_BASEDIR_VALUE);
+ } else {
+ assert false : "Unexpected drift def [" + def.getName() + "]:" + def;
+ }
+ }
+ if (seen.size() != 2) {
+ assert false : "did not see what we expected to see: " + seen;
+ }
+
+ seen.clear();
+ ResourceTypeBundleConfiguration bundle = resourceType.getResourceTypeBundleConfiguration();
+ assert bundle.getBundleDestinationBaseDirectories().size() == 2;
+ for (BundleDestinationBaseDirectory bundleBasedir : bundle.getBundleDestinationBaseDirectories()) {
+ seen.add(bundleBasedir.getName());
+ if (bundleBasedir.getName().equals(CHANGED_BUNDLE_TARGET_NAME)) {
+ assert bundleBasedir.getValueContext().equals(CHANGED_BUNDLE_BASEDIR_CONTEXT);
+ assert bundleBasedir.getValueName().equals(CHANGED_BUNDLE_BASEDIR_VALUE);
+ } else if (bundleBasedir.getName().equals(NEW_BUNDLE_TARGET_NAME)) {
+ assert bundleBasedir.getValueContext().equals(NEW_BUNDLE_BASEDIR_CONTEXT);
+ assert bundleBasedir.getValueName().equals(NEW_BUNDLE_BASEDIR_VALUE);
+ } else {
+ assert false : "Unexpected bundle basedir [" + bundleBasedir.getName() + "]:" + bundleBasedir;
+ }
+ }
+ if (seen.size() != 2) {
+ assert false : "did not see what we expected to see: " + seen;
+ }
+ }
+
+ private ResourceType loadResourceTypeFully(String typeName, String typePlugin) {
+ ResourceTypeCriteria c = new ResourceTypeCriteria();
+ c.addFilterName(typeName);
+ c.addFilterPluginName(typePlugin);
+ c.setStrict(true);
+ c.fetchSubCategories(true);
+ c.fetchPluginConfigurationDefinition(true);
+ c.fetchProcessScans(true);
+ c.fetchOperationDefinitions(true);
+ c.fetchMetricDefinitions(true);
+ c.fetchEventDefinitions(true);
+ c.fetchResourceConfigurationDefinition(true);
+ c.fetchDriftDefinitionTemplates(true);
+ c.fetchBundleConfiguration(true);
+ List<ResourceType> t = resourceTypeMgr.findResourceTypesByCriteria(subjectMgr.getOverlord(), c);
+ ResourceType resourceType = t.get(0);
+ return resourceType;
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest.java
new file mode 100644
index 0000000..b24ea04
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest.java
@@ -0,0 +1,201 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.resource.metadata;
+
+import static java.util.Arrays.asList;
+
+import java.util.List;
+
+import javax.ejb.EJBException;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginStatusType;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.core.plugin.PluginDeploymentScanner;
+import org.rhq.enterprise.server.scheduler.jobs.PurgePluginsJob;
+import org.rhq.enterprise.server.scheduler.jobs.PurgeResourceTypesJob;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Unit tests for {@link PluginManagerBean}.
+ */
+@Test(groups = { "plugin.metadata", "PluginManagerBean" }, priority = 100000)
+public class PluginManagerBeanTest extends MetadataBeanTest {
+
+ private SubjectManagerLocal subjectMgr;
+ private PluginManagerLocal pluginMgr;
+
+ // Our test class wants to deploy plugins that other test methods use.
+ // We need to keep intact our plugin scanner throughout our methods
+ // so we keep our own copy here.
+ private PluginDeploymentScanner pluginScanner;
+
+ @AfterClass
+ public void afterClass() throws Exception {
+ this.pluginScanner = null;
+ super.afterClass();
+ }
+
+ @Override
+ protected void preparePluginScannerService() {
+ if (this.pluginScanner == null) {
+ this.pluginScanner = new PluginDeploymentScanner();
+ }
+ super.preparePluginScannerService(this.pluginScanner);
+ }
+
+ public void registerPlugins() throws Exception {
+ subjectMgr = LookupUtil.getSubjectManager();
+ pluginMgr = LookupUtil.getPluginManager();
+
+ List<Plugin> plugins = getEntityManager().createQuery("from Plugin where name IN ('PluginManagerBeanTestPlugin1', 'PluginManagerBeanTestPlugin2', 'PluginManagerBeanTestPlugin3')").getResultList();
+ if (!plugins.isEmpty()) {
+ System.out.println("Purging plugins " + plugins + "...");
+ for (Plugin plugin : plugins) {
+ pluginMgr.deletePlugins(subjectMgr.getOverlord(), asList(plugin.getId()));
+ pluginMgr.markPluginsForPurge(subjectMgr.getOverlord(), asList(plugin.getId()));
+ }
+ new PurgeResourceTypesJob().execute(null);
+ new PurgePluginsJob().execute(null);
+ }
+
+ createPlugin("test-plugin1", "1.0", "plugin_1.xml");
+ createPlugin("test-plugin2", "1.0", "plugin_2.xml");
+ createPlugin("test-plugin3", "1.0", "plugin_3.xml");
+ }
+
+ @Test(dependsOnMethods = { "registerPlugins" })
+ public void disablePlugin() throws Exception {
+ Plugin plugin = getPlugin("PluginManagerBeanTestPlugin3");
+
+ pluginMgr.disablePlugins(subjectMgr.getOverlord(), asList(plugin.getId()));
+ plugin = pluginMgr.getPlugin("PluginManagerBeanTestPlugin3");
+
+ assertNotNull(plugin);
+ assertFalse("Failed to disable plugin", plugin.isEnabled());
+ }
+
+ @Test(dependsOnMethods = { "registerPlugins" })
+ public void doNotDisablePluginIfDependentPluginsAreNotAlsoDisabled() throws Exception {
+ Plugin plugin = getPlugin("PluginManagerBeanTestPlugin1");
+ EJBException exception = null;
+
+ try {
+ pluginMgr.disablePlugins(subjectMgr.getOverlord(), asList(plugin.getId()));
+ } catch (EJBException e) {
+ exception = e;
+ }
+
+ assertNotNull("Expected exception to be thrown when trying to disable a plugin that has dependent plugins",
+ exception);
+ assertTrue("Expected an IllegalArgumentException when trying to disable a plugin with dependent plugins",
+ exception.getCausedByException() instanceof IllegalArgumentException);
+ }
+
+ @Test(dependsOnMethods = { "doNotDisablePluginIfDependentPluginsAreNotAlsoDisabled" })
+ public void disablePluginAndDependentPlugins() throws Exception {
+ Plugin plugin1 = getPlugin("PluginManagerBeanTestPlugin1");
+ Plugin plugin2 = getPlugin("PluginManagerBeanTestPlugin2");
+
+ pluginMgr.disablePlugins(subjectMgr.getOverlord(), asList(plugin1.getId(), plugin2.getId()));
+
+ plugin1 = getPlugin("PluginManagerBeanTestPlugin1");
+ plugin2 = getPlugin("PluginManagerBeanTestPlugin2");
+
+ assertFalse("Failed to disable plugin", plugin1.isEnabled());
+ assertFalse("Failed to disable plugin", plugin2.isEnabled());
+ }
+
+ @Test(groups = { "plugin.metadata", "PluginManagerBean" }, dependsOnMethods = { "disablePluginAndDependentPlugins" })
+ public void enablePlugins() throws Exception {
+ Plugin plugin1 = getPlugin("PluginManagerBeanTestPlugin1");
+ Plugin plugin2 = getPlugin("PluginManagerBeanTestPlugin2");
+
+ pluginMgr.enablePlugins(subjectMgr.getOverlord(), asList(plugin1.getId(), plugin2.getId()));
+
+ plugin1 = getPlugin("PluginManagerBeanTestPlugin1");
+ plugin2 = getPlugin("PluginManagerBeanTestPlugin2");
+
+ assertTrue("Failed to enable plugin", plugin1.isEnabled());
+ assertTrue("Failed to enable plugin", plugin2.isEnabled());
+ }
+
+ @Test(dependsOnMethods = { "enablePlugins" })
+ public void doNotDeletePluginIfDependentPluginIsNotAlsoDeleted() throws Exception {
+ Plugin plugin = getPlugin("PluginManagerBeanTestPlugin1");
+ EJBException exception = null;
+
+ try {
+ pluginMgr.deletePlugins(subjectMgr.getOverlord(), asList(plugin.getId()));
+ } catch (EJBException e) {
+ exception = e;
+ }
+
+ assertNotNull("Expected exception to be thrown when trying to delete a plugin that has dependent plugins",
+ exception);
+ assertTrue("Expected an IllegalArgumentException when trying to delete a plugin with dependent plugins",
+ exception.getCausedByException() instanceof IllegalArgumentException);
+ }
+
+ @Test(dependsOnMethods = { "doNotDeletePluginIfDependentPluginIsNotAlsoDeleted" })
+ public void deletePlugins() throws Exception {
+ Plugin plugin1 = getPlugin("PluginManagerBeanTestPlugin1");
+ Plugin plugin2 = getPlugin("PluginManagerBeanTestPlugin2");
+
+ pluginMgr.deletePlugins(subjectMgr.getOverlord(), asList(plugin1.getId(), plugin2.getId()));
+
+ plugin1 = getPlugin("PluginManagerBeanTestPlugin1", "Deleting a plugin should not remove it from the database");
+ plugin2 = getPlugin("PluginManagerBeanTestPlugin2", "Deleting a plugin should not remove it from the database");
+
+ assertTrue("Expected plugin status to be set to DELETED", plugin1.getStatus() == PluginStatusType.DELETED);
+ assertTrue("Expected plugin status to be set to DELETED", plugin2.getStatus() == PluginStatusType.DELETED);
+ }
+
+ @Test(enabled = false, dependsOnMethods = { "deletePlugins" })
+ public void purgePlugins() throws Exception {
+ Plugin plugin1 = getPlugin("PluginManagerBeanTestPlugin1",
+ "Deleting a plugin should not remove it from the database");
+ Plugin plugin2 = getPlugin("PluginManagerBeanTestPlugin2",
+ "Deleting a plugin should not remove it from the database");
+
+ pluginMgr.markPluginsForPurge(subjectMgr.getOverlord(), asList(plugin1.getId(), plugin2.getId()));
+
+ assertEquals("Failed to purge plugins from the database", 1, pluginMgr.getPlugins().size());
+ }
+
+ private Plugin getPlugin(String name) {
+ Plugin plugin = pluginMgr.getPlugin(name);
+ assertNotNull("Failed to find plugin [" + name + "].", plugin);
+
+ return plugin;
+ }
+
+ private Plugin getPlugin(String name, String msg) {
+ List<Plugin> plugins = getEntityManager().createQuery("from Plugin where name = :name")
+ .setParameter("name", name).getResultList();
+ assertTrue("Failed to find plugin [" + name + "]: " + msg, plugins.size() == 1);
+
+ return plugins.get(0);
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest.java
new file mode 100644
index 0000000..624793c
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest.java
@@ -0,0 +1,224 @@
+package org.rhq.enterprise.server.resource.metadata;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.criteria.ResourceTypeCriteria;
+import org.rhq.core.domain.operation.OperationDefinition;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.core.plugin.PluginDeploymentScanner;
+import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * This test shows a plugin extended multiple times via the embedded extension model,
+ * but it tests starting with the server's plugin scanner service. This helps
+ * simulate more closely the full end-to-end agent plugin scanning and deployment
+ * mechanism during which resource types are registered.
+ *
+ * There is one parent plugin and two child plugins. This test makes sure multiple
+ * plugins can extend and be updated; it won't test a full comprehensive set of
+ * metadata being upgraded. See {@link PluginExtensionMetadataTest} for a
+ * comprehensive test showing all the different kinds of metadata being updated.
+ *
+ * @author John Mazzitelli
+ */
+@Test(groups = { "plugin.extension.scanning.metadata", "plugin.metadata" })
+public class PluginScanningExtensionMetadataTest extends MetadataBeanTest {
+
+ private static final String PLUGIN_NAME_PARENT = "PluginScanningExtensionMetadataParentTestPlugin";
+ private static final String PLUGIN_NAME_CHILD1 = "PluginScanningExtensionMetadataChild1TestPlugin";
+ private static final String PLUGIN_NAME_CHILD2 = "PluginScanningExtensionMetadataChild2TestPlugin";
+ private static final String TYPE_NAME_PARENT = "ParentServerA";
+ private static final String TYPE_NAME_CHILD1 = "Child1ServerA";
+ private static final String TYPE_NAME_CHILD2 = "Child2ServerA";
+
+ // names of things from the first version of the plugin metadata
+ private static final String OP_NAME = "A-op";
+ private static final int OP_TIMEOUT = 123456;
+ private static final String OP_DESC = "a op";
+
+ // names of things from the second, updated version of the plugin metadata
+ // updated operations
+ private static final String NEW_OP_NAME = "A-op-NEW";
+ private static final int NEW_OP_TIMEOUT = 987654;
+ private static final String NEW_OP_DESC = "a new op";
+
+ private SubjectManagerLocal subjectMgr;
+ private ResourceTypeManagerLocal resourceTypeMgr;
+
+ private List<File> createdJarFiles = new ArrayList<File>();
+ private PluginDeploymentScanner pluginScanner;
+
+ @BeforeMethod
+ public void prepareBeforeTestMethod() {
+ subjectMgr = LookupUtil.getSubjectManager();
+ resourceTypeMgr = LookupUtil.getResourceTypeManager();
+
+ // clean up any old previously generated jar files so they don't get in the way
+ if (!createdJarFiles.isEmpty()) {
+ for (File doomed : createdJarFiles) {
+ doomed.delete();
+ }
+ }
+ createdJarFiles.clear();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void cleanUpAfterTestMethod() {
+ // clean up any generated jar files - we want to remove these so they don't get in the way of a future test run
+ if (!createdJarFiles.isEmpty()) {
+ for (File doomed : createdJarFiles) {
+ doomed.delete();
+ }
+ }
+ createdJarFiles.clear();
+ }
+
+ @Override
+ @Test(enabled = false)
+ // this method isn't a test method
+ protected void preparePluginScannerService() {
+ if (this.pluginScanner == null) {
+ this.pluginScanner = new PluginDeploymentScanner();
+
+ String pluginDirPath = null;
+ try {
+ pluginDirPath = getPluginWorkDir();
+ } catch (Exception e) {
+ throw new RuntimeException("Cannot determine where to put the plugin jar files", e);
+ }
+ this.pluginScanner.setAgentPluginDir(pluginDirPath); // we don't want to scan for these
+ this.pluginScanner.setServerPluginDir(null); // we don't want to scan for these
+ this.pluginScanner.setScanPeriod("9999999"); // we want to manually scan - don't allow for auto-scan to happen
+ }
+ super.preparePluginScannerService(this.pluginScanner);
+
+ try {
+ this.pluginScanner.start();
+ } catch (Exception e) {
+ throw new RuntimeException(e); // should never really happen
+ }
+
+ }
+
+ public void testRegisterPlugins() throws Exception {
+ try {
+ registerParentPluginV1(); // create an initial type (called the parent)
+ registerChild1PluginV1(); // using plugin extension mechanism, create child #1 type that extends that parent type
+ registerChild2PluginV1(); // using plugin extension mechanism, create child #2 type that extends that parent type
+ registerParentPluginV2(); // update the parent type
+ checkChild1Plugin(); // check that the changes to the parent type propogated to the child #1
+ checkChild2Plugin(); // check that the changes to the parent type propogated to the child #2
+ } finally {
+ // let our superclass know about our plugins so it can clean them up
+ pluginDeployed(PLUGIN_NAME_PARENT);
+ pluginDeployed(PLUGIN_NAME_CHILD1);
+ pluginDeployed(PLUGIN_NAME_CHILD2);
+ }
+ }
+
+ private void registerParentPluginV1() throws Exception {
+ // register the plugin, load the new type and test to make sure its what we expect
+ createdJarFiles.add(createPluginJarFile("parent-plugin.jar", "parent_plugin_v1.xml"));
+ this.pluginScanner.startDeployment(); // first time we need to scan so call startDeployment which will call scanAndRegister
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_PARENT, PLUGIN_NAME_PARENT);
+ assert resourceType.getName().equals(TYPE_NAME_PARENT);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_PARENT);
+ assertVersion1(resourceType);
+ }
+
+ private void registerChild1PluginV1() throws Exception {
+ // register the plugin, load the new type and test to make sure its what we expect
+ createdJarFiles.add(createPluginJarFile("child1-plugin.jar", "child1_plugin_v1.xml"));
+ this.pluginScanner.scanAndRegister();
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_CHILD1, PLUGIN_NAME_CHILD1);
+ assert resourceType.getName().equals(TYPE_NAME_CHILD1);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_CHILD1);
+ assertVersion1(resourceType);
+
+ // in our child #1 plugin, our extended type is actually a child of child #1 plugin's root type
+ // here we want to make sure that hierarchy remains intact with our extended type - the parent
+ // of our extended type should be this child #1 root type
+ assert resourceType.getParentResourceTypes() != null;
+ assert resourceType.getParentResourceTypes().size() == 1;
+ assert resourceType.getParentResourceTypes().iterator().next().getName().equals("OuterServerA");
+ }
+
+ private void registerChild2PluginV1() throws Exception {
+ // register the plugin, load the new type and test to make sure its what we expect
+ createdJarFiles.add(createPluginJarFile("child2-plugin.jar", "child2_plugin_v1.xml"));
+ this.pluginScanner.scanAndRegister();
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_CHILD2, PLUGIN_NAME_CHILD2);
+ assert resourceType.getName().equals(TYPE_NAME_CHILD2);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_CHILD2);
+ assertVersion1(resourceType);
+ }
+
+ private void registerParentPluginV2() throws Exception {
+ // register the plugin, load the new type and test to make sure its what we expect
+ createdJarFiles.add(createPluginJarFile("parent-plugin.jar", "parent_plugin_v2.xml"));
+ this.pluginScanner.scanAndRegister();
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_PARENT, PLUGIN_NAME_PARENT);
+ assert resourceType.getName().equals(TYPE_NAME_PARENT);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_PARENT);
+ assertVersion2(resourceType);
+ }
+
+ private void checkChild1Plugin() throws Exception {
+ // load the child #1 type and test to make sure it has been updated to what we expect
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_CHILD1, PLUGIN_NAME_CHILD1);
+ assert resourceType.getName().equals(TYPE_NAME_CHILD1);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_CHILD1);
+ assertVersion2(resourceType);
+
+ // in our child #1 plugin, our extended type is actually a child of child #1 plugin's root type
+ // here we want to make sure that hierarchy remains intact with our extended type - the parent
+ // of our extended type should be this child #1 root type
+ assert resourceType.getParentResourceTypes() != null;
+ assert resourceType.getParentResourceTypes().size() == 1;
+ assert resourceType.getParentResourceTypes().iterator().next().getName().equals("OuterServerA");
+ }
+
+ private void checkChild2Plugin() throws Exception {
+ // load the child #2 type and test to make sure it has been updated to what we expect
+ ResourceType resourceType = loadResourceTypeFully(TYPE_NAME_CHILD2, PLUGIN_NAME_CHILD2);
+ assert resourceType.getName().equals(TYPE_NAME_CHILD2);
+ assert resourceType.getPlugin().equals(PLUGIN_NAME_CHILD2);
+ assertVersion2(resourceType);
+ }
+
+ private void assertVersion1(ResourceType resourceType) {
+ assert resourceType.getOperationDefinitions().size() == 1;
+ OperationDefinition op = resourceType.getOperationDefinitions().iterator().next();
+ assert op.getName().equals(OP_NAME);
+ assert op.getTimeout().intValue() == OP_TIMEOUT;
+ assert op.getDescription().equals(OP_DESC);
+ }
+
+ private void assertVersion2(ResourceType resourceType) {
+ assert resourceType.getOperationDefinitions().size() == 1;
+ OperationDefinition op = resourceType.getOperationDefinitions().iterator().next();
+ assert op.getName().equals(NEW_OP_NAME);
+ assert op.getTimeout().intValue() == NEW_OP_TIMEOUT;
+ assert op.getDescription().equals(NEW_OP_DESC);
+ }
+
+ private ResourceType loadResourceTypeFully(String typeName, String typePlugin) {
+ ResourceTypeCriteria c = new ResourceTypeCriteria();
+ c.addFilterName(typeName);
+ c.addFilterPluginName(typePlugin);
+ c.setStrict(true);
+ c.fetchParentResourceTypes(true);
+ c.fetchOperationDefinitions(true);
+ List<ResourceType> t = resourceTypeMgr.findResourceTypesByCriteria(subjectMgr.getOverlord(), c);
+ ResourceType resourceType = t.get(0);
+ return resourceType;
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java
new file mode 100644
index 0000000..0e142e9
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java
@@ -0,0 +1,702 @@
+package org.rhq.enterprise.server.resource.metadata;
+
+import static java.util.Arrays.asList;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.Query;
+
+import org.apache.commons.beanutils.MethodUtils;
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.lang.WordUtils;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.alert.AlertDampening;
+import org.rhq.core.domain.alert.AlertDefinition;
+import org.rhq.core.domain.alert.AlertPriority;
+import org.rhq.core.domain.alert.BooleanExpression;
+import org.rhq.core.domain.bundle.Bundle;
+import org.rhq.core.domain.bundle.BundleType;
+import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration;
+import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory;
+import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory.Context;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.content.Package;
+import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.criteria.OperationDefinitionCriteria;
+import org.rhq.core.domain.criteria.ResourceCriteria;
+import org.rhq.core.domain.criteria.ResourceTypeCriteria;
+import org.rhq.core.domain.drift.DriftConfigurationDefinition;
+import org.rhq.core.domain.drift.DriftConfigurationDefinition.BaseDirValueContext;
+import org.rhq.core.domain.drift.DriftDefinition;
+import org.rhq.core.domain.drift.DriftDefinitionTemplate;
+import org.rhq.core.domain.drift.Filter;
+import org.rhq.core.domain.operation.OperationDefinition;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.shared.ResourceBuilder;
+import org.rhq.enterprise.server.alert.AlertTemplateManagerLocal;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.bundle.BundleManagerLocal;
+import org.rhq.enterprise.server.content.ContentManagerLocal;
+import org.rhq.enterprise.server.operation.OperationManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+public class ResourceMetadataManagerBeanTest extends MetadataBeanTest {
+
+ @Test(groups = { "plugin.resource.metadata.test", "plugin.metadata", "NewPlugin" })
+ public void testRemovalOfObsoleteBundleAndDriftConfig() throws Exception {
+ // create the initial type that has bundle and drift definitions
+ createPlugin("test-plugin.jar", "1.0", "remove_bundle_drift_config_v1.xml");
+
+ // make sure the drift definition was persisted, and remember the type
+ ResourceType type1 = assertResourceTypeAssociationEquals("ServerWithBundleAndDriftConfig", "TestPlugin",
+ "driftDefinitionTemplates", asList("drift1"));
+
+ // sanity check, make sure our queries work and that we did persist these things
+ Query qTemplate;
+ Query qConfig;
+ //String qTemplateString = "select ct from ConfigurationTemplate ct where ct.id = :id";
+ String qTemplateString = "from DriftDefinitionTemplate where id = :id";
+ String qConfigString = "from Configuration c where id = :id";
+ DriftDefinitionTemplate driftTemplate = type1.getDriftDefinitionTemplates().iterator().next();
+ Configuration bundleConfig = type1.getResourceTypeBundleConfiguration().getBundleConfiguration();
+ Configuration driftDefConfig = driftTemplate.getConfiguration();
+
+ getTransactionManager().begin();
+ try {
+ qTemplate = getEntityManager().createQuery(qTemplateString).setParameter("id", driftTemplate.getId());
+ qConfig = getEntityManager().createQuery(qConfigString).setParameter("id", driftDefConfig.getId());
+ assertEquals("drift template didn't get persisted", 1, qTemplate.getResultList().size());
+ assertEquals("drift template config didn't get persisted", 1, qConfig.getResultList().size());
+
+ qConfig.setParameter("id", bundleConfig.getId());
+ assertEquals("bundle config didn't get persisted", 1, qConfig.getResultList().size());
+ } finally {
+ getTransactionManager().commit();
+ }
+
+ // make sure the bundle config was also persisted
+ // NOTE: WHY DOES THIS WORK? I DIDN'T ASK TO FETCH IT AND IT IS MARKED AS LAZY LOAD
+ assertNotNull(type1.getResourceTypeBundleConfiguration());
+ assertEquals("destdir1", type1.getResourceTypeBundleConfiguration().getBundleDestinationBaseDirectories()
+ .iterator().next().getName());
+
+ // upgrade the type which removes the bundle config and drift definition
+ createPlugin("test-plugin.jar", "2.0", "remove_bundle_drift_config_v2.xml");
+
+ getTransactionManager().begin();
+ try {
+ qTemplate = getEntityManager().createQuery(qTemplateString).setParameter("id", driftTemplate.getId());
+ qConfig = getEntityManager().createQuery(qConfigString).setParameter("id", driftDefConfig.getId());
+ assertEquals("drift template didn't get purged", 0, qTemplate.getResultList().size());
+ assertEquals("drift template config didn't get purged", 0, qConfig.getResultList().size());
+
+ qConfig.setParameter("id", bundleConfig.getId());
+ assertEquals("bundle config didn't get purged", 0, qConfig.getResultList().size());
+ } finally {
+ getTransactionManager().commit();
+ }
+ }
+
+ @Test(groups = { "plugin.resource.metadata.test", "plugin.metadata", "NewPlugin" })
+ public void registerPluginWithDuplicateDriftDefinitions() {
+ try {
+ createPlugin("test-plugin.jar", "1.0", "dup_drift.xml");
+ fail("should not have succeeded - the drift definition had duplicate names");
+ } catch (Exception e) {
+ // OK, the plugin should have failed to be deployed since it has duplicate drift definitions
+ }
+ }
+
+ @Test(dependsOnMethods = { "registerPluginWithDuplicateDriftDefinitions" }, groups = {
+ "plugin.resource.metadata.test", "plugin.metadata", "NewPlugin" })
+ public void registerPlugin() throws Exception {
+ createPlugin("test-plugin.jar", "1.0", "plugin_v1.xml");
+ }
+
+
+ @Test(dependsOnMethods = { "registerPluginWithDuplicateDriftDefinitions" }, groups = {
+ "plugin.resource.metadata.test", "plugin.metadata", "NewPlugin" })
+ public void registerParentResouceTypePlugin() throws Exception {
+ createPlugin("parent_resource_type-plugin.jar", "1.0", "parent_resource_type-plugin.xml");
+ assertResourceTypeAssociationEquals("Server A First Level", "ParentResourceTypeTestPlugin",
+ "childResourceTypes", asList("Server B Second Level", "Service A Second Level"));
+ assertResourceTypeAssociationEquals("Server B Second Level", "ParentResourceTypeTestPlugin",
+ "childResourceTypes", asList("Server C First Level", "Service B First Level"));
+ assertResourceTypeAssociationEquals("Service A Second Level", "ParentResourceTypeTestPlugin",
+ "childResourceTypes", asList("Service C First Level"));
+ }
+
+
+ @Test(dependsOnMethods = { "registerPlugin" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "NewPlugin" })
+ public void persistNewTypes() {
+ List<String> newTypes = asList("ServerA", "ServerB");
+ assertTypesPersisted("Failed to persist new types", newTypes, "TestPlugin");
+ }
+
+ // @Test(dependsOnMethods = {"persistNewTypes"}, groups = {"plugin.resource.metadata.test", "plugin.metadata", "NewPlugin"})
+ // public void persistSubcategories() throws Exception {
+ // assertResourceTypeAssociationEquals(
+ // "ServerA",
+ // "TestPlugin",
+ // "childSubCategories",
+ // asList("Resources", "Applications")
+ // );
+ // }
+
+ @Test(dependsOnMethods = { "persistNewTypes" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "NewPlugin" })
+ public void persistMeasurementDefinitions() throws Exception {
+ assertResourceTypeAssociationEquals("ServerA", "TestPlugin", "metricDefinitions",
+ asList("metric1", "metric2", "rhq.availability"));
+ }
+
+ @Test(dependsOnMethods = { "persistNewTypes" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "NewPlugin" })
+ public void persistEventDefinitions() throws Exception {
+ assertResourceTypeAssociationEquals("ServerA", "TestPlugin", "eventDefinitions",
+ asList("logAEntry", "logBEntry"));
+ }
+
+ @Test(dependsOnMethods = { "persistNewTypes" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "NewPlugin" })
+ public void persistOperationDefinitions() throws Exception {
+ assertResourceTypeAssociationEquals("ServerA", "TestPlugin", "operationDefinitions", asList("start", "stop"));
+ }
+
+ @Test(dependsOnMethods = { "persistNewTypes" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "NewPlugin" })
+ public void persistProcessScans() throws Exception {
+ assertResourceTypeAssociationEquals("ServerA", "TestPlugin", "processScans", asList("serverA"));
+ }
+
+ @Test(dependsOnMethods = { "persistNewTypes" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "NewPlugin" })
+ public void persistDriftDefinitionTemplates() throws Exception {
+ ResourceType type = assertResourceTypeAssociationEquals("ServerA", "TestPlugin", "driftDefinitionTemplates",
+ asList("drift-pc", "drift-fs"));
+
+ DriftDefinition driftDef = null;
+ Set<DriftDefinitionTemplate> drifts = type.getDriftDefinitionTemplates();
+ for (DriftDefinitionTemplate drift : drifts) {
+ if (drift.getName().equals("drift-pc")) {
+ driftDef = new DriftDefinition(drift.getConfiguration());
+ assertTrue(driftDef.isEnabled());
+ assertEquals(BaseDirValueContext.pluginConfiguration, driftDef.getBasedir().getValueContext());
+ assertEquals("connectionPropertyX", driftDef.getBasedir().getValueName());
+ assertEquals(123456L, driftDef.getInterval());
+ assertEquals(1, driftDef.getIncludes().size());
+ assertEquals(2, driftDef.getExcludes().size());
+ Filter filter = driftDef.getIncludes().get(0);
+ assertEquals("foo/bar", filter.getPath());
+ assertEquals("**/*.blech", filter.getPattern());
+ filter = driftDef.getExcludes().get(0);
+ assertEquals("/wot/gorilla", filter.getPath());
+ assertEquals("*.xml", filter.getPattern());
+ filter = driftDef.getExcludes().get(1);
+ assertEquals("/hello", filter.getPath());
+ assertEquals("", filter.getPattern());
+ } else if (drift.getName().equals("drift-fs")) {
+ driftDef = new DriftDefinition(drift.getConfiguration());
+ assertTrue(driftDef.isEnabled());
+ assertEquals(BaseDirValueContext.fileSystem, driftDef.getBasedir().getValueContext());
+ assertEquals("/", driftDef.getBasedir().getValueName());
+ assertEquals(DriftConfigurationDefinition.DEFAULT_INTERVAL, driftDef.getInterval());
+ assertEquals(0, driftDef.getIncludes().size());
+ assertEquals(0, driftDef.getExcludes().size());
+ } else {
+ fail("got an unexpected drift definition: " + driftDef);
+ }
+ }
+ }
+
+ @Test(dependsOnMethods = { "persistNewTypes" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "NewPlugin" })
+ public void persistBundleTargetConfigurations() throws Exception {
+ String resourceTypeName = "ServerA";
+ String plugin = "TestPlugin";
+
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+ ResourceTypeManagerLocal resourceTypeMgr = LookupUtil.getResourceTypeManager();
+
+ ResourceTypeCriteria criteria = new ResourceTypeCriteria();
+ criteria.addFilterName(resourceTypeName);
+ criteria.addFilterPluginName(plugin);
+ criteria.fetchBundleConfiguration(true);
+ List<ResourceType> resourceTypes = resourceTypeMgr.findResourceTypesByCriteria(subjectMgr.getOverlord(),
+ criteria);
+ ResourceType resourceType = resourceTypes.get(0);
+
+ ResourceTypeBundleConfiguration rtbc = resourceType.getResourceTypeBundleConfiguration();
+ assertNotNull("missing bundle configuration", rtbc);
+ Set<BundleDestinationBaseDirectory> dirs = rtbc.getBundleDestinationBaseDirectories();
+ assertEquals("Should have persisted 2 bundle dest dirs", 2, dirs.size());
+ for (BundleDestinationBaseDirectory dir : dirs) {
+ if (dir.getName().equals("bundleTarget-pc")) {
+ assertEquals(Context.pluginConfiguration, dir.getValueContext());
+ assertEquals("connectionPropertyY", dir.getValueName());
+ assertEquals("pc-description", dir.getDescription());
+ } else if (dir.getName().equals("bundleTarget-fs")) {
+ assertEquals(Context.fileSystem, dir.getValueContext());
+ assertEquals("/wot/gorilla", dir.getValueName());
+ assertNull(dir.getDescription());
+ } else {
+ fail("got an unexpected bundle target dest dir: " + dir);
+ }
+ }
+ }
+
+ @Test(dependsOnMethods = { "persistNewTypes" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "NewPlugin" })
+ public void persistChildTypes() throws Exception {
+ assertResourceTypeAssociationEquals("ServerA", "TestPlugin", "childResourceTypes", asList("Child1", "Child2"));
+ }
+
+ @Test(dependsOnMethods = { "persistNewTypes" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "NewPlugin" })
+ public void persistPluginConfigurationDefinition() throws Exception {
+ assertAssociationExists("ServerA", "pluginConfigurationDefinition");
+ }
+
+ @Test(dependsOnMethods = { "persistNewTypes" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "NewPlugin" })
+ public void persistPackageTypes() throws Exception {
+ assertResourceTypeAssociationEquals("ServerA", "TestPlugin", "packageTypes",
+ asList("ServerA.Content.1", "ServerA.Content.2"));
+ }
+
+ @Test(groups = { "plugin.resource.metadata.test", "plugin.metadata", "UpgradePlugin" }, dependsOnGroups = { "NewPlugin" })
+ public void upgradePlugin() throws Exception {
+ createPlugin("test-plugin.jar", "2.0", "plugin_v2.xml");
+ }
+
+ @Test(dependsOnMethods = { "upgradePlugin" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "UpgradePlugin" })
+ public void upgradeOperationDefinitions() throws Exception {
+ assertResourceTypeAssociationEquals("ServerA", "TestPlugin", "operationDefinitions",
+ asList("start", "shutdown", "restart"));
+ }
+
+ @Test(dependsOnMethods = { "upgradePlugin" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "UpgradePlugin" })
+ public void upgradeChildResources() throws Exception {
+ assertResourceTypeAssociationEquals("ServerA", "TestPlugin", "childResourceTypes", asList("Child1", "Child3"));
+ }
+
+ @Test(dependsOnMethods = { "upgradePlugin" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "UpgradePlugin" })
+ public void upgradeParentTypeOfChild() throws Exception {
+ assertResourceTypeAssociationEquals("ServerB", "TestPlugin", "childResourceTypes", asList("Child2"));
+ }
+
+ @Test(dependsOnMethods = { "upgradePlugin" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "UpgradePlugin" })
+ public void upgradeEventDefinitions() throws Exception {
+ assertResourceTypeAssociationEquals("ServerA", "TestPlugin", "eventDefinitions",
+ asList("logAEntry", "logCEntry"));
+ }
+
+ @Test(dependsOnMethods = { "upgradePlugin" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "UpgradePlugin" })
+ public void upgradeProcessScans() throws Exception {
+ assertResourceTypeAssociationEquals("ServerA", "TestPlugin", "processScans", asList("processA", "processB"));
+ }
+
+ @Test(dependsOnMethods = { "upgradePlugin" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "UpgradePlugin" })
+ public void upgradeDriftDefinitionTemplates() throws Exception {
+ ResourceType type = assertResourceTypeAssociationEquals("ServerA", "TestPlugin", "driftDefinitionTemplates",
+ asList("drift-rc", "drift-mt"));
+
+ DriftDefinition driftDef = null;
+ Set<DriftDefinitionTemplate> drifts = type.getDriftDefinitionTemplates();
+ for (DriftDefinitionTemplate drift : drifts) {
+ if (drift.getName().equals("drift-rc")) {
+ driftDef = new DriftDefinition(drift.getConfiguration());
+ assertTrue(driftDef.isEnabled());
+ assertEquals(BaseDirValueContext.resourceConfiguration, driftDef.getBasedir().getValueContext());
+ assertEquals("resourceConfig1", driftDef.getBasedir().getValueName());
+ assertEquals(DriftConfigurationDefinition.DEFAULT_INTERVAL, driftDef.getInterval());
+ assertEquals(0, driftDef.getIncludes().size());
+ assertEquals(0, driftDef.getExcludes().size());
+ } else if (drift.getName().equals("drift-mt")) {
+ driftDef = new DriftDefinition(drift.getConfiguration());
+ assertTrue(driftDef.isEnabled());
+ assertEquals(BaseDirValueContext.measurementTrait, driftDef.getBasedir().getValueContext());
+ assertEquals("trait1", driftDef.getBasedir().getValueName());
+ assertEquals(DriftConfigurationDefinition.DEFAULT_INTERVAL, driftDef.getInterval());
+ assertEquals(0, driftDef.getIncludes().size());
+ assertEquals(0, driftDef.getExcludes().size());
+ } else {
+ fail("got an unexpected drift definition: " + driftDef);
+ }
+ }
+ }
+
+ @Test(dependsOnMethods = { "upgradePlugin" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "UpgradePlugin" })
+ public void upgradeBundleTargetConfigurations() throws Exception {
+ String resourceTypeName = "ServerA";
+ String plugin = "TestPlugin";
+
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+ ResourceTypeManagerLocal resourceTypeMgr = LookupUtil.getResourceTypeManager();
+
+ ResourceTypeCriteria criteria = new ResourceTypeCriteria();
+ criteria.addFilterName(resourceTypeName);
+ criteria.addFilterPluginName(plugin);
+ criteria.fetchBundleConfiguration(true);
+ List<ResourceType> resourceTypes = resourceTypeMgr.findResourceTypesByCriteria(subjectMgr.getOverlord(),
+ criteria);
+ ResourceType resourceType = resourceTypes.get(0);
+
+ ResourceTypeBundleConfiguration rtbc = resourceType.getResourceTypeBundleConfiguration();
+ assertNotNull("missing bundle configuration", rtbc);
+ Set<BundleDestinationBaseDirectory> dirs = rtbc.getBundleDestinationBaseDirectories();
+ assertEquals("Should have persisted 2 bundle dest dirs", 2, dirs.size());
+ for (BundleDestinationBaseDirectory dir : dirs) {
+ if (dir.getName().equals("bundleTarget-rc")) {
+ assertEquals(Context.resourceConfiguration, dir.getValueContext());
+ assertEquals("resourceConfig1", dir.getValueName());
+ assertEquals("rc-description", dir.getDescription());
+ } else if (dir.getName().equals("bundleTarget-mt")) {
+ assertEquals(Context.measurementTrait, dir.getValueContext());
+ assertEquals("trait1", dir.getValueName());
+ assertEquals("mt-description", dir.getDescription());
+ } else {
+ assertTrue("got an unexpected bundle target dest dir: " + dir, false);
+ }
+ }
+ }
+
+ @Test(dependsOnMethods = { "upgradePlugin" }, groups = { "plugin.resource.metadata.test", "plugin.metadata",
+ "UpgradePlugin" })
+ public void upgradePackageTypes() throws Exception {
+ assertResourceTypeAssociationEquals("ServerA", "TestPlugin", "packageTypes",
+ asList("ServerA.Content.1", "ServerA.Content.3"));
+ }
+
+ @Test(groups = { "RemoveTypes" }, dependsOnGroups = { "UpgradePlugin" })
+ public void upgradePluginWithTypesRemoved() throws Exception {
+ createPlugin("remove-types-plugin", "1.0", "remove_types_v1.xml");
+
+ createResources(3, "RemoveTypesPlugin", "ServerC");
+ createBundle("test-bundle-1", "Test Bundle", "ServerC", "RemoveTypesPlugin");
+ createPackage("ServerC::test-package", "ServerC", "RemoveTypesPlugin");
+ createResourceGroup("ServerC Group", "ServerC", "RemoveTypesPlugin");
+ createAlertTemplate("ServerC Alert Template", "ServerC", "RemoveTypesPlugin");
+
+ createPlugin("remove-types-plugin", "2.0", "remove_types_v2.xml");
+ }
+
+ @Test(dependsOnMethods = { "upgradePluginWithTypesRemoved" }, groups = { "plugin.resource.metadata.test",
+ "plugin.metadata", "RemoveTypes" })
+ public void deleteOperationDefsForRemovedType() throws Exception {
+ OperationManagerLocal operationMgr = LookupUtil.getOperationManager();
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+
+ OperationDefinitionCriteria criteria = new OperationDefinitionCriteria();
+ criteria.addFilterResourceTypeName("ServerC");
+ criteria.addFilterName("run");
+
+ List<OperationDefinition> operationDefs = operationMgr.findOperationDefinitionsByCriteria(
+ subjectMgr.getOverlord(), criteria);
+
+ assertEquals("The operation definition should have been deleted", 0, operationDefs.size());
+ }
+
+ @Test(dependsOnMethods = { "upgradePluginWithTypesRemoved" }, groups = { "plugin.resource.metadata.test",
+ "plugin.metadata", "RemoveTypes" })
+ public void deleteEventDefsForRemovedType() throws Exception {
+ List<?> results = getEntityManager()
+ .createQuery("from EventDefinition e where e.name = :ename and e.resourceType.name = :rname")
+ .setParameter("ename", "serverCEvent").setParameter("rname", "ServerC").getResultList();
+
+ assertEquals("The event definition(s) should have been deleted", 0, results.size());
+ }
+
+ @Test(dependsOnMethods = { "upgradePluginWithTypesRemoved" }, groups = { "plugin.resource.metadata.test",
+ "plugin.metadata", "RemoveTypes" })
+ public void deleteParent() throws Exception {
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+ ResourceTypeManagerLocal resourceTypeMgr = LookupUtil.getResourceTypeManager();
+
+ ResourceTypeCriteria criteria = new ResourceTypeCriteria();
+ criteria.addFilterName("ServerD.GrandChild1");
+ criteria.addFilterPluginName("RemoveTypesPlugin");
+ criteria.fetchParentResourceTypes(true);
+
+ List<ResourceType> types = resourceTypeMgr.findResourceTypesByCriteria(subjectMgr.getOverlord(), criteria);
+
+ assertEquals("Expected to get back one resource type", 1, types.size());
+
+ ResourceType type = types.get(0);
+
+ assertEquals("Expected to find one parent type", 1, type.getParentResourceTypes().size());
+
+ ResourceType parentType = findByName(type.getParentResourceTypes(), "ServerD");
+
+ assertNotNull("Expected to find 'ServerD' as the parent, but found, " + type.getParentResourceTypes(),
+ parentType);
+ }
+
+ private ResourceType findByName(Collection<ResourceType> types, String name) {
+ for (ResourceType type : types) {
+ if (type.getName().equals(name)) {
+ return type;
+ }
+ }
+ return null;
+ }
+
+ @Test(dependsOnMethods = { "upgradePluginWithTypesRemoved" }, groups = { "plugin.resource.metadata.test",
+ "plugin.metadata", "RemoveTypes" })
+ public void deleteTypeAndAllItsDescedantTypes() throws Exception {
+ List<?> typesNotRemoved = getEntityManager()
+ .createQuery("from ResourceType t where t.plugin = :plugin and t.name in (:resourceTypes)")
+ .setParameter("plugin", "RemoveTypesPlugin")
+ .setParameter("resourceTypes", asList("ServerE", "ServerE1", "ServerE2", "ServerE3", "ServerE4"))
+ .getResultList();
+
+ assertEquals("Failed to delete resource type or one or more of its descendant types", 0, typesNotRemoved.size());
+ }
+
+ @Test(dependsOnMethods = { "upgradePluginWithTypesRemoved" }, groups = { "plugin.resource.metadata.test",
+ "plugin.metadata", "RemoveTypes" })
+ public void deleteProcessScans() {
+ List<?> processScans = getEntityManager()
+ .createQuery("from ProcessScan p where p.name = :name1 or p.name = :name2").setParameter("name1", "scan1")
+ .setParameter("name2", "scan2").getResultList();
+
+ assertEquals("The process scans should have been deleted", 0, processScans.size());
+ }
+
+ @Test(dependsOnMethods = { "upgradePluginWithTypesRemoved" }, groups = { "plugin.resource.metadata.test",
+ "plugin.metadata", "RemoveTypes" })
+ public void deleteSubcategories() {
+ List<?> subcategories = getEntityManager()
+ .createQuery("from ResourceSubCategory r where r.name = :name1 or r.name = :name2 or r.name = :name3")
+ .setParameter("name1", "ServerC.Category1").setParameter("name2", "ServerC.Category2")
+ .setParameter("name3", "ServerC.NestedCategory1").getResultList();
+ assertEquals("The subcategories should have been deleted", 0, subcategories.size());
+ }
+
+ @Test(dependsOnMethods = { "upgradePluginWithTypesRemoved" }, groups = { "plugin.resource.metadata.test",
+ "plugin.metadata", "RemoveTypes" })
+ public void deleteResources() {
+ ResourceManagerLocal resourceMgr = LookupUtil.getResourceManager();
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+
+ ResourceCriteria criteria = new ResourceCriteria();
+ criteria.addFilterResourceTypeName("ServerC");
+ criteria.addFilterPluginName("RemoveTypesPlugin");
+
+ List<Resource> resources = resourceMgr.findResourcesByCriteria(subjectMgr.getOverlord(), criteria);
+
+ assertTrue("Did not expect to find any more that three resources. Database might need to be reset",
+ resources.size() < 4);
+
+ // We won't do anything more rigorous that making sure the resources were marked uninventoried.
+ // Resource deletion is an expensive, time-consuming process; consequently, it is carried out
+ // asynchronously in a scheduled job. The call to initiate the resource deletion returns very
+ // quickly as it is basically just updates the the inventory status to UNINVENTORIED for the
+ // resources to be deleted.
+ for (Resource resource : resources) {
+ assertTrue("The resource should have been marked for deletion",
+ InventoryStatus.UNINVENTORIED == resource.getInventoryStatus());
+ }
+ }
+
+ @Test(dependsOnMethods = { "upgradePluginWithTypesRemoved" }, groups = { "plugin.resource.metadata.test",
+ "plugin.metadata", "RemoveTypes" })
+ public void deleteBundles() {
+ List<?> bundles = getEntityManager().createQuery("from Bundle b where b.bundleType.name = :name")
+ .setParameter("name", "Test Bundle").getResultList();
+
+ assertEquals("Failed to delete the bundles", 0, bundles.size());
+ }
+
+ @Test(dependsOnMethods = { "upgradePluginWithTypesRemoved" }, groups = { "plugin.resource.metadata.test",
+ "plugin.metadata", "RemoveTypes" })
+ public void deleteBundleTypes() {
+ List<?> bundleTypes = getEntityManager().createQuery("from BundleType b where b.name = :name")
+ .setParameter("name", "Test Bundle").getResultList();
+
+ assertEquals("The bundle type should have been deleted", 0, bundleTypes.size());
+ }
+
+ @Test(dependsOnMethods = { "upgradePluginWithTypesRemoved" }, groups = { "plugin.resource.metadata.test",
+ "plugin.metadata", "RemoveTypes" })
+ public void deletePackages() {
+ List<?> packages = getEntityManager().createQuery("from Package p where p.name = :name")
+ .setParameter("name", "ServerC::test-package").getResultList();
+
+ assertEquals("All packages should have been deleted", 0, packages.size());
+ }
+
+ @Test(dependsOnMethods = { "upgradePluginWithTypesRemoved" }, groups = { "plugin.resource.metadata.test",
+ "plugin.metadata", "RemoveTypes" })
+ public void deletePackageTypes() {
+ List<?> packageTypes = getEntityManager().createQuery("from PackageType p where p.name = :name")
+ .setParameter("name", "ServerC.Content").getResultList();
+
+ assertEquals("All package types should have been deleted", 0, packageTypes.size());
+ }
+
+ @Test(dependsOnMethods = { "upgradePluginWithTypesRemoved" }, groups = { "plugin.resource.metadata.test",
+ "plugin.metadata", "RemoveTypes" })
+ public void deleteResourceGroups() {
+ List<?> groups = getEntityManager()
+ .createQuery("from ResourceGroup g where g.name = :name and g.resourceType.name = :typeName")
+ .setParameter("name", "ServerC Group").setParameter("typeName", "ServerC").getResultList();
+
+ assertEquals("All resource groups should have been deleted", 0, groups.size());
+ }
+
+ @Test(dependsOnMethods = { "upgradePluginWithTypesRemoved" }, groups = { "plugin.resource.metadata.test",
+ "plugin.metadata", "RemoveTypes" })
+ public void deleteAlertTemplates() {
+ List<?> templates = getEntityManager()
+ .createQuery("from AlertDefinition a where a.name = :name and a.resourceType.name = :typeName")
+ .setParameter("name", "ServerC Alert Template").setParameter("typeName", "ServerC").getResultList();
+
+ assertEquals("Alert templates should have been deleted.", 0, templates.size());
+ }
+
+ @Test(dependsOnMethods = { "upgradePluginWithTypesRemoved" }, groups = { "plugin.resource.metadata.test",
+ "plugin.metadata", "RemoveTypes" })
+ public void deleteMeasurementDefinitions() {
+ List<?> measurementDefs = getEntityManager().createQuery("from MeasurementDefinition m where m.name = :name")
+ .setParameter("name", "ServerC::metric1").getResultList();
+
+ assertEquals("Measurement definitions should have been deleted", 0, measurementDefs.size());
+ }
+
+ void assertTypesPersisted(String msg, List<String> types, String plugin) {
+ List<String> typesNotFound = new ArrayList<String>();
+ ResourceTypeManagerLocal resourceTypeMgr = LookupUtil.getResourceTypeManager();
+
+ for (String type : types) {
+ if (resourceTypeMgr.getResourceTypeByNameAndPlugin(type, plugin) == null) {
+ typesNotFound.add(type);
+ }
+ }
+
+ if (!typesNotFound.isEmpty()) {
+ fail(msg + ": The following types were not found: " + typesNotFound);
+ }
+ }
+
+ void assertAssociationExists(String resourceTypeName, String propertyName) throws Exception {
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+ ResourceTypeManagerLocal resourceTypeMgr = LookupUtil.getResourceTypeManager();
+
+ String fetch = "fetch" + WordUtils.capitalize(propertyName);
+ ResourceTypeCriteria criteria = new ResourceTypeCriteria();
+ criteria.addFilterName(resourceTypeName);
+ criteria.addFilterPluginName("TestPlugin");
+ MethodUtils.invokeMethod(criteria, fetch, true);
+
+ List<ResourceType> resourceTypes = resourceTypeMgr.findResourceTypesByCriteria(subjectMgr.getOverlord(),
+ criteria);
+ ResourceType resourceType = resourceTypes.get(0);
+
+ Object property = PropertyUtils.getProperty(resourceType, propertyName);
+ assertNotNull("Failed to find $propertyName for type '$resourceTypeName'", property);
+ }
+
+ void createResources(int count, String pluginName, String resourceTypeName) throws Exception {
+ ResourceTypeManagerLocal resourceTypeMgr = LookupUtil.getResourceTypeManager();
+ ResourceType resourceType = resourceTypeMgr.getResourceTypeByNameAndPlugin(resourceTypeName, pluginName);
+
+ assertNotNull("Cannot create resources. Unable to find resource type for [name: " + resourceTypeName
+ + ", plugin: " + pluginName + "]", resourceType);
+
+ List<Resource> resources = new ArrayList<Resource>();
+ for (int i = 0; i < count; ++i) {
+ resources.add(new ResourceBuilder().createServer().withResourceType(resourceType)
+ .withName(resourceType.getName() + "--" + i).withUuid(resourceType.getName())
+ .withRandomResourceKey(resourceType.getName() + "--" + i).build());
+ }
+
+ getTransactionManager().begin();
+ for (Resource resource : resources) {
+ getEntityManager().persist(resource);
+ }
+ getTransactionManager().commit();
+ }
+
+ void createBundle(String bundleName, String bundleTypeName, String resourceTypeName, String pluginName)
+ throws Exception {
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+ BundleManagerLocal bundleMgr = LookupUtil.getBundleManager();
+ ResourceTypeManagerLocal resourceTypeMgr = LookupUtil.getResourceTypeManager();
+ ResourceType resourceType = resourceTypeMgr.getResourceTypeByNameAndPlugin(resourceTypeName, pluginName);
+
+ assertNotNull("Cannot create bundle. Unable to find resource type for [name: " + resourceTypeName
+ + ", plugin: " + pluginName + "]", resourceType);
+
+ BundleType bundleType = bundleMgr.getBundleType(subjectMgr.getOverlord(), bundleTypeName);
+ assertNotNull("Cannot create bundle. Unable to find bundle type for [name: " + bundleTypeName + "]", bundleType);
+ Bundle bundle = bundleMgr.createBundle(subjectMgr.getOverlord(), bundleName, "test bundle: " + bundleName,
+ bundleType.getId());
+
+ assertNotNull("Failed create bundle for [name: " + bundleName + "]", bundle);
+ }
+
+ void createPackage(String packageName, String resourceTypeName, String pluginName) throws Exception {
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+ ContentManagerLocal contentMgr = LookupUtil.getContentManager();
+
+ List<PackageType> packageTypes = contentMgr.findPackageTypes(subjectMgr.getOverlord(), resourceTypeName,
+ pluginName);
+ Package pkg = new Package(packageName, packageTypes.get(0));
+
+ contentMgr.persistPackage(pkg);
+ }
+
+ void createResourceGroup(String groupName, String resourceTypeName, String pluginName) throws Exception {
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+ ResourceTypeManagerLocal resourceTypeMgr = LookupUtil.getResourceTypeManager();
+ ResourceGroupManagerLocal resourceGroupMgr = LookupUtil.getResourceGroupManager();
+
+ ResourceType resourceType = resourceTypeMgr.getResourceTypeByNameAndPlugin(resourceTypeName, pluginName);
+
+ assertNotNull("Cannot create resource group. Unable to find resource type for [name: " + resourceTypeName
+ + ", plugin: " + pluginName + "]", resourceType);
+
+ ResourceGroup resourceGroup = new ResourceGroup(groupName, resourceType);
+ resourceGroupMgr.createResourceGroup(subjectMgr.getOverlord(), resourceGroup);
+ }
+
+ void createAlertTemplate(String name, String resourceTypeName, String pluginName) throws Exception {
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+ ResourceTypeManagerLocal resourceTypeMgr = LookupUtil.getResourceTypeManager();
+ AlertTemplateManagerLocal alertTemplateMgr = LookupUtil.getAlertTemplateManager();
+
+ ResourceType resourceType = resourceTypeMgr.getResourceTypeByNameAndPlugin(resourceTypeName, pluginName);
+ assertNotNull("Cannot create alert template. Unable to find resource type for [name: " + resourceTypeName
+ + ", plugin: " + pluginName + "]", resourceType);
+
+ AlertDefinition alertDef = new AlertDefinition();
+ alertDef.setName(name);
+ alertDef.setPriority(AlertPriority.MEDIUM);
+ alertDef.setResourceType(resourceType);
+ alertDef.setConditionExpression(BooleanExpression.ALL);
+ alertDef.setAlertDampening(new AlertDampening(AlertDampening.Category.NONE));
+ alertDef.setRecoveryId(0);
+
+ alertTemplateMgr.createAlertTemplate(subjectMgr.getOverlord(), alertDef, resourceType.getId());
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/PluginDescriptorValidationTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/PluginDescriptorValidationTest.java
new file mode 100644
index 0000000..66d87e6
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/PluginDescriptorValidationTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.enterprise.server.resource.metadata.test;
+
+import java.io.File;
+import java.net.URL;
+
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.util.ValidationEventCollector;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.descriptor.DescriptorPackages;
+
+/**
+ * Try to validate the rhq-plugin.xml plugin descriptors
+ *
+ * @author Heiko W. Rupp
+ * TODO get the plugins dynamically - see comment in {@link #testPluginDescriptors()}
+ */
+public class PluginDescriptorValidationTest extends UpdatePluginMetadataTestBase {
+ // we stand in modules/enterprise/jar
+ String BASE = "../../../plugins/";
+ String EXT = "/src/main/resources/META-INF/rhq-plugin.xml";
+
+ /**
+ * Plugins we want to test. Note that they need to appear here in the correct dependency order.
+ */
+ String[] plugins = { "database", "postgres", "platform", "jmx", "rhq-agent", "apache" };
+
+ @BeforeMethod
+ @Override
+ protected void init() {
+ super.init();
+ }
+
+ /**
+ * Load all the plugin descriptors thus running them through the XML Schema validation.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPluginDescriptors() throws Exception {
+ int failed = 0;
+
+ // TODO: dynamically determine the list of plugins and their sort order.
+ // first part could be done by a simple filesystem walk in BASE, picking up
+ // the directories. The second part is harder. Perhaps take some logik from
+ // the plugin deployer code.
+
+ getTransactionManager().begin();
+ try {
+ for (String plugin : plugins) {
+ String descriptor = BASE + plugin + EXT;
+ try {
+ System.out.println("--- Testing plugin [" + plugin + "] ---");
+ File f = new File(descriptor);
+ descriptor = f.getCanonicalPath();
+
+ long then = System.currentTimeMillis();
+ validatePluginDescriptor(descriptor);
+ long now = System.currentTimeMillis();
+ System.out.println(" Validation took " + (now - then) + "ms");
+ } catch (Exception e) {
+ failed++;
+ System.out.println("!!! Validation of " + descriptor + " failed: " + e.getMessage() + " !!!");
+ }
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+
+ if (failed > 0) {
+ String msg = "Vaildation of [" + failed + "/" + plugins.length + "] descriptors failed";
+ System.err.println(msg);
+ throw new Exception(msg);
+ } else {
+ System.out.println("All tests passed");
+ }
+ }
+
+ /**
+ * Load the descriptor file from the file system, umarshalls and thus parses it.
+ */
+ public void validatePluginDescriptor(String descriptorFile) throws Exception {
+ String PROTO = "file:///";
+ URL descriptorUrl = new URL(PROTO + descriptorFile);
+
+ JAXBContext jaxbContext = JAXBContext.newInstance(DescriptorPackages.PC_PLUGIN);
+ URL pluginSchemaURL = getClass().getClassLoader().getResource("rhq-plugin.xsd");
+ Schema pluginSchema = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(pluginSchemaURL);
+
+ Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+ ValidationEventCollector vec = new ValidationEventCollector();
+ unmarshaller.setEventHandler(vec);
+ unmarshaller.setSchema(pluginSchema);
+ unmarshaller.unmarshal(descriptorUrl.openStream());
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/SubcategoryTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/SubcategoryTest.java
new file mode 100644
index 0000000..aa3c616
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/SubcategoryTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.enterprise.server.resource.metadata.test;
+
+import org.testng.annotations.Test;
+
+/**
+ * Various testing around subCategories
+ *
+ * @author Heiko W. Rupp
+ */
+public class SubcategoryTest extends UpdatePluginMetadataTestBase {
+
+ @Override
+ protected String getSubsystemDirectory() {
+ return "resource";
+ }
+
+ @Test
+ public void testAddResourcTypeWithKnownSubCategory() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ registerPlugin("test-subcategories.xml");
+ registerPlugin("test-subcategories3.xml");
+ } finally {
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testAddResourcTypeWithKnownSubCategory");
+ }
+ }
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java
new file mode 100644
index 0000000..4714f57
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java
@@ -0,0 +1,1302 @@
+/*
+ * 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.enterprise.server.resource.metadata.test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.transaction.Status;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
+import org.rhq.core.domain.configuration.definition.PropertyDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionEnumeration;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.configuration.definition.PropertyGroupDefinition;
+import org.rhq.core.domain.configuration.definition.PropertySimpleType;
+import org.rhq.core.domain.configuration.definition.constraint.Constraint;
+import org.rhq.core.domain.configuration.definition.constraint.FloatRangeConstraint;
+import org.rhq.core.domain.configuration.definition.constraint.IntegerRangeConstraint;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+
+/**
+ * Tests the updating of persisted ResourceTypes' resource and plugin ConfigurationDefinitions, which is essentially
+ * handled by {@link org.rhq.enterprise.server.configuration.metadata.ConfigurationMetadataManagerBean}.
+ *
+ * @author Heiko Rupp
+ */
+public class UpdateConfigurationSubsystemTest extends UpdatePluginMetadataTestBase {
+
+ private static final boolean ENABLED = true;
+
+ @Override
+ protected String getSubsystemDirectory() {
+ return "configuration";
+ }
+
+ /**
+ * Test updating of plugin configs.
+ *
+ * @throws Exception
+ */
+ @Test(enabled = ENABLED)
+ public void testUpdatePluginConfig() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ registerPlugin("update5-v1_0.xml", null);
+ ResourceType platform1 = getResourceType("myPlatform5");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform1 = em.find(ResourceType.class, platform1.getId());
+
+ Set<ResourceType> servers = platform1.getChildResourceTypes();
+ assert servers.size() == 1 : "Expected to find 1 server in v1, but got " + servers.size();
+ ResourceType server1 = servers.iterator().next();
+ ConfigurationDefinition cDef = server1.getPluginConfigurationDefinition();
+ assert cDef != null : "Expected to find a PluginConfigurationDefinition in v1";
+ List<PropertyGroupDefinition> groups1 = cDef.getGroupDefinitions();
+ assert groups1.size() == 3 : "Expected to find 3 groups in v1, but got " + groups1.size();
+ int found = 0;
+ for (PropertyGroupDefinition pgd : groups1) {
+ if (containedIn(pgd.getName(), new String[] { "connection", "tuning", "control" })) {
+ found++;
+ }
+
+ if (pgd.getName().equals("tuning")) {
+ List<PropertyDefinition> pdl = cDef.getPropertiesInGroup("tuning");
+ for (PropertyDefinition pd : pdl) {
+ if (pd.getName().equals("rampDownTime")) {
+ assert pd.isRequired() == false : "rampDownTime is not required in 'tuning' in v1";
+ assert pd.isReadOnly() == true : "rampDownTime should be r/o in v1";
+ assert pd.isSummary() == false : "rampDownTime should not be summary in v1";
+ }
+ }
+ // TODO more checking per group
+ }
+ }
+
+ assert found == 3 : "Expected to find 3 specially named control groups in v1, but only found " + found;
+ // TODO check more stuff here
+ getTransactionManager().rollback();
+
+ System.out.println("-------- done with v1");
+
+ /*
+ * Now deploy version 2
+ */
+ registerPlugin("update5-v2_0.xml", null);
+ ResourceType platform2 = getResourceType("myPlatform5");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform2 = em.find(ResourceType.class, platform2.getId());
+
+ Set<ResourceType> servers2 = platform2.getChildResourceTypes();
+ assert servers2.size() == 1 : "Expected to find 1 server in v2, but got " + servers2.size();
+ ResourceType server2 = servers2.iterator().next();
+ ConfigurationDefinition cDef2 = server2.getPluginConfigurationDefinition();
+ assert cDef2 != null : "Expected to find a PluginConfigurationDefinition in v2";
+ List<PropertyGroupDefinition> groups2 = cDef2.getGroupDefinitions();
+ assert groups2.size() == 3 : "Expected to find 3 groups in v2, but got " + groups2.size();
+ found = 0;
+ for (PropertyGroupDefinition pgd : groups2) {
+ if (pgd.getName().equals("fun")) {
+ found++;
+ List<PropertyDefinition> pdl = cDef2.getPropertiesInGroup("fun");
+ assert pdl.size() == 1 : "Expected to find 1 property for group 'fun' in v2, but got " + pdl.size();
+ PropertyDefinition pd = pdl.get(0);
+ assert pd.getName().equals("funRampUpTime") : "Expected to find the property 'rampUpTime', but got "
+ + pd.getName();
+ } else if (pgd.getName().equals("tuning")) {
+ found++;
+ List<PropertyDefinition> pdl = cDef2.getPropertiesInGroup("tuning");
+ assert pdl.size() == 3 : "Expected 3 properties in group 'tuning' in v2, but got " + pdl.size();
+ for (PropertyDefinition pd : pdl) {
+ if (pd.getName().equals("rampDownTime")) {
+ assert pd.isRequired() == true : "rampDownTime is now required in 'tuning' in v2";
+ assert pd.isReadOnly() == false : "rampDownTime should be r/w in v2";
+ assert pd.isSummary() == true : "rampDownTime should be summary in v2";
+ }
+ }
+ } else if (pgd.getName().equals("control")) {
+ found++;
+ } else {
+ // assert true==false : "Unknown definition in v2: " + pgd.getName();
+ System.out.println("Unknown definition in v2: " + pgd.getName());
+ }
+ // TODO more checking per group
+ }
+
+ assert found == 3 : "Expected to find 3 specially named control groups in v2, but only found " + found;
+ // TODO check resource-config as well
+ getTransactionManager().rollback();
+
+ System.out.println("-------- done with v2");
+
+ // TODO check changing back
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testAddDeleteDefaultTemplate");
+ }
+ }
+ }
+
+ // This test fails but I'm not sure why. It may be a bad test or it may be a real problem. It should
+ // be investigated and either enabled or deleted.
+ @Test(enabled = false)
+ public void testBZ_573034() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ // register plugin
+ String version1 = "1.0";
+ String version2 = "2.0";
+
+ registerPlugin("BZ_573034_v1.xml", version1);
+
+ // create resource with plugin configuration
+ ResourceType testServerResourceType = getResourceType("TestServer");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ testServerResourceType = em.find(ResourceType.class, testServerResourceType.getId());
+ ConfigurationDefinition pluginConfigurationDef = testServerResourceType.getPluginConfigurationDefinition();
+ PropertyDefinition testPropertyDef = pluginConfigurationDef.getPropertyDefinitionSimple("testProperty");
+ Configuration pluginConfiguration = null;
+ int pluginConfigurationId = 0;
+ try {
+ assertNotNull(
+ "Expected plugin configuration definition to have a property definition for 'testProperty'",
+ testPropertyDef);
+
+ String resourceKey = testServerResourceType.getName() + System.currentTimeMillis();
+ Resource testResource = new Resource(resourceKey, resourceKey, testServerResourceType);
+ testResource.setUuid("" + new Random().nextInt());
+ em.persist(testResource);
+ em.flush();
+
+ setUpAgent(em, testResource);
+
+ testResource = em.find(Resource.class, testResource.getId());
+ pluginConfigurationId = testResource.getPluginConfiguration().getId();
+
+ pluginConfiguration = em.find(Configuration.class, pluginConfigurationId);
+ PropertySimple testProperty = pluginConfiguration.getSimple("testProperty");
+
+ assertNull(
+ "Did not expect to find a value for 'testProperty' since a value has not been supplied for it yet",
+ testProperty);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ getTransactionManager().rollback();
+ fail("testBZ_573034:" + e);
+ }
+
+ // register new version of plugin that specifies new plugin configuration property having a default value
+ registerPlugin("BZ_573034_v2.xml", version2);
+
+ // verify existing resource has its plugin configuration updated with new property having default value
+ testServerResourceType = getResourceType("TestServer");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ testServerResourceType = em.find(ResourceType.class, testServerResourceType.getId());
+
+ pluginConfigurationDef = testServerResourceType.getPluginConfigurationDefinition();
+ PropertyDefinition testPropertyWithDefaultDef = pluginConfigurationDef
+ .getPropertyDefinitionSimple("testPropertyWithDefault");
+
+ assertNotNull(
+ "Expected updated plugin configuration definition to define the property 'testPropertyWithDefault'",
+ testPropertyWithDefaultDef);
+
+ pluginConfiguration = em.find(Configuration.class, pluginConfigurationId);
+ PropertySimple testPropertyWithDefault = pluginConfiguration.getSimple("testPropertyWithDefault");
+
+ assertNotNull(
+ "Expected to find the property 'testPropertyWithDefault' in the updated plugin configuration",
+ testPropertyWithDefault);
+ assertEquals("Expected default value to be set", "default", testPropertyWithDefault.getStringValue());
+
+ getTransactionManager().rollback();
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testResourceConfiguration");
+ }
+ }
+ }
+
+ /**
+ * Tests the behaviour wrt <resource-configuration> entries
+ *
+ * @throws Exception
+ */
+ @Test(enabled = ENABLED)
+ public void testResourceConfiguration() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ registerPlugin("update5-v1_0.xml", "1");
+ ResourceType platform1 = getResourceType("myPlatform5");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform1 = em.find(ResourceType.class, platform1.getId());
+
+ Set<ResourceType> servers = platform1.getChildResourceTypes();
+ assert servers.size() == 1 : "Expected to find 1 server in v1, but got " + servers.size();
+ ResourceType server1 = servers.iterator().next();
+ ConfigurationDefinition def1 = server1.getResourceConfigurationDefinition();
+ List<PropertyDefinition> cpdl = def1.getNonGroupedProperties();
+
+ assert cpdl.size() == 3 : "Did not find 3 properties in <resource-configuration> in v1 but " + cpdl.size();
+ for (PropertyDefinition pd : cpdl) {
+ if (pd.getName().equals("jnpPort")) {
+ assert pd instanceof PropertyDefinitionSimple : "jnpPort is no simple-property in v1";
+ PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pd;
+
+ List<PropertyDefinitionEnumeration> pdel = pds.getEnumeratedValues();
+ assert pdel.size() == 3 : "jnpPort did not have 3 options in v1, but " + pdel.size();
+ int found = 0;
+ for (PropertyDefinitionEnumeration pde : pdel) {
+ if (containedIn(pde.getName(), new String[] { "option1", "option2", "option3" })) {
+ found++;
+ }
+ }
+
+ assert found == 3 : "Did not find the three expected options in v1";
+ } else if (pd.getName().equals("secureJnpPort")) {
+ assert pd instanceof PropertyDefinitionSimple : "secureJnpPort is no simple-property in v1";
+ PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pd;
+ assert pds.getType() == PropertySimpleType.INTEGER : "Type of secureJnpPort is not integer in v1";
+ Set<Constraint> constraints = pds.getConstraints();
+ assert constraints.size() == 4 : "Did not find 4 constraints for secureJnpPort in v1, but "
+ + constraints.size();
+ }
+ }
+ getTransactionManager().rollback();
+
+ /*
+ * Now check the changed plugin
+ */
+ registerPlugin("update5-v2_0.xml", "2");
+ ResourceType platform2 = getResourceType("myPlatform5");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform2 = em.find(ResourceType.class, platform2.getId());
+
+ Set<ResourceType> servers2 = platform2.getChildResourceTypes();
+ assert servers2.size() == 1 : "Expected to find 1 server in v2, but got " + servers2.size();
+ ResourceType server2 = servers2.iterator().next();
+ ConfigurationDefinition def2 = server2.getResourceConfigurationDefinition();
+ def2 = getEntityManager().find(ConfigurationDefinition.class, def2.getId());
+ List<PropertyDefinition> cpdl2 = def2.getNonGroupedProperties();
+ assert cpdl2.size() == 3 : "Did not find 3 properties in <resource-configuration> in v2 but "
+ + cpdl2.size();
+ int found = 0;
+ for (PropertyDefinition pd : cpdl2) {
+ if (containedIn(pd.getName(), new String[] { "jnpPort", "secureJnpPort", "memorySize" })) {
+ found++;
+ }
+ }
+
+ assert found == 3 : "Did not find the 3 specific properties in v2";
+ for (PropertyDefinition pd : cpdl2) {
+ if (pd.getName().equals("jnpPort")) {
+ if (pd instanceof PropertyDefinitionSimple) {
+ PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pd;
+
+ List<PropertyDefinitionEnumeration> pdel = pds.getEnumeratedValues();
+
+ /*
+ * TODO there is a strange effect where pdel has also "null" elements in it, that were not
+ * present at the time the new enumeration has been computed in the ResourceMetadataManager.
+ * That is why I am here first removing the nulls and then do the assertion
+ */
+ for (int i = pdel.size() - 1; i >= 0; i--) {
+ if (pdel.get(i) == null) {
+ pdel.remove(i);
+ }
+ }
+
+ assert pdel.size() == 4 : "jnpPort did not have 4 options in v2, but " + pdel.size();
+ found = 0;
+ for (PropertyDefinitionEnumeration pde : pdel) {
+ if (containedIn(pde.getName(), new String[] { "option2", "option3", "newOption4",
+ "newOption5" })) {
+ found++;
+ }
+
+ if (pde.getName().equals("option3")) {
+ assert pde.getValue().equals("changed") : "Value for option 'option3' did not change in v2";
+ }
+ }
+
+ assert found == 4 : "Did not find the four expected options in v2 ";
+ }
+ } else if (pd.getName().equals("secureJnpPort")) {
+ assert pd instanceof PropertyDefinitionSimple : "secureJnpPort is no simple-property in v2";
+ PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pd;
+ Set<Constraint> constraints = pds.getConstraints();
+ assert constraints.size() == 3 : "Did not find 3 constraints for secureJnpPort in v2, but "
+ + constraints.size();
+ }
+ }
+ getTransactionManager().rollback();
+
+ /*
+ * And now back to the first version
+ */
+
+ registerPlugin("update5-v1_0.xml", "3");
+ platform1 = getResourceType("myPlatform5");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform1 = em.find(ResourceType.class, platform1.getId());
+
+ servers = platform1.getChildResourceTypes();
+ assert servers.size() == 1 : "Expected to find 1 server in v1, but got " + servers.size();
+ ResourceType server3 = servers.iterator().next();
+ ConfigurationDefinition def3 = server3.getResourceConfigurationDefinition();
+ List<PropertyDefinition> cpdl3 = def3.getNonGroupedProperties();
+
+ assert cpdl3.size() == 3 : "Did not find 3 properties in <resource-configuration> in v3 again but "
+ + cpdl3.size();
+ for (PropertyDefinition pd : cpdl3) {
+ if (pd.getName().equals("jnpPort")) {
+ if (pd instanceof PropertyDefinitionSimple) {
+ PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pd;
+
+ List<PropertyDefinitionEnumeration> pdel = pds.getEnumeratedValues();
+
+ /*
+ * TODO there is a strange effect where pdel has also "null" elements in it, that were not
+ * present at the time the new enumeration has been computed in the ResourceMetadataManager.
+ * That is why I am here first removing the nulls and then do the assertion
+ */
+ for (int i = pdel.size() - 1; i >= 0; i--) {
+ if (pdel.get(i) == null) {
+ pdel.remove(i);
+ }
+ }
+
+ assert pdel.size() == 3 : "jnpPort did not have 3 options in v3, but " + pdel.size();
+ found = 0;
+ for (PropertyDefinitionEnumeration pde : pdel) {
+ if (containedIn(pde.getName(), new String[] { "option1", "option2", "option3" })) {
+ found++;
+ }
+ }
+
+ assert found == 3 : "Did not find the three expected options in v3";
+ }
+ }
+ }
+ getTransactionManager().rollback();
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testResourceConfiguration");
+ }
+ }
+ }
+
+ /**
+ * Test for storing of back links from Constraint to PropertyDefinitionSimple. See JBNADM-1587
+ *
+ * @throws Exception
+ */
+ @SuppressWarnings("deprecation")
+ @Test(enabled = ENABLED)
+ public void testConstraint() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ registerPlugin("constraint.xml");
+ ResourceType platform = getResourceType("constraintPlatform");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ ConfigurationDefinition config = platform.getResourceConfigurationDefinition();
+ PropertyDefinitionSimple propDef = config.getPropertyDefinitionSimple("secureJnpPort");
+ Set<Constraint> constraints = propDef.getConstraints();
+ assert constraints.size() == 4 : "Expected to get 4 constraints, but got " + constraints.size();
+
+ assert propDef.getDefaultValue().equals("1234");
+ getTransactionManager().rollback();
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testConstraint");
+ }
+ }
+ }
+
+ /**
+ * Test for storing of back links from Constraint to PropertyDefinitionSimple. See JBNADM-1587
+ *
+ * @throws Exception
+ */
+ @SuppressWarnings("deprecation")
+ @Test(enabled = ENABLED)
+ public void testConstraint2() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ registerPlugin("constraint.xml");
+ ResourceType platform = getResourceType("constraintPlatform");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ ConfigurationDefinition config = platform.getResourceConfigurationDefinition();
+ Map<String, PropertyDefinition> propDefMap = config.getPropertyDefinitions();
+ PropertyDefinitionSimple propDef = (PropertyDefinitionSimple) propDefMap.get("secureJnpPort");
+ Set<Constraint> constraints = propDef.getConstraints();
+ assert constraints.size() == 4 : "Expected to get 4 constraints, but got " + constraints.size();
+
+ assert propDef.getDefaultValue().equals("1234");
+ getTransactionManager().rollback();
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testConstraint2");
+ }
+ }
+ }
+
+ /**
+ * Test for setting min/max in contraints. See JBNADM-1596 See JBNADM-1597
+ *
+ * @throws Exception
+ */
+ @Test(enabled = ENABLED)
+ public void testConstraintMinMax() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ registerPlugin("constraintMinMax.xml");
+ ResourceType platform = getResourceType("constraintPlatform");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ ConfigurationDefinition config = platform.getResourceConfigurationDefinition();
+ PropertyDefinitionSimple propDef = config.getPropertyDefinitionSimple("secureJnpPort");
+ Set<Constraint> constraints = propDef.getConstraints();
+ assert constraints.size() == 2 : "Expected to get 2 constraints, but got " + constraints.size();
+ for (Constraint co : constraints) {
+ if (co instanceof IntegerRangeConstraint) {
+ IntegerRangeConstraint irc = (IntegerRangeConstraint) co;
+ assert irc.getMinimum() == 5; // TODO change when JBNADM-1597 is being worked on
+ assert irc.getMaximum() == 0;
+ } else if (co instanceof FloatRangeConstraint) {
+ FloatRangeConstraint frc = (FloatRangeConstraint) co;
+ assert frc != null;
+ assert frc.getMaximum() == 0.0; // TODO change when JBNADM-1597 is being worked on
+ assert frc.getMinimum() == 5.0;
+ }
+ }
+ getTransactionManager().rollback();
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testConstraint2");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testListOfLists() throws Exception {
+ try {
+ // extra block for variable scoping purposes
+ registerPlugin("propertyList-v1.xml");
+ ResourceType platform = getResourceType("myPlatform6");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+ ConfigurationDefinition cd = platform.getResourceConfigurationDefinition();
+ Map<String, PropertyDefinition> propDefs = cd.getPropertyDefinitions();
+ assert propDefs.size() == 4 : "Expected to see 4 <list-property>s in v1, but got " + propDefs.size();
+ for (PropertyDefinition def : propDefs.values()) {
+ assert def instanceof PropertyDefinitionList : "PropertyDefinition " + def.getName()
+ + " is no list-property in v1";
+ PropertyDefinitionList pdl = (PropertyDefinitionList) def;
+ PropertyDefinition member = pdl.getMemberDefinition();
+
+ if (pdl.getName().equals("myList1")) {
+ assert pdl.getDescription().equals("Just a simple list");
+ assert member instanceof PropertyDefinitionSimple : "Expected the member of myList1 to be a simple property in v1";
+ PropertyDefinitionSimple pds = (PropertyDefinitionSimple) member;
+ assert pds.getName().equals("foo");
+ } else if (pdl.getName().equals("myList2")) {
+ assert member instanceof PropertyDefinitionList : "Expected the member of myList2 to be a list property in v1";
+ } else if (pdl.getName().equals("myList3")) {
+ assert member instanceof PropertyDefinitionSimple : "Expected the member of myList3 to be a simple property in v1";
+ PropertyDefinitionSimple pds = (PropertyDefinitionSimple) member;
+ assert pds.getName().equals("baz");
+ } else if (pdl.getName().equals("rec1")) {
+ assert member instanceof PropertyDefinitionList : "Expected the member of rc1 to be a list property in v1";
+ PropertyDefinitionList pdl2 = (PropertyDefinitionList) member;
+
+ // TODO check min/max for the lists on the way. Commented out. See JBNADM-1595
+ assert pdl2.getName().equals("rec2");
+
+ // assert pdl2.getMin()==2 : "Expected rec2:min to be 2, but it was " + pdl2.getMin();
+ // assert pdl2.getMax()==20;
+ pdl2 = (PropertyDefinitionList) pdl2.getMemberDefinition();
+ assert pdl2.getName().equals("rec3");
+
+ // assert pdl2.getMin()==3;
+ // assert pdl2.getMax()==30;
+ pdl2 = (PropertyDefinitionList) pdl2.getMemberDefinition();
+ assert pdl2.getName().equals("rec4");
+
+ // assert pdl2.getMin()==4;
+ // assert pdl2.getMax()==40;
+ assert pdl2.getMemberDefinition() instanceof PropertyDefinitionSimple;
+ PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pdl2.getMemberDefinition();
+ assert pds.getName().equals("rec5");
+ assert pds.getDescription().equals("Deeply nested");
+ List<PropertyDefinitionEnumeration> options = pds.getEnumeratedValues();
+ assert options.size() == 4;
+ int found = 0;
+ String[] optionVals = new String[] { "a", "b", "c", "d" };
+ for (PropertyDefinitionEnumeration option : options) {
+ if (containedIn(option.getValue(), optionVals)) {
+ found++;
+ }
+ }
+
+ assert found == 4;
+ Set<Constraint> constraints = pds.getConstraints();
+ assert constraints.size() == 1;
+ } else {
+ assert true == false : "Unknown list-definition in v1: " + pdl.getName();
+ }
+ }
+ getTransactionManager().rollback();
+
+ /*
+ * Deploy v2 of the plugin
+ */
+ registerPlugin("propertyList-v2.xml");
+ platform = getResourceType("myPlatform6");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ cd = platform.getResourceConfigurationDefinition();
+ propDefs = cd.getPropertyDefinitions();
+ assert propDefs.size() == 4 : "Expected to see 4 <list-property>s in v2, but got " + propDefs.size();
+ for (PropertyDefinition def : propDefs.values()) {
+ assert def instanceof PropertyDefinitionList : "PropertyDefinition " + def.getName()
+ + " is no list-property in v2";
+ PropertyDefinitionList pdl = (PropertyDefinitionList) def;
+ PropertyDefinition member = pdl.getMemberDefinition();
+
+ if (pdl.getName().equals("myList2")) {
+ assert member instanceof PropertyDefinitionList : "Expected the member of myList2 to be a list property in v2";
+ } else if (pdl.getName().equals("myList3")) {
+ assert member instanceof PropertyDefinitionList : "Expected the member of myList3 to be a list property in v2";
+ PropertyDefinitionList pds = (PropertyDefinitionList) member;
+ assert pds.getName().equals("baz");
+ assert pds.getDescription().equals("myList3:baz");
+ assert pds.getMemberDefinition() instanceof PropertyDefinitionSimple : "Expected the member of list3:baz to be a simple property in v2";
+ } else if (pdl.getName().equals("myList4")) {
+ assert pdl.getDescription().equals("Just a simple list");
+ assert member instanceof PropertyDefinitionSimple : "Expected the member of myList4 to be a simple property in v2";
+ PropertyDefinitionSimple pds = (PropertyDefinitionSimple) member;
+ assert pds.getName().equals("foo");
+ } else if (pdl.getName().equals("rec1")) {
+ assert member instanceof PropertyDefinitionList : "Expected the member of rec1 to be a list property in v2";
+ PropertyDefinitionList pdl2 = (PropertyDefinitionList) member;
+ assert pdl2.getName().equals("rec2");
+
+ /*
+ * PropertyDefinitionList.getMin()/getMax() are commented out. See JBNADM1595
+ */
+
+ // assert pdl2.getMin()==12 : "Expected rec2:min to be 12, but it was " + pdl2.getMin();
+ // assert pdl2.getMax()==200;
+ pdl2 = (PropertyDefinitionList) pdl2.getMemberDefinition();
+ assert pdl2.getName().equals("rec3+");
+
+ // assert pdl2.getMin()==13;
+ // assert pdl2.getMax()==300;
+ pdl2 = (PropertyDefinitionList) pdl2.getMemberDefinition();
+ assert pdl2.getName().equals("rec4");
+
+ // assert pdl2.getMin()==14;
+ // assert pdl2.getMax()==400;
+ assert pdl2.getMemberDefinition() instanceof PropertyDefinitionSimple;
+ PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pdl2.getMemberDefinition();
+ assert pds.getName().equals("rec5");
+ assert pds.getDescription().equals("Nested deeply");
+ List<PropertyDefinitionEnumeration> options = pds.getEnumeratedValues();
+ assert options.size() == 5;
+ int found = 0;
+ String[] optionVals = new String[] { "b", "c", "d", "x", "z" };
+ for (PropertyDefinitionEnumeration option : options) {
+ if (containedIn(option.getValue(), optionVals)) {
+ found++;
+ }
+ }
+
+ assert found == optionVals.length;
+ Set<Constraint> constraints = pds.getConstraints();
+ assert constraints.size() == 2;
+ for (Constraint constraint : constraints) {
+ if (constraint instanceof IntegerRangeConstraint) {
+ IntegerRangeConstraint irc = (IntegerRangeConstraint) constraint;
+ assert irc != null : "Integer-constraint was null, but should not be";
+ // See JBNADM-1596/97
+ assert irc.getDetails().equals("-2#10");
+ // TODO (ips, 3/31/10): The below is a workaround for IntegerRangeConstraint.onLoad() not being called by Hibernate.
+ irc.setDetails(irc.getDetails());
+ assert irc.getMaximum() == 10;
+ assert irc.getMinimum() == -2;
+ } else if (constraint instanceof FloatRangeConstraint) {
+ FloatRangeConstraint frc = (FloatRangeConstraint) constraint;
+ assert frc != null : "Float-constraint was null, but should not be";
+ // See JBNADM-1596/97
+ assert frc.getDetails().equals("10.0#5.0");
+ // TODO (ips, 3/31/10): The below is a workaround for FloatRangeConstraint.onLoad() not being called by Hibernate.
+ frc.setDetails(frc.getDetails());
+ assert frc.getMinimum() == 10; // TODO change when JBNADM-1597 is being worked on
+ assert frc.getMaximum() == 5;
+
+ } else {
+ assert true == false : "Unknown constraint type encountered";
+ }
+ }
+ } else {
+ assert true == false : "Unknown list-definition in v2: " + pdl.getName();
+ }
+ }
+ getTransactionManager().rollback();
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testListOfLists");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testListPropertyMinMax() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ registerPlugin("propertyList-simple.xml");
+ ResourceType platform = getResourceType("myPlatform");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ ConfigurationDefinition cd = platform.getResourceConfigurationDefinition();
+ Map<String, PropertyDefinition> properties = cd.getPropertyDefinitions();
+ PropertyDefinitionList a = (PropertyDefinitionList) properties.get("a");
+ assert a.getDescription().equals("Yada !") : "Expected the description to be 'Yada !', but it was "
+ + a.getDescription();
+
+ // The next two are marked as @Transient in PropertyDefinitonList
+ // See JBNADM-1595
+ // assert a.getMax()==6 : "Expected the max to be 6 but it was " + a.getMax();
+ // assert a.getMin()==4 : "Expected the min to be 4 but it was " + a.getMin();
+
+ getTransactionManager().rollback();
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testListPropertyMinMax");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testMapProperty() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ { // extra block for variable scoping purposes
+ registerPlugin("propertyMap-v1.xml");
+ ResourceType platform = getResourceType("myPlatform7");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ ConfigurationDefinition cd = platform.getResourceConfigurationDefinition();
+ Map<String, PropertyDefinition> propDefs = cd.getPropertyDefinitions();
+ assert propDefs.size() == 5 : "Expected to find 5 properties in v1, but got " + propDefs.size();
+ int found = 0;
+ for (PropertyDefinition def : propDefs.values()) {
+ if (containedIn(def.getName(), new String[] { "map1", "map2", "map3", "map4", "map5" })) {
+ found++;
+ }
+
+ assert def instanceof PropertyDefinitionMap : "Not all properties are maps in v1";
+
+ if (def.getName().equals("map4")) {
+ PropertyDefinitionMap map = (PropertyDefinitionMap) def;
+ Map<String, PropertyDefinition> children = map.getMap();
+ assert children.size() == 1 : "Map4 should have 1 child";
+ children = map.getMap();
+ map = (PropertyDefinitionMap) children.get("map4:2");
+ assert map != null : "Child map4:2 not found";
+ children = map.getMap();
+ map = (PropertyDefinitionMap) children.get("map4:2:3");
+ assert map != null : "Child map4:2:3 not found";
+ children = map.getMap();
+ PropertyDefinitionSimple simple = (PropertyDefinitionSimple) children.get("simple");
+ assert simple != null : "Child simple not found";
+ }
+
+ if (def.getName().equals("map5")) {
+ PropertyDefinitionMap map = (PropertyDefinitionMap) def;
+ Map<String, PropertyDefinition> children = map.getMap();
+ assert children.size() == 1 : "Map4 should have 1 child";
+ children = map.getMap();
+ PropertyDefinitionSimple simple = (PropertyDefinitionSimple) children.get("hugo");
+ assert simple.getDescription().equals("foo");
+ }
+ }
+
+ assert found == 5 : "Did not find the 5 desired maps in v1";
+
+ getTransactionManager().rollback();
+ }
+
+ System.out.println("Done with v1");
+
+ /*
+ * Now deploy v2
+ */
+ { // extra block for variable scoping purposes
+ registerPlugin("propertyMap-v2.xml");
+ ResourceType platform = getResourceType("myPlatform7");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ ConfigurationDefinition cd = platform.getResourceConfigurationDefinition();
+ Map<String, PropertyDefinition> propDefs = cd.getPropertyDefinitions();
+ assert propDefs.size() == 5 : "Expected to find 5 properties in v2, but got " + propDefs.size();
+
+ int found = 0;
+ for (PropertyDefinition def : propDefs.values()) {
+ if (containedIn(def.getName(), new String[] { "map1", "map2", "map3", "map4", "map5" })) {
+ found++;
+ }
+
+ if (def.getName().equals("map1")) {
+ assert def instanceof PropertyDefinitionSimple : "Map 1 should be a simple-property in v2";
+ } else {
+ assert def instanceof PropertyDefinitionMap : "Not all properties are maps in v2";
+ }
+
+ if (def.getName().equals("map3")) {
+ assert def.isRequired() == false : "Map 3 should not be false in v2";
+ }
+
+ if (def.getName().equals("map4")) {
+ PropertyDefinitionMap map = (PropertyDefinitionMap) def;
+ Map<String, PropertyDefinition> children = map.getMap();
+ assert children.size() == 1 : "Map4 should have 1 child, but has " + children.size();
+ children = map.getMap();
+ map = (PropertyDefinitionMap) children.get("map4:2+");
+ assert map != null : "Child map4:2 not found";
+ children = map.getMap();
+ assert children.size() == 1 : "Map4:2 should have 1 child, but has " + children.size();
+ map = (PropertyDefinitionMap) children.get("map4:2:3");
+ assert map != null : "Child map4:2:3 not found";
+ children = map.getMap();
+ assert children.size() == 2 : "Map4:2:3 should have 1 child, but has " + children.size();
+ PropertyDefinitionList list = (PropertyDefinitionList) children.get("list");
+ assert list != null : "Child list not found";
+ PropertyDefinitionSimple simple = (PropertyDefinitionSimple) children.get("simple2");
+ assert simple != null : "Child simple2 not found";
+ }
+
+ if (def.getName().equals("map5")) {
+ PropertyDefinitionMap map = (PropertyDefinitionMap) def;
+ Map<String, PropertyDefinition> children = map.getMap();
+ assert children.size() == 1 : "Map5 should have 1 child";
+ children = map.getMap();
+ PropertyDefinitionSimple simple = (PropertyDefinitionSimple) children.get("hugo");
+ assert simple.getDescription().equals("bar") : "Map5:hugo should have 'bar' in v2";
+ }
+ }
+
+ assert found == 5 : "Did not find the 5 desired properties in v2, instead found " + found;
+
+ getTransactionManager().rollback();
+ }
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testMapProperty");
+ }
+ }
+ }
+
+ /**
+ * This test checks what happens if a property of one type checks its type into another one upon redeploy.
+ *
+ * @throws Exception
+ */
+ @Test(enabled = ENABLED)
+ public void testChangePropertyType() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ { // extra block for variable scoping purposes
+ registerPlugin("propertyChanging-v1.xml");
+ ResourceType platform = getResourceType("myPlatform7");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ ConfigurationDefinition cd = platform.getResourceConfigurationDefinition();
+ Map<String, PropertyDefinition> propDefs = cd.getPropertyDefinitions();
+ for (PropertyDefinition def : propDefs.values()) {
+ if (def.getName().equals("one")) {
+ assert def instanceof PropertyDefinitionMap;
+ } else if (def.getName().equals("two")) {
+ assert def instanceof PropertyDefinitionMap;
+ } else if (def.getName().equals("three")) {
+ assert def instanceof PropertyDefinitionList;
+ } else if (def.getName().equals("four")) {
+ assert def instanceof PropertyDefinitionList;
+ } else if (def.getName().equals("five")) {
+ assert def instanceof PropertyDefinitionSimple;
+ } else if (def.getName().equals("six")) {
+ assert def instanceof PropertyDefinitionSimple;
+ } else {
+ assert true == false : "Unknown definition : " + def.getName() + " in v1";
+ }
+ }
+ getTransactionManager().rollback();
+ }
+
+ /*
+ * Now deploy v2
+ */
+
+ { // extra block for variable scoping purposes
+ registerPlugin("propertyChanging-v2.xml");
+ ResourceType platform = getResourceType("myPlatform7");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ ConfigurationDefinition cd = platform.getResourceConfigurationDefinition();
+ Map<String, PropertyDefinition> propDefs = cd.getPropertyDefinitions();
+ for (PropertyDefinition def : propDefs.values()) {
+ if (def.getName().equals("one")) {
+ assert def instanceof PropertyDefinitionList : "Expected a list-property, but it was "
+ + def.getClass().getCanonicalName();
+ } else if (def.getName().equals("two")) {
+ assert def instanceof PropertyDefinitionSimple : "Expected a simple-property, but it was "
+ + def.getClass().getCanonicalName();
+ } else if (def.getName().equals("three")) {
+ assert def instanceof PropertyDefinitionMap : "Expected a map-property, but it was "
+ + def.getClass().getCanonicalName();
+ } else if (def.getName().equals("four")) {
+ assert def instanceof PropertyDefinitionSimple : "Expected a simple-property, but it was "
+ + def.getClass().getCanonicalName();
+ } else if (def.getName().equals("five")) {
+ assert def instanceof PropertyDefinitionMap : "Expected a map-property, but it was "
+ + def.getClass().getCanonicalName();
+ } else if (def.getName().equals("six")) {
+ assert def instanceof PropertyDefinitionList : "Expected a list-property, but it was "
+ + def.getClass().getCanonicalName();
+ } else {
+ assert true == false : "Unknown definition : " + def.getName() + " in v2";
+ }
+ }
+ getTransactionManager().rollback();
+ }
+
+ /*
+ * Now deploy v1 again
+ */{ // extra block for variable scoping purposes
+ registerPlugin("propertyChanging-v1.xml", "3.0"); // this is our 3rd version, but reuse v1
+ ResourceType platform = getResourceType("myPlatform7");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ ConfigurationDefinition cd = platform.getResourceConfigurationDefinition();
+ Map<String, PropertyDefinition> propDefs = cd.getPropertyDefinitions();
+ for (PropertyDefinition def : propDefs.values()) {
+ if (def.getName().equals("one")) {
+ assert def instanceof PropertyDefinitionMap : "Expected a map-property, but it was "
+ + def.getClass().getCanonicalName();
+ } else if (def.getName().equals("two")) {
+ assert def instanceof PropertyDefinitionMap : "Expected a map-property, but it was "
+ + def.getClass().getCanonicalName();
+ } else if (def.getName().equals("three")) {
+ assert def instanceof PropertyDefinitionList : "Expected a list-property, but it was "
+ + def.getClass().getCanonicalName();
+ } else if (def.getName().equals("four")) {
+ assert def instanceof PropertyDefinitionList : "Expected a list-property, but it was "
+ + def.getClass().getCanonicalName();
+ } else if (def.getName().equals("five")) {
+ assert def instanceof PropertyDefinitionSimple : "Expected a simple-property, but it was "
+ + def.getClass().getCanonicalName();
+ } else if (def.getName().equals("six")) {
+ assert def instanceof PropertyDefinitionSimple : "Expected a simple-property, but it was "
+ + def.getClass().getCanonicalName();
+ }
+ }
+ getTransactionManager().rollback();
+ }
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testChangePropertyType");
+ }
+ }
+
+ }
+
+ /*==================================== Resource Config Tests ======================================*/
+
+ @Test(enabled = ENABLED)
+ public void testGroupDeleted() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ registerPlugin("groupDeleted-v1.xml");
+ System.out.println("==> Done with v1");
+ registerPlugin("groupDeleted-v2.xml");
+ System.out.println("==> Done with v2");
+ registerPlugin("groupDeleted-v1.xml", "3.0");
+ System.out.println("==> Done with v1");
+ } finally {
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testGroupDeleted");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testGroupPropDeleted() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ registerPlugin("groupPropDeleted-v1.xml");
+ System.out.println("==> Done with v1");
+ registerPlugin("groupPropDeleted-v2.xml");
+ System.out.println("==> Done with v2");
+ registerPlugin("groupPropDeleted-v1.xml", "3.0");
+ System.out.println("==> Done with v1");
+ } finally {
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testGroupPropDeleted");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testGroupPropDeletedExt() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ registerPlugin("groupPropDeleted-v3.xml");
+ System.out.println("==> Done with v1");
+ registerPlugin("groupPropDeleted-v4.xml");
+ System.out.println("==> Done with v2");
+ registerPlugin("groupPropDeleted-v3.xml", "5.0");
+ System.out.println("==> Done with v1");
+ } finally {
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testGroupPropDeletedExt");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testGroupPropMoved() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ registerPlugin("groupPropMoved-v1.xml");
+ System.out.println("==> Done with v1");
+ registerPlugin("groupPropMoved-v2.xml");
+ System.out.println("==> Done with v2");
+ registerPlugin("groupPropMoved-v1.xml", "3.0");
+ System.out.println("==> Done with v1");
+ } finally {
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testGroupPropMoved");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testUpdateDefaultTemplate() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ registerPlugin("updateDefaultTemplate1.xml");
+ ResourceType platform = getResourceType("myPlatform7");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ ConfigurationDefinition cd = platform.getResourceConfigurationDefinition();
+ ConfigurationTemplate defaultTemplate = cd.getDefaultTemplate();
+ assert defaultTemplate != null;
+ Configuration config = defaultTemplate.getConfiguration();
+ PropertySimple ps = config.getSimple("six");
+ assert "foo".equals(ps.getStringValue()) : "Expected 'foo', but got " + ps.getStringValue();
+ getTransactionManager().rollback();
+
+ registerPlugin("updateDefaultTemplate2.xml");
+ platform = getResourceType("myPlatform7");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ cd = platform.getResourceConfigurationDefinition();
+ defaultTemplate = cd.getDefaultTemplate();
+ assert defaultTemplate != null;
+ config = defaultTemplate.getConfiguration();
+ ps = config.getSimple("six");
+ assert "bar".equals(ps.getStringValue()) : "Expected 'bar', but got " + ps.getStringValue();
+ getTransactionManager().rollback();
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testUpdateDefaultTemplate");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testAddDeleteTemplate() throws Exception {
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ ResourceType platform;
+ ConfigurationTemplate defaultTemplate;
+ ConfigurationDefinition cd;
+ Map<String, ConfigurationTemplate> templateMap;
+ ConfigurationTemplate template;
+ PropertySimple ps;
+
+ registerPlugin("addDeleteTemplate1.xml");
+ platform = getResourceType("myPlatform7");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ cd = platform.getResourceConfigurationDefinition();
+ defaultTemplate = cd.getDefaultTemplate();
+ assert defaultTemplate != null;
+ templateMap = cd.getTemplates();
+ assert templateMap.size() == 1 : "Expected only the 1 default template but got " + templateMap.size();
+ getTransactionManager().rollback();
+
+ System.out.println("Done with v1");
+
+ registerPlugin("addDeleteTemplate2.xml");
+ platform = getResourceType("myPlatform7");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+ cd = platform.getResourceConfigurationDefinition();
+ defaultTemplate = cd.getDefaultTemplate();
+ templateMap = cd.getTemplates();
+ assert defaultTemplate != null;
+ assert templateMap.size() == 2 : "Expected 2 templates but got " + templateMap;
+ template = templateMap.get("additional");
+ assert template != null;
+ ps = template.getConfiguration().getSimple("second_one");
+ assert ps.getStringValue().equals("Bart") : "Expected 'Bart', but got " + ps.getStringValue();
+ getTransactionManager().rollback();
+
+ System.out.println("Done with v2");
+
+ registerPlugin("addDeleteTemplate3.xml");
+ platform = getResourceType("myPlatform7");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+ cd = platform.getResourceConfigurationDefinition();
+ defaultTemplate = cd.getDefaultTemplate();
+ templateMap = cd.getTemplates();
+ assert defaultTemplate != null;
+ assert templateMap.size() == 2 : "Expected 2 templates but got " + templateMap;
+ template = templateMap.get("additional");
+ assert template != null;
+ ps = template.getConfiguration().getSimple("second_one");
+ assert ps.getStringValue().equals("Bart Simpson") : "Expected 'Bart Simpson', but got "
+ + ps.getStringValue();
+ getTransactionManager().rollback();
+
+ System.out.println("Done with v3");
+
+ registerPlugin("addDeleteTemplate1.xml", "4.0"); // this is our 4th version, but reuse v1
+ platform = getResourceType("myPlatform7");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+ cd = platform.getResourceConfigurationDefinition();
+ defaultTemplate = cd.getDefaultTemplate();
+ templateMap = cd.getTemplates();
+ assert defaultTemplate != null;
+ assert templateMap.size() == 1 : "Expected only the 1 default template but got " + templateMap;
+ getTransactionManager().rollback();
+
+ System.out.println("Done with v1(2)");
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testAddDeleteDefaultTemplate");
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateContentSubsystemTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateContentSubsystemTest.java
new file mode 100644
index 0000000..d0ee3ba
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateContentSubsystemTest.java
@@ -0,0 +1,26 @@
+/*
+ * 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.enterprise.server.resource.metadata.test;
+
+public class UpdateContentSubsystemTest extends UpdatePluginMetadataTestBase {
+ @Override
+ protected String getSubsystemDirectory() {
+ return "content";
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateEventsSubsystemTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateEventsSubsystemTest.java
new file mode 100644
index 0000000..08b313a
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateEventsSubsystemTest.java
@@ -0,0 +1,256 @@
+/*
+ * 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.enterprise.server.resource.metadata.test;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.transaction.Status;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.event.Event;
+import org.rhq.core.domain.event.EventDefinition;
+import org.rhq.core.domain.event.EventSeverity;
+import org.rhq.core.domain.event.EventSource;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.event.EventManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Note, plugins are registered in new transactions. for tests, this means
+ * you can't do everything in a trans and roll back at the end. You must clean up manually.
+ */
+public class UpdateEventsSubsystemTest extends UpdatePluginMetadataTestBase {
+
+ static final boolean ENABLED = true;
+
+ @Override
+ protected String getSubsystemDirectory() {
+ return "events";
+ }
+
+ @Test(enabled = ENABLED)
+ public void testCreateDeleteEvent() throws Exception {
+ System.out.println("= testCreateDeleteEvent");
+ try {
+ registerPlugin("event1-1.xml");
+ ResourceType platform = getResourceType("events");
+ assert platform != null;
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ Set<EventDefinition> eDefs = platform.getEventDefinitions();
+ assert eDefs != null;
+ assert eDefs.size() == 1;
+ EventDefinition hugo = eDefs.iterator().next();
+ assert hugo.getDescription().equals("One");
+ assert hugo.getDisplayName().equals("HugoOne");
+ getTransactionManager().rollback();
+
+ System.out.println("==> Done with v1");
+
+ registerPlugin("event1-2.xml");
+ platform = getResourceType("events");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ eDefs = platform.getEventDefinitions();
+ assert eDefs != null;
+ assert eDefs.size() == 2 : "Did not find 2 EventDefinitions, but " + eDefs.size();
+ Iterator<EventDefinition> eIter = eDefs.iterator();
+ while (eIter.hasNext()) {
+ EventDefinition def = eIter.next();
+ if (def.getName().equals("hugo")) {
+ assert def.getDescription().equals("Two") : "Expected 'Two', but got : " + def.getDescription();
+ assert def.getDisplayName().equals("HugoTwo");
+ }
+ }
+ getTransactionManager().rollback();
+
+ System.out.println("==> Done with v2");
+
+ registerPlugin("event1-1.xml", "3.0");
+ platform = getResourceType("events");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ eDefs = platform.getEventDefinitions();
+ assert eDefs != null;
+ assert eDefs.size() == 1 : "Did not find 1 EventDefinition, but " + eDefs.size();
+ hugo = eDefs.iterator().next();
+ assert hugo.getDescription().equals("One");
+ assert hugo.getDisplayName().equals("HugoOne");
+
+ System.out.println("==> Done with v1");
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testCreateDeleteEvent");
+ }
+ }
+ }
+
+ /**
+ * Simulate just redeploying the plugin with no change in descriptor.
+ * @throws Exception
+ */
+ @Test(enabled = ENABLED)
+ public void testNoOpChange() throws Exception {
+ System.out.println("= testNoOpChange");
+ try {
+ registerPlugin("event1-1.xml");
+ ResourceType platform = getResourceType("events");
+ assert platform != null;
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ Set<EventDefinition> eDefs = platform.getEventDefinitions();
+ assert eDefs != null;
+ assert eDefs.size() == 1;
+ EventDefinition hugo = eDefs.iterator().next();
+ assert hugo.getDescription().equals("One");
+ assert hugo.getDisplayName().equals("HugoOne");
+ getTransactionManager().rollback();
+
+ System.out.println("==> Done with v1");
+
+ registerPlugin("event1-1.xml", "2.0");
+ platform = getResourceType("events");
+ assert platform != null;
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ eDefs = platform.getEventDefinitions();
+ assert eDefs != null;
+ assert eDefs.size() == 1;
+ hugo = eDefs.iterator().next();
+ assert hugo.getDescription().equals("One");
+ assert hugo.getDisplayName().equals("HugoOne");
+
+ System.out.println("==> Done with v2");
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testNoOpChange");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testDeleteEventStuff() throws Exception {
+ System.out.println("= testDeleteEvent");
+ EventManagerLocal eventManager = LookupUtil.getEventManager();
+
+ ResourceType platform = null;
+ Resource testResource = null;
+ EntityManager entityManager = null;
+
+ // prepare basic stuff
+ try {
+ registerPlugin("event1-2.xml");
+ getTransactionManager().begin();
+ entityManager = getEntityManager();
+ platform = getResourceType("events");
+
+ testResource = new Resource("-test-", "-test resource", platform);
+ testResource.setUuid("" + new Random().nextInt());
+ entityManager.persist(testResource);
+ setUpAgent(entityManager, testResource);
+ getTransactionManager().commit();
+
+ getTransactionManager().begin();
+ entityManager = getEntityManager();
+ platform = entityManager.find(ResourceType.class, platform.getId());
+ testResource = entityManager.find(Resource.class, testResource.getId());
+ Set<EventDefinition> eDefs = platform.getEventDefinitions();
+ assert eDefs.size() == 2 : "Did not find the expected 2 eventDefinitions, but " + eDefs.size();
+ Iterator<EventDefinition> eIter = eDefs.iterator();
+ boolean found = false;
+ Map<EventSource, Set<Event>> events = new HashMap<EventSource, Set<Event>>(1);
+ while (eIter.hasNext()) {
+ EventDefinition def = eIter.next();
+ if (def.getName().equals("hans")) {
+ found = true;
+ // We got the definition that will vanish later, so attach some stuff to it
+ EventSource source = new EventSource("test location", def, testResource);
+ entityManager.persist(source);
+
+ Event ev = new Event(def.getName(), source.getLocation(), System.currentTimeMillis(),
+ EventSeverity.INFO, "This is a test");
+ Set<Event> evSet = new HashSet<Event>(1);
+ evSet.add(ev);
+ events.put(source, evSet);
+ }
+ }
+ assert found : "Hans was not found";
+ getTransactionManager().commit();
+ eventManager.addEventData(events);
+
+ /*
+ * --- done with the setup ---
+ * Now check that the event source + events are gone.
+ */
+ registerPlugin("event1-1.xml", "3.0");
+ platform = getResourceType("events");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ eDefs = platform.getEventDefinitions();
+ assert eDefs != null;
+ assert eDefs.size() == 1 : "Did not find 1 EventDefinition, but " + eDefs.size();
+ EventDefinition hugo = eDefs.iterator().next();
+ assert hugo.getDescription().equals("One");
+ assert hugo.getDisplayName().equals("HugoOne");
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testSingleSubCategoryCreate");
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateMeasurementSubsystemTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateMeasurementSubsystemTest.java
new file mode 100644
index 0000000..d30fbf6
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateMeasurementSubsystemTest.java
@@ -0,0 +1,352 @@
+/*
+ * 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.enterprise.server.resource.metadata.test;
+
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.criteria.ResourceCriteria;
+import org.rhq.core.domain.event.EventDefinition;
+import org.rhq.core.domain.measurement.DisplayType;
+import org.rhq.core.domain.measurement.MeasurementBaseline;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementSchedule;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+public class UpdateMeasurementSubsystemTest extends UpdatePluginMetadataTestBase {
+
+ static final boolean ENABLED = true;
+
+ @Override
+ protected String getSubsystemDirectory() {
+ return "measurement";
+ }
+
+ /**
+ * Simple test for the update of a plugin where a server has some metrics that get in the second version of the
+ * plugin added / changed / removed
+ *
+ * @throws Exception
+ */
+ @Test(enabled = ENABLED)
+ public void testUpdateMeasurementDefinitions() throws Exception {
+
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+ try {
+ registerPlugin("update-v1_0.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ Set<MeasurementDefinition> definitions1 = server1.getMetricDefinitions();
+ // for metric counts, add one for the built in AvailabilityType metric
+ assert definitions1.size() == 5 : "There should be 5 metrics for v1";
+ for (MeasurementDefinition def : definitions1) {
+ if (def.getDisplayName().equals("Three")) {
+ assert def.getDisplayType() == DisplayType.DETAIL : "DisplayType for Three should be Detail in v1";
+ }
+
+ if (def.getDisplayName().equals("Five")) {
+ // this is a trick(y) one, as we do not want to honor updates
+ // of the default interval when a plugin was already deployed once and
+ // we do a redeploy
+ assert def.getDefaultInterval() == 30000L : "DefaultInterval should be 30000 for Five in v1";
+ }
+ }
+
+ // now hot deploy a new version of that plugin
+ registerPlugin("update-v2_0.xml");
+
+ ResourceType server2 = getResourceType("testServer1");
+ Set<MeasurementDefinition> definitions2 = server2.getMetricDefinitions();
+ // for metric counts, add one for the built in AvailabilityType metric
+ assert definitions2.size() == 5 : "There should be 5 metrics in v2";
+ boolean foundFour = false;
+
+ for (MeasurementDefinition def : definitions2) {
+ assert !(def.getDisplayName().equals("One")) : "One should be gone in v2";
+ if (def.getDisplayName().equals("Three")) {
+ assert def.getDisplayType() == DisplayType.SUMMARY : "DisplayType for Three should be Summary in v2";
+ }
+
+ if (def.getDisplayName().equals("Four")) {
+ foundFour = true;
+ }
+
+ if (def.getDisplayName().equals("Five")) {
+ // this is a trick(y) one, as we do not want to honor updates
+ // of the default interval when a plugin was already deployed once and
+ // we do a redeploy
+ assert def.getDefaultInterval() == 30000L : "DefaultInterval should still be 30000 for Five in v2";
+ }
+ }
+
+ assert foundFour == true : "Four should be there in v2, but wasn't";
+
+ // Now try the other way round
+ registerPlugin("update-v1_0.xml", "3.0");
+ ResourceType server3 = getResourceType("testServer1");
+ Set<MeasurementDefinition> definitions3 = server3.getMetricDefinitions();
+ // for metric counts, add one for the built in AvailabilityType metric
+ assert definitions3.size() == 5 : "There should be 5 metrics for v3";
+ for (MeasurementDefinition def : definitions3) {
+ if (def.getDisplayName().equals("Three")) {
+ assert def.getDisplayType() == DisplayType.DETAIL : "DisplayType for Three should be Detail in v3";
+ }
+
+ if (def.getDisplayName().equals("Five")) {
+ // this is a trick(y) one, as we do not want to honor updates
+ // of the default interval when a plugin was already deployed once and
+ // we do a redeploy
+ assert def.getDefaultInterval() == 30000L : "DefaultInterval should be 30000 for Five in v3";
+ }
+ }
+ } finally {
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testUpdateMeasurementDefinition");
+ }
+ }
+ }
+
+ /**
+ * Test if the full deletion of MeasurementDefinitions works JBNADM-1639
+ *
+ * @throws Exception
+ */
+ @Test(enabled = ENABLED)
+ public void testDeleteMeasurementDefinition() throws Exception {
+
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually.
+
+ // for metric counts, add one for the built in AvailabilityType metric
+ try {
+ { // extra block for variable scoping purposes
+ registerPlugin("measurementDeletion-v1_0.xml");
+ ResourceType server = getResourceType("testServer1");
+ Set<MeasurementDefinition> def = server.getMetricDefinitions();
+ assertEquals(5, def.size());
+ }
+
+ { // extra block for variable scoping purposes
+ registerPlugin("measurementDeletion-v2_0.xml", "2.0");
+
+ ResourceType server = getResourceType("testServer1");
+ Set<MeasurementDefinition> def = server.getMetricDefinitions();
+ assertEquals(1, def.size());
+ }
+
+ { // extra block for variable scoping purposes
+ registerPlugin("measurementDeletion-v1_0.xml", "3.0");
+ ResourceType server = getResourceType("testServer1");
+ Set<MeasurementDefinition> def = server.getMetricDefinitions();
+ assertEquals(5, def.size());
+ }
+ } finally {
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testDeleteMeasurementDefinition");
+ }
+ }
+ }
+
+ /**
+ * I am renaming (= removing + adding ) a server with metrics on it.
+ * Make sure all stuff hanging on the server gets deleted. So we need
+ * to add some relations like MeasurementSchedules
+ * @throws Exception
+ */
+ @Test(enabled = ENABLED)
+ public void testRenameServer() throws Exception {
+
+ Resource testResource = null;
+ MeasurementSchedule sched = null;
+ MeasurementBaseline baseline = null;
+ EventDefinition eDef = null;
+
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually. Still, some work can be performed transactionally, as done below.
+ try {
+ try {
+ registerPlugin("update6-1.xml");
+ ResourceType server = getResourceType("testServer1");
+
+ getTransactionManager().begin();
+ EntityManager entityManager = getEntityManager();
+
+ getPluginId(entityManager);
+
+ Set<MeasurementDefinition> definitions1 = server.getMetricDefinitions();
+ // for metric counts, add one for the built in AvailabilityType metric
+ assert definitions1.size() == 2;
+
+ /*
+ * Create a Fake Resource and a MeasurementSchedule
+ */
+ testResource = new Resource("-test-", "-test resource-", server);
+ testResource.setUuid("" + new Random().nextInt());
+ entityManager.persist(testResource);
+
+ sched = new MeasurementSchedule(definitions1.iterator().next(), testResource);
+ entityManager.persist(sched);
+
+ entityManager.flush();
+
+ baseline = new MeasurementBaseline();
+ baseline.setSchedule(sched);
+ baseline.setUserEntered(true);
+ entityManager.persist(baseline);
+
+ eDef = new EventDefinition(server, "-test event definition-");
+ entityManager.persist(eDef);
+
+ setUpAgent(entityManager, testResource);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ getTransactionManager().rollback();
+ fail("Setup of v1 failed: " + e);
+ }
+
+ // Set up done, now replace the plugin with a new one.
+
+ System.out.println("Done with v1");
+
+ registerPlugin("update6-2.xml");
+
+ ResourceType server;
+ try {
+ server = getResourceType("testServer1");
+ assert server == null : "testServer1 found, but should not";
+ } catch (NoResultException nre) {
+ ; // no issue
+ }
+
+ server = getResourceType("testServer2");
+ assert server != null : "testServer2 not found";
+
+ } finally {
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testRenameServer");
+ }
+ }
+ }
+
+ /**
+ * We define a plugin with a metric. Later we upgrade the plugin to add another metric.
+ * The Metadatamamanger neeeds to add another {@link MeasurementSchedule} to it.
+ * @throws Exception
+ */
+ @Test(enabled = ENABLED)
+ public void testAddScheduleOnExistingResources() throws Exception {
+
+ // Note, plugins are registered in new transactions. for tests, this means
+ // you can't do everything in a trans and roll back at the end. You must clean up
+ // manually. Still, some work can be performed transactionally, as done below.
+ try {
+ try {
+ registerPlugin("update7-1.xml");
+ ResourceType platform = getResourceType("myPlatform7");
+
+ getTransactionManager().begin();
+ EntityManager entityManager = getEntityManager();
+
+ getPluginId(entityManager);
+
+ Set<MeasurementDefinition> definitions1 = platform.getMetricDefinitions();
+ assert definitions1.size() == 1;
+
+ /*
+ * Create a Fake Resource and a MeasurementSchedule
+ */
+ Resource testResource = new Resource("-test-", "-test resource", platform);
+ testResource.setUuid("" + new Random().nextInt());
+ entityManager.persist(testResource);
+
+ setUpAgent(entityManager, testResource);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ getTransactionManager().rollback();
+ fail("Setup of v1 failed: " + e);
+ }
+
+ // Set up done, now replace the plugin with a new one.
+
+ System.out.println("Done with v1");
+
+ try {
+ registerPlugin("update7-2.xml");
+ } catch (Throwable t) {
+ System.err.println(t);
+ }
+
+ ResourceType platform = getResourceType("myPlatform7");
+ Set<MeasurementDefinition> definitions2 = platform.getMetricDefinitions();
+ assert definitions2.size() == 2;
+
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ ResourceCriteria c = new ResourceCriteria();
+ c.addFilterResourceTypeId(platform.getId());
+ c.addFilterInventoryStatus(InventoryStatus.NEW);
+ c.fetchSchedules(true);
+ List<Resource> resources = LookupUtil.getResourceManager().findResourcesByCriteria(overlord, c);
+ assert resources != null;
+ assertEquals(1, resources.size());
+
+ Resource res = resources.get(0);
+ Set<MeasurementSchedule> schedules = res.getSchedules();
+ assert schedules != null;
+ /*
+ * We only expect one schedule for the freshly created metric, as the resource we
+ * created earlier has no schedule attached yet (in the test).
+ * In the "real world" it would get its schedules on inventory sync time.
+ */
+ assert schedules.size() == 1 : "Did not find the expected 1 new schedule, but: " + schedules.size();
+ } finally {
+ // clean up
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testRenameServer");
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateNativesSubsystemTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateNativesSubsystemTest.java
new file mode 100644
index 0000000..5f51d6c
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateNativesSubsystemTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.enterprise.server.resource.metadata.test;
+
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.transaction.Status;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.resource.ProcessScan;
+import org.rhq.core.domain.resource.ResourceType;
+
+/**
+ * Note, plugins are registered in new transactions. for tests, this means
+ * you can't do everything in a trans and roll back at the end. You must clean up manually.
+ */
+public class UpdateNativesSubsystemTest extends UpdatePluginMetadataTestBase {
+
+ @Override
+ protected String getSubsystemDirectory() {
+ return "natives";
+ }
+
+ /**
+ * Tests the behaviour of the MetadataManager wrt <process-scan> entries.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testProcessScans() throws Exception {
+ try {
+ registerPlugin("update5-v1_0.xml");
+ ResourceType platform1 = getResourceType("myPlatform5");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform1 = em.find(ResourceType.class, platform1.getId());
+
+ Set<ResourceType> servers = platform1.getChildResourceTypes();
+ assert servers.size() == 1 : "Expected to find 1 server in v1, but got " + servers.size();
+ ResourceType server1 = servers.iterator().next();
+
+ /*
+ * TODO check process scans as well
+ */
+ Set<ProcessScan> scans1 = server1.getProcessScans();
+ assert scans1.size() == 3 : "Expected to find 3 process scans in v1, but got " + scans1.size();
+ int found = 0;
+ for (ProcessScan ps : scans1) {
+ if (containedIn(ps.getName(), new String[] { "JBoss4", "JBoss5", "JBoss6" })) {
+ found++;
+ }
+ }
+
+ assert found == 3 : "Expected to find 3 process scans in v1";
+ // TODO also check query
+ getTransactionManager().rollback();
+
+ /*
+ * check process scans in v2 as well
+ */
+ registerPlugin("update5-v2_0.xml");
+ ResourceType platform2 = getResourceType("myPlatform5");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform2 = em.find(ResourceType.class, platform2.getId());
+ Set<ResourceType> servers2 = platform2.getChildResourceTypes();
+ assert servers2.size() == 1 : "Expected to find 1 server in v2, but got " + servers2.size();
+ ResourceType server2 = servers2.iterator().next();
+
+ Set<ProcessScan> scans2 = server2.getProcessScans();
+ assert scans2.size() == 3 : "Expected to find 3 process scans in v2, but got " + scans2.size();
+ found = 0;
+ for (ProcessScan ps : scans2) {
+ if (containedIn(ps.getName(), new String[] { "JBoss5", "JBoss6", "Hibernate" })) {
+ found++;
+ }
+ }
+
+ assert found == 3 : "Expected to find 3 specific process scans in v2, but got " + found;
+ getTransactionManager().rollback();
+
+ /*
+ * Now return to first version of plugin
+ */
+ registerPlugin("update5-v1_0.xml", "3.0");
+ platform1 = getResourceType("myPlatform5");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform1 = em.find(ResourceType.class, platform1.getId());
+ servers = platform1.getChildResourceTypes();
+ assert servers.size() == 1 : "Expected to find 1 server in v1, but got " + servers.size();
+ server1 = servers.iterator().next();
+
+ scans1 = server1.getProcessScans();
+ assert scans1.size() == 3 : "Expected to find 3 process scans in v1, but got " + scans1.size();
+ found = 0;
+ for (ProcessScan ps : scans1) {
+ if (containedIn(ps.getName(), new String[] { "JBoss4", "JBoss5", "JBoss6" })) {
+ found++;
+ }
+ }
+
+ assert found == 3 : "Expected to find 3 specific process scans in v1 again, but got " + found;
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testProcessScans");
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateOperationsSubsystemTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateOperationsSubsystemTest.java
new file mode 100644
index 0000000..c340367
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateOperationsSubsystemTest.java
@@ -0,0 +1,381 @@
+/*
+ * 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.enterprise.server.resource.metadata.test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.transaction.Status;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionEnumeration;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.operation.OperationDefinition;
+import org.rhq.core.domain.resource.ResourceType;
+
+/**
+ * Note, plugins are registered in new transactions. for tests, this means
+ * you can't do everything in a trans and roll back at the end. You must clean up manually.
+ */
+public class UpdateOperationsSubsystemTest extends UpdatePluginMetadataTestBase {
+
+ private static final boolean ENABLED = true;
+
+ @Override
+ protected String getSubsystemDirectory() {
+ return "operation";
+ }
+
+ /**
+ * Check updates of artifacts and operations
+ *
+ * @throws Exception
+ */
+ @Test(enabled = ENABLED)
+ public void testOperationAndArtifactUpdates() throws Exception {
+ System.out.println("= testOperationAndArtifactUpdates");
+ try {
+ registerPlugin("update3-v1_0.xml");
+ ResourceType platform1 = getResourceType("myPlatform3");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform1 = em.find(ResourceType.class, platform1.getId());
+
+ Set<PackageType> packageTypes = platform1.getPackageTypes();
+ assert packageTypes.size() == 3 : "Did not find the three expected package types in v1";
+ Set<OperationDefinition> ops = platform1.getOperationDefinitions();
+ assert ops.size() == 3 : "Did not find three expected operations in v1";
+ getTransactionManager().rollback();
+
+ /*
+ * Now deploy the changed version of the plugin
+ */
+ registerPlugin("update3-v2_0.xml");
+ ResourceType platform2 = getResourceType("myPlatform3");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform2 = em.find(ResourceType.class, platform2.getId());
+
+ Set<PackageType> packageTypes2 = platform2.getPackageTypes();
+ assert packageTypes2.size() == 3 : "Did not find the expected three package types in v2";
+ Set<OperationDefinition> opDefs = platform2.getOperationDefinitions();
+ assert opDefs.size() == 3 : "Did not find the three expected operations in v2";
+ // now that the basics are tested, go for the details...
+
+ boolean ubuFound = false;
+ for (PackageType pt : packageTypes2) {
+ // System.out.println(at.getName());
+ assert !(pt.getName().equals("rpm")) : "RPM should be gone in v2";
+ if (pt.getName().equals("ubu")) {
+ ubuFound = true;
+ }
+ }
+
+ assert ubuFound == true : "Ubu should be in v2";
+
+ boolean startFound = false;
+ for (OperationDefinition opDef : opDefs) {
+ // System.out.println(opDef.getName());
+ assert !(opDef.getName().equals("restart")) : "Restart should be gone in v2";
+ if (opDef.getName().equals("start")) {
+ startFound = true;
+ }
+
+ if (opDef.getName().equals("status")) {
+ assert opDef.getDescription().equals("Yadda!") : "Description for 'start' should be 'Yadda!', but was "
+ + opDef.getDescription();
+ }
+ }
+
+ assert startFound == true : "Start should be in v2";
+ getTransactionManager().rollback();
+
+ /*
+ * Now try the other way round
+ */
+
+ registerPlugin("update3-v1_0.xml", "3.0");
+ ResourceType platform3 = getResourceType("myPlatform3");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform3 = em.find(ResourceType.class, platform3.getId());
+
+ Set<PackageType> packageTypes3 = platform3.getPackageTypes();
+ assert packageTypes3.size() == 3 : "Did not find the three package types in v3";
+ Set<OperationDefinition> ops3 = platform3.getOperationDefinitions();
+ assert ops3.size() == 3 : "Did not find three expected operations in v3";
+
+ // we should have rpm, deb, mpkg. ubu from v2 should be gone again.
+ boolean rpmFound = false;
+ for (PackageType pt : packageTypes3) {
+ System.out.println(pt.getName());
+ assert !(pt.getName().equals("ubu")) : "ubu should be gone in v3";
+ if (pt.getName().equals("rpm")) {
+ rpmFound = true;
+ }
+ }
+
+ assert rpmFound == true : "rpm should be in v3";
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testOperationAndArtifactUpdates");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testAddRemoveOperationWithParams() throws Exception {
+ System.out.println("= testAddRemoveOperationWithParams");
+ try {
+ registerPlugin("operation1-1.xml");
+ ResourceType platform = getResourceType("ops");
+ assert platform != null;
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ Set<OperationDefinition> opDefs = platform.getOperationDefinitions();
+ assert opDefs != null;
+ assert opDefs.size() == 1;
+ OperationDefinition def = opDefs.iterator().next();
+ assert def.getName().equals("sleep");
+ assert def.getParametersConfigurationDefinition() == null;
+ getTransactionManager().rollback();
+
+ System.out.println("==> Done with v1");
+
+ registerPlugin("operation1-2.xml");
+ platform = getResourceType("ops");
+ assert platform != null;
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ opDefs = platform.getOperationDefinitions();
+ assert opDefs != null;
+ assert opDefs.size() == 2;
+
+ for (OperationDefinition odef : opDefs) {
+ if (odef.getName().equals("invokeSql")) {
+ assert odef.getDescription().startsWith("Execute");
+ ConfigurationDefinition conf = odef.getParametersConfigurationDefinition();
+ assert conf != null;
+ Map<String, PropertyDefinition> props = conf.getPropertyDefinitions();
+ assert props.size() == 2;
+ for (PropertyDefinition pd : props.values()) {
+ PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pd;
+ if (pds.getName().equals("sleep")) {
+ assert pds.getDescription() == null;
+ }
+ if (pds.getName().equals("invokeSql")) {
+ List<PropertyDefinitionEnumeration> pde = pds.getEnumeratedValues();
+ assert pde.size() == 2;
+ }
+ }
+
+ conf = odef.getResultsConfigurationDefinition();
+ assert conf != null;
+ }
+ }
+ getTransactionManager().rollback();
+
+ System.out.println("==> Done with v2");
+
+ registerPlugin("operation1-1.xml", "3.0");
+ platform = getResourceType("ops");
+ assert platform != null;
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ opDefs = platform.getOperationDefinitions();
+ assert opDefs != null;
+ assert opDefs.size() == 1;
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testAddRemoveOperationWithParams");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testAddRemoveOperationWithParams2() throws Exception {
+ System.out.println("= testAddRemoveOperationWithParams2");
+ try {
+ registerPlugin("operation2-1.xml");
+ ResourceType platform = getResourceType("ops");
+ assert platform != null;
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ Set<OperationDefinition> opDefs = platform.getOperationDefinitions();
+ assert opDefs != null;
+ assert opDefs.size() == 3 : "Did not find the expected 3 defs, but " + opDefs.size();
+
+ int found = 0;
+ for (OperationDefinition def : opDefs) {
+ if (containedIn(def.getName(), new String[] { "sleep", "wakeup", "getup" }))
+ found++;
+ }
+ assert found == 3 : "Did not find all 3 expected operations";
+ getTransactionManager().rollback();
+
+ System.out.println("==> Done with v1");
+
+ registerPlugin("operation2-1.xml");
+ System.out.println("==> Done with v1 (2)");
+
+ registerPlugin("operation2-2.xml");
+ platform = getResourceType("ops");
+ assert platform != null;
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ opDefs = platform.getOperationDefinitions();
+ assert opDefs != null;
+ assert opDefs.size() == 4 : "Did not find the expected 4 defs, but " + opDefs.size();
+ found = 0;
+ for (OperationDefinition def : opDefs) {
+ if (containedIn(def.getName(), new String[] { "wakeup", "getup", "eat", "goToWork" }))
+ found++;
+ }
+ assert found == 4 : "Did not find all 4 expected operations";
+ getTransactionManager().rollback();
+
+ System.out.println("==> Done with v2");
+
+ registerPlugin("operation2-1.xml", "3.0");
+ platform = getResourceType("ops");
+ assert platform != null;
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ opDefs = platform.getOperationDefinitions();
+ assert opDefs != null;
+ assert opDefs.size() == 3 : "Did not find the expected 3 defs, but " + opDefs.size();
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testAddRemoveOperationWithParams2");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testAddRemoveOperationWithGrouping() throws Exception {
+ System.out.println("= testAddRemoveOperationWithGrouping");
+ try {
+ registerPlugin("operation3-1.xml");
+ ResourceType platform = getResourceType("ops");
+ assert platform != null;
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ Set<OperationDefinition> opDefs = platform.getOperationDefinitions();
+ assert opDefs != null;
+ assert opDefs.size() == 3 : "Did not find the expected 3 defs, but " + opDefs.size();
+
+ int found = 0;
+ for (OperationDefinition def : opDefs) {
+ if (containedIn(def.getName(), new String[] { "sleep", "wakeup", "getup" }))
+ found++;
+ }
+ assert found == 3 : "Did not find all 3 expected operations";
+ getTransactionManager().rollback();
+
+ System.out.println("==> Done with v1");
+
+ registerPlugin("operation3-1.xml");
+ System.out.println("==> Done with v1 (2)");
+
+ registerPlugin("operation3-2.xml");
+ platform = getResourceType("ops");
+ assert platform != null;
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ opDefs = platform.getOperationDefinitions();
+ assert opDefs != null;
+
+ assert opDefs.size() == 4 : "Did not find the expected 4 defs, but " + opDefs.size();
+ found = 0;
+ for (OperationDefinition def : opDefs) {
+ if (containedIn(def.getName(), new String[] { "wakeup", "getup", "eat", "goToWork" }))
+ found++;
+ }
+ assert found == 4 : "Did not find all 4 expected operations";
+ getTransactionManager().rollback();
+
+ System.out.println("==> Done with v2");
+
+ registerPlugin("operation3-1.xml", "3.0");
+ platform = getResourceType("ops");
+ assert platform != null;
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform = em.find(ResourceType.class, platform.getId());
+
+ opDefs = platform.getOperationDefinitions();
+ assert opDefs != null;
+ assert opDefs.size() == 3 : "Did not find the expected 3 defs, but " + opDefs.size();
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testAddRemoveOperationWithGrouping");
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdatePluginMetadataTestBase.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdatePluginMetadataTestBase.java
new file mode 100644
index 0000000..ef785fc
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdatePluginMetadataTestBase.java
@@ -0,0 +1,452 @@
+/*
+ * 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.resource.metadata.test;
+
+import java.io.FileNotFoundException;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.transaction.Status;
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.util.ValidationEventCollector;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+import org.rhq.core.clientapi.agent.measurement.MeasurementAgentService;
+import org.rhq.core.clientapi.descriptor.DescriptorPackages;
+import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.criteria.ResourceCriteria;
+import org.rhq.core.domain.criteria.ResourceTypeCriteria;
+import org.rhq.core.domain.measurement.MeasurementData;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.domain.measurement.ResourceMeasurementScheduleRequest;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
+import org.rhq.enterprise.server.resource.metadata.PluginManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.test.TransactionCallbackReturnable;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+public class UpdatePluginMetadataTestBase extends AbstractEJB3Test {
+
+ protected TestServerCommunicationsService agentServiceContainer;
+
+ protected static final String PLUGIN_NAME = "ResourceMetaDataManagerBeanTest"; // don't change this - our test descriptor .xml files use it as plugin name
+ protected static final String AGENT_NAME = "-dummy agent-";
+ protected static final String COMMON_PATH_PREFIX = "./test/metadata/";
+
+ protected static PluginManagerLocal pluginMgr;
+ protected static ResourceTypeManagerLocal resourceTypeManager;
+ protected static ResourceManagerLocal resourceManager;
+
+ @AfterClass
+ public void afterClass() throws Exception {
+ cleanupTest();
+ unpreparePluginScannerService();
+ }
+
+ @BeforeMethod
+ protected void init() {
+ agentServiceContainer = prepareForTestAgents();
+ prepareMockAgentServiceContainer();
+
+ prepareScheduler();
+ try {
+ unpreparePluginScannerService(true);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ preparePluginScannerService();
+
+ try {
+ pluginMgr = LookupUtil.getPluginManager();
+ resourceTypeManager = LookupUtil.getResourceTypeManager();
+ resourceManager = LookupUtil.getResourceManager();
+ } catch (Throwable t) {
+ // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
+ // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ unprepareForTestAgents();
+ unprepareScheduler();
+ }
+
+ protected void prepareMockAgentServiceContainer() {
+ agentServiceContainer.measurementService = new MockMeasurementAgentService();
+ }
+
+ protected ResourceType getResourceType(String typeName) {
+ return getResourceType(typeName, PLUGIN_NAME);
+ }
+
+ protected ResourceType getResourceType(String typeName, String pluginName) {
+ Subject overlord = getOverlord();
+
+ ResourceTypeCriteria resourceTypeCriteria = new ResourceTypeCriteria();
+ resourceTypeCriteria.setStrict(true);
+ resourceTypeCriteria.addFilterName(typeName);
+ resourceTypeCriteria.addFilterPluginName(pluginName);
+
+ // used in UpdateMeasurementSubsystemTest
+ resourceTypeCriteria.fetchMetricDefinitions(true);
+ // used in several UpdateResourceSubsystemTest tests
+ resourceTypeCriteria.fetchSubCategory(true);
+
+ PageList<ResourceType> results = resourceTypeManager
+ .findResourceTypesByCriteria(overlord, resourceTypeCriteria);
+ if (results.size() == 0) {
+ return null;
+ } else if (results.size() == 1) {
+ return results.get(0);
+ } else {
+ throw new IllegalStateException("Found more than one resourceType with name " + typeName + " from plugin "
+ + pluginName + ".");
+ }
+ }
+
+ protected Resource createResource(String resourceKey, String name, ResourceType type) {
+ Resource resource = new Resource(resourceKey, name, type);
+ resource.setUuid(UUID.randomUUID().toString());
+ resource.setInventoryStatus(InventoryStatus.COMMITTED);
+ return resource;
+ }
+
+ protected Resource getResource(ResourceCriteria resourceCriteria) {
+ Subject overlord = getOverlord();
+
+ PageList<Resource> results = resourceManager.findResourcesByCriteria(overlord, resourceCriteria);
+ if (results.size() == 0) {
+ return null;
+ } else if (results.size() == 1) {
+ return results.get(0);
+ } else {
+ throw new IllegalStateException("Found more than one Resource with criteria " + resourceCriteria + ".");
+ }
+ }
+
+ protected String getSubsystemDirectory() {
+ return ".";
+ }
+
+ protected void registerPlugin(String pathToDescriptor, String versionOverride) throws Exception {
+ pathToDescriptor = COMMON_PATH_PREFIX + getSubsystemDirectory() + "/" + pathToDescriptor;
+ registerPluginInternal(pathToDescriptor, versionOverride);
+ }
+
+ private void registerPluginInternal(String pathToDescriptor, String versionOverride) throws Exception {
+ System.out.println("Registering plugin with descriptor [" + pathToDescriptor + "]...");
+ String md5 = MessageDigestGenerator.getDigestString(pathToDescriptor);
+ Plugin testPlugin = new Plugin(PLUGIN_NAME, "foo.jar", md5);
+ testPlugin.setDisplayName(PLUGIN_NAME + ": " + pathToDescriptor);
+ PluginDescriptor descriptor = loadPluginDescriptor(pathToDescriptor);
+ // if caller passed in their own version, use it - otherwise, use the plugin descriptor version.
+ // this allows our tests to reuse descriptors without having to duplicate them
+ if (versionOverride != null) {
+ testPlugin.setVersion(versionOverride);
+ } else {
+ testPlugin.setVersion(descriptor.getVersion());
+ }
+ try {
+ pluginMgr.registerPlugin(testPlugin, descriptor, null, true);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+
+ }
+
+ protected void registerPlugin(String pathToDescriptor) throws Exception {
+ registerPlugin(pathToDescriptor, null);
+ }
+
+ public PluginDescriptor loadPluginDescriptor(String descriptorFile) throws Exception {
+ URL descriptorUrl = this.getClass().getClassLoader().getResource(descriptorFile);
+
+ JAXBContext jaxbContext = JAXBContext.newInstance(DescriptorPackages.PC_PLUGIN);
+ URL pluginSchemaURL = this.getClass().getClassLoader().getResource("rhq-plugin.xsd");
+ Schema pluginSchema = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(pluginSchemaURL);
+
+ Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+ ValidationEventCollector vec = new ValidationEventCollector();
+ unmarshaller.setEventHandler(vec);
+ unmarshaller.setSchema(pluginSchema);
+ if (descriptorUrl == null)
+ throw new FileNotFoundException("File " + descriptorFile + " not found");
+ return (PluginDescriptor) unmarshaller.unmarshal(descriptorUrl.openStream());
+ }
+
+ protected boolean containedIn(String string, String[] references) {
+ boolean found = false;
+ for (String ref : references) {
+ if (string.equals(ref)) {
+ found = true;
+ break;
+ }
+ }
+
+ return found;
+ }
+
+ protected int getPluginId(EntityManager entityManager) throws NoResultException {
+ Plugin existingPlugin;
+ try {
+ existingPlugin = (Plugin) entityManager.createNamedQuery(Plugin.QUERY_FIND_BY_NAME)
+ .setParameter("name", PLUGIN_NAME).getSingleResult();
+ int plugin1Id = existingPlugin.getId();
+ return plugin1Id;
+ } catch (NoResultException nre) {
+ throw nre;
+ }
+ }
+
+ protected int getAgentId(EntityManager entityManager) throws NoResultException {
+ try {
+ Agent existingAgent = getAgent(entityManager);
+ int agentId = existingAgent.getId();
+ return agentId;
+ } catch (NoResultException nre) {
+ throw nre;
+ }
+ }
+
+ protected Agent getAgent(EntityManager entityManager) throws NoResultException {
+ Agent existingAgent;
+ try {
+ existingAgent = (Agent) entityManager.createNamedQuery(Agent.QUERY_FIND_BY_NAME)
+ .setParameter("name", AGENT_NAME).getSingleResult();
+ return existingAgent;
+ } catch (NoResultException nre) {
+ throw nre;
+ }
+ }
+
+ protected void setUpAgent(EntityManager entityManager, Resource testResource) {
+ Agent agent;
+ try {
+ agent = getAgent(entityManager);
+ } catch (NoResultException nre) {
+ agent = new Agent(AGENT_NAME, "localhost", 12345, "http://localhost:12345/", "-dummy token-");
+ entityManager.persist(agent);
+ }
+
+ testResource.setAgent(agent);
+ agentServiceContainer.addStartedAgent(agent);
+ }
+
+ /**
+ * A dummy that needs to be set up before running ResourceManager.deleteResource()
+ */
+ public class MockMeasurementAgentService implements MeasurementAgentService {
+
+ @Override
+ public Set<MeasurementData> getRealTimeMeasurementValue(int resourceId, Set<MeasurementScheduleRequest> requests) {
+ return null;
+ }
+
+ public void scheduleCollection(Set<ResourceMeasurementScheduleRequest> resourceSchedules) {
+ }
+
+ public void unscheduleCollection(Set<Integer> resourceIds) {
+ }
+
+ public void updateCollection(Set<ResourceMeasurementScheduleRequest> resourceSchedules) {
+ }
+
+ public Map<String, Object> getMeasurementScheduleInfoForResource(int resourceId) {
+ return null;
+ }
+ }
+
+ protected void cleanupTest() throws Exception {
+ cleanupMetadata();
+ cleanupAgent();
+ cleanupPlugin();
+ }
+
+ protected void cleanupMetadata() throws Exception {
+ String pathToDescriptor = COMMON_PATH_PREFIX + "/noTypes.xml";
+ registerPluginInternal(pathToDescriptor, null);
+ }
+
+ protected void cleanupAgent() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ try {
+ int agentId = getAgentId(em);
+ Agent agent = em.getReference(Agent.class, agentId);
+ if (null != agent) {
+ em.remove(agent);
+ }
+ } catch (NoResultException nre) {
+ // ignore, nothing to clean up
+ }
+ } catch (Exception e) {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ System.out.println("CANNOT CLEAN UP AGENT: " + e);
+ throw e;
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().commit();
+ }
+ }
+ }
+
+ protected void cleanupPlugin() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ try {
+ int plugin1Id = getPluginId(em);
+ Plugin plugin1 = em.getReference(Plugin.class, plugin1Id);
+ if (null != plugin1) {
+ em.remove(plugin1);
+ }
+ } catch (NoResultException nre) {
+ // ignore, nothing to do
+ }
+ } catch (Exception e) {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ System.out.println("CANNOT CLEAN UP PLUGIN: " + e);
+ throw e;
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().commit();
+ }
+ }
+ }
+
+ protected void cleanupResourceType(String rtName) throws Exception {
+ try {
+ ResourceType rt = getResourceType(rtName);
+
+ if (null != rt) {
+ Subject overlord = getOverlord();
+ ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+
+ // delete any resources first
+ ResourceCriteria c = new ResourceCriteria();
+ c.setStrict(true);
+ c.addFilterResourceTypeId(rt.getId());
+ c.addFilterInventoryStatus(InventoryStatus.NEW);
+ List<Resource> doomedResources = resourceManager.findResourcesByCriteria(overlord, c);
+ c.addFilterInventoryStatus(InventoryStatus.DELETED);
+ doomedResources.addAll(resourceManager.findResourcesByCriteria(overlord, c));
+ c.addFilterInventoryStatus(InventoryStatus.UNINVENTORIED);
+ doomedResources.addAll(resourceManager.findResourcesByCriteria(overlord, c));
+ // invoke bulk delete on the resource to remove any dependencies not defined in the hibernate entity model
+ // perform in-band and out-of-band work in quick succession
+ for (Resource doomed : doomedResources) {
+ List<Integer> deletedIds = resourceManager.uninventoryResource(overlord, doomed.getId());
+ for (Integer deletedResourceId : deletedIds) {
+ resourceManager.uninventoryResourceAsyncWork(overlord, deletedResourceId);
+ }
+ }
+
+ // Measurement defs go away via cascade remove
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ rt = em.find(ResourceType.class, rt.getId());
+ ResourceType parent = rt.getParentResourceTypes().isEmpty() ? null : rt.getParentResourceTypes()
+ .iterator().next();
+ em.remove(rt);
+ if (null != parent) {
+ em.remove(parent);
+ }
+ }
+ } catch (Exception e) {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ System.out.println("CANNOT CLEAN UP RESOURCE TYPE: " + rtName + ": " + e);
+ throw e;
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().commit();
+ }
+ }
+ }
+
+ //
+ // provide some convience methods to create resources
+ //
+
+ protected Subject getOverlord() {
+ return LookupUtil.getSubjectManager().getOverlord();
+ }
+
+ protected Resource persistNewResource(final String resourceTypeName) throws Exception {
+ return executeInTransaction(new TransactionCallbackReturnable<Resource>() {
+
+ public Resource execute() throws Exception {
+ ResourceType resourceType = getResourceType(resourceTypeName);
+ Resource resource = new Resource("reskey" + System.currentTimeMillis(), "resname", resourceType);
+ resource.setUuid(UUID.randomUUID().toString());
+ resource.setInventoryStatus(InventoryStatus.COMMITTED);
+ setUpAgent(em, resource);
+ em.persist(resource);
+ return resource;
+ }
+ });
+ }
+
+ protected void deleteNewResource(final Resource resource) throws Exception {
+ try {
+ List<Integer> deletedIds = resourceManager.uninventoryResource(getOverlord(), resource.getId());
+ for (Integer deletedResourceId : deletedIds) {
+ resourceManager.uninventoryResourceAsyncWork(getOverlord(), deletedResourceId);
+ }
+ } catch (Exception e) {
+ System.out.println("CANNOT CLEAN UP RESOURCE: " + resource + ": " + e);
+ throw e;
+ }
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateResourceSubsystemTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateResourceSubsystemTest.java
new file mode 100644
index 0000000..2d35079
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateResourceSubsystemTest.java
@@ -0,0 +1,805 @@
+/*
+ * 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.enterprise.server.resource.metadata.test;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.transaction.Status;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.resource.ResourceSubCategory;
+import org.rhq.core.domain.resource.ResourceType;
+
+/**
+ * Note, plugins are registered in new transactions. for tests, this means
+ * you can't do everything in a trans and roll back at the end. You must clean up manually.
+ */
+public class UpdateResourceSubsystemTest extends UpdatePluginMetadataTestBase {
+
+ private static final boolean ENABLED = true;
+
+ @Override
+ protected String getSubsystemDirectory() {
+ return "resource";
+ }
+
+ @Test(enabled = ENABLED)
+ public void testSingleSubCategoryCreate() throws Exception {
+ try {
+ registerPlugin("one-subcat-v1_0.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ assertAppsSubCategory(subCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testSingleSubCategoryCreate");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testSingleSubCategoryAddFromEmpty() throws Exception {
+ try {
+ registerPlugin("no-subcat.xml", "1.0");
+ registerPlugin("one-subcat-v1_0.xml", "2.0");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ assertAppsSubCategory(subCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testSingleSubCategoryAddFromEmpty");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testSingleSubCategoryAddSibling() throws Exception {
+ try {
+ registerPlugin("one-subcat-v1_0.xml", "1.0");
+ registerPlugin("two-subcat.xml", "2.0");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 2, 0);
+ assertAppsSubCategory(subCat);
+
+ subCat = assertSubCategory(server1.getChildSubCategories(), 2, 1);
+ assertServicesSubCategory(subCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testSingleSubCategoryAddSibling");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testSingleSubCategoryReplace() throws Exception {
+ try {
+ registerPlugin("one-subcat-v1_0.xml");
+ registerPlugin("one-subcat-v2_0.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ assertServicesSubCategory(subCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testSingleSubCategoryReplace");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testSingleSubCategoryRemoveOneFromTwo() throws Exception {
+ try {
+ registerPlugin("two-subcat.xml", "1.0");
+ registerPlugin("one-subcat-v2_0.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ assertServicesSubCategory(subCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testSingleSubCategoryRemoveOneFromTwo");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testSingleSubCategoryUpdate() throws Exception {
+ try {
+ registerPlugin("one-subcat-v1_0.xml");
+ registerPlugin("one-subcat-v1_1.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ assertApps2SubCategory(subCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testSingleSubCategoryUpdate");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testSingleSubCategoryRemove() throws Exception {
+ try {
+ registerPlugin("one-subcat-v1_0.xml");
+ registerPlugin("no-subcat.xml", "2.0");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ assertSubCategory(server1.getChildSubCategories(), 0, null);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testSingleSubCategoryRemove");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testNestedSubCategoryReplace() throws Exception {
+ try {
+ registerPlugin("nested-subcat-v1_0.xml");
+ registerPlugin("nested-subcat-v2_0.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ ResourceSubCategory childSubCat = assertSubCategory(subCat.getChildSubCategories(), 1, 0);
+ assertServicesSubCategory(childSubCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testNestedSubCategoryReplace");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testNestedSubCategoryAddFromEmpty() throws Exception {
+ try {
+ registerPlugin("no-subcat.xml", "0.0");
+ registerPlugin("nested-subcat-v1_0.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ ResourceSubCategory childSubCat = assertSubCategory(subCat.getChildSubCategories(), 1, 0);
+ assertAppsSubCategory(childSubCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testNestedSubCategoryAddFromEmpty");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testNestedSubCategoryRemoveOneFromTwo() throws Exception {
+ try {
+ registerPlugin("nested-subcat-2children.xml", "1.0");
+ registerPlugin("nested-subcat-v2_0.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ ResourceSubCategory childSubCat = assertSubCategory(subCat.getChildSubCategories(), 1, 0);
+ assertServicesSubCategory(childSubCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testNestedSubCategoryRemoveOneFromTwo");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testNestedSubCategoryAddSibling() throws Exception {
+ try {
+ registerPlugin("nested-subcat-v2_0.xml");
+ registerPlugin("nested-subcat-2children.xml", "3.0");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ ResourceSubCategory childSubCat = assertSubCategory(subCat.getChildSubCategories(), 2, 1);
+ assertAppsSubCategory(childSubCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testNestedSubCategoryAddSibling");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testNestedSubCategoryRemoveChild() throws Exception {
+ try {
+ registerPlugin("nested-subcat-grandchild.xml", "1.0");
+ registerPlugin("nested-subcat-v2_0.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ ResourceSubCategory childSubCat = assertSubCategory(subCat.getChildSubCategories(), 1, 0);
+
+ assertServicesSubCategory(childSubCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testNestedSubCategoryRemoveChild");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testNestedSubCategoryAddChild() throws Exception {
+ try {
+ registerPlugin("nested-subcat-v2_0.xml");
+ registerPlugin("nested-subcat-grandchild.xml", "3.0");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ ResourceSubCategory childSubCat = assertSubCategory(subCat.getChildSubCategories(), 1, 0);
+ ResourceSubCategory grandChildSubCat = assertSubCategory(childSubCat.getChildSubCategories(), 1, 0);
+ assertAppsSubCategory(grandChildSubCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testNestedSubCategoryAddChild");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testNestedSubCategoryUpdate() throws Exception {
+ try {
+ registerPlugin("nested-subcat-v1_0.xml");
+ registerPlugin("nested-subcat-v1_1.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ ResourceSubCategory childSubCat = assertSubCategory(subCat.getChildSubCategories(), 1, 0);
+
+ assertApps2SubCategory(childSubCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testNestedSubCategoryUpdate");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testNestedSubCategoryAdd() throws Exception {
+ try {
+ registerPlugin("one-subcat-v3_0.xml");
+ registerPlugin("nested-subcat-v1_1.xml", "4.0");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ ResourceSubCategory childSubCat = assertSubCategory(subCat.getChildSubCategories(), 1, 0);
+
+ assertApps2SubCategory(childSubCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testNestedSubCategoryAdd");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testNestedSubCategoryCreate() throws Exception {
+ try {
+ registerPlugin("nested-subcat-v1_1.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ ResourceSubCategory childSubCat = assertSubCategory(subCat.getChildSubCategories(), 1, 0);
+
+ assertApps2SubCategory(childSubCat);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testNestedSubCategoryCreate");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testNestedSubCategoryRemoveAll() throws Exception {
+ try {
+ registerPlugin("nested-subcat-v1_0.xml");
+ registerPlugin("no-subcat.xml", "2.0");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ assertSubCategory(server1.getChildSubCategories(), 0, null);
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testNestedSubCategoryRemoveAll");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testNestedSubCategoryCreateWithServices() throws Exception {
+ try {
+ registerPlugin("nested-subcat-services-v1_0.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ Set<ResourceType> children = server1.getChildResourceTypes();
+ assert children.size() == 3;
+
+ ResourceType services = getResourceType("testService1");
+ assertServicesSubCategory(services.getSubCategory());
+
+ ResourceType apps = getResourceType("testApp1");
+ assertAppsSubCategory(apps.getSubCategory());
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testNestedSubCategoryCreateWithServices");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testNestedSubCategoryCreateWithServices2() throws Exception {
+ try {
+ registerPlugin("nested-subcat-services-v2_0.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ Set<ResourceType> children = server1.getChildResourceTypes();
+ assert children.size() == 2;
+
+ ResourceType services = getResourceType("testService2");
+ assert services.getSubCategory().getName().equals("applications2");
+
+ ResourceType apps = getResourceType("testApp1");
+ assert apps.getSubCategory().getName().equals("applications2");
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testNestedSubCategoryCreateWithServices2");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testNestedSubCategoryUpdateWithServices() throws Exception {
+ try {
+ registerPlugin("nested-subcat-services-v1_0.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ Set<ResourceType> children = server1.getChildResourceTypes();
+ assert children.size() == 3;
+ List<ResourceSubCategory> subCategories = server1.getChildSubCategories();
+ assert subCategories != null;
+ assert subCategories.size() == 1; // subcat with name "parent"
+ // TODO check for 2 children of this subcategory
+ getTransactionManager().rollback();
+
+ registerPlugin("nested-subcat-services-v2_0.xml");
+ server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ children = server1.getChildResourceTypes();
+ assert children.size() == 2 : "Expected 2 children, but got " + children.size();
+ subCategories = server1.getChildSubCategories(); // "testServer1"
+ assert subCategories != null;
+ assert subCategories.size() == 1; // Subcat with name "parent"
+ ResourceSubCategory parent = subCategories.get(0);
+ assert parent != null;
+ assert parent.getName().equals("parent") : "Name was not 'parent', but " + parent.getName();
+ subCategories = parent.getChildSubCategories();
+ assert subCategories != null;
+ assert subCategories.size() == 1; // SubSubcat with name "applications2"
+ ResourceSubCategory app2 = subCategories.get(0);
+ assert app2 != null;
+ assert app2.getName().equals("applications2") : "Name was not 'applications2', but " + app2.getName();
+
+ // Now the services within <server name="testServer1"/> ...
+ ResourceType service2 = getResourceType("testService2");
+ assert service2 != null;
+ assert service2.getParentResourceTypes().iterator().next().equals(server1);
+ subCategories = service2.getChildSubCategories();
+ assert subCategories.isEmpty() : "Expected subcategories to be empty, but was " + subCategories;
+
+ ResourceSubCategory subCategory = service2.getSubCategory(); // the subcategory attribute
+ // TODO the subCategory is currently not persisted to the DB, so can not be found
+ subCategory = em.find(ResourceSubCategory.class, subCategory.getId());
+ String name = subCategory.getName();
+ assert name.equals("applications2") : "Expected 'applictions2', but got " + name;
+
+ ResourceType apps = getResourceType("testApp1");
+ assert apps.getSubCategory().getName().equals("applications2");
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testNestedSubCategoryUpdateWithServices");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testRemoveService() throws Exception {
+ try {
+ registerPlugin("services-v1_0.xml");
+ registerPlugin("services-v2_0.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ Set<ResourceType> children = server1.getChildResourceTypes();
+ assert children.size() == 2 : "Incorrect number of child resource types, should have been 2 but was ["
+ + children.size() + "].";
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testRemoveService");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testSimpleSubCategoryCreate() throws Exception {
+ try {
+ registerPlugin("test-subcategories.xml");
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ assert subCat.getName().equals("applications");
+
+ ResourceType server2 = getResourceType("testServer2");
+ server2 = em.find(ResourceType.class, server2.getId());
+
+ assert server2.getChildSubCategories() != null;
+ assert server2.getChildSubCategories().size() == 2 : "Unexpected number of subcategories ["
+ + server2.getChildSubCategories().size() + "]";
+ subCat = server2.getChildSubCategories().get(1);
+ assert subCat.getName().equals("resource");
+
+ List<ResourceSubCategory> childSubCats = subCat.getChildSubCategories();
+ assert childSubCats.size() == 2;
+ subCat = childSubCats.get(1);
+ assert subCat.getName().equals("destinations");
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testSimpleSubCategoryCreate");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testSimpleSubCategoryUpdate() throws Exception {
+ try {
+ registerPlugin("test-subcategories.xml", "1.0");
+ // pretend to be an updated plugin
+ registerPlugin("test-subcategories2.xml", "2.0");
+ // now test how the subcategories got updated
+ ResourceType server1 = getResourceType("testServer1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ server1 = em.find(ResourceType.class, server1.getId());
+
+ ResourceSubCategory subCat = assertSubCategory(server1.getChildSubCategories(), 1, 0);
+ assertApps2SubCategory(subCat);
+
+ ResourceType server2 = getResourceType("testServer2");
+ server2 = em.find(ResourceType.class, server2.getId());
+
+ assert server2.getChildSubCategories() != null;
+
+ assert server2.getChildSubCategories().size() == 2 : "Unexpected number of subcategories ["
+ + server2.getChildSubCategories().size() + "]";
+ int found = 0;
+ ResourceSubCategory resourceSubCat = null;
+ for (int i = 0; i <= 1; i++) {
+ ResourceSubCategory subCategory = server2.getChildSubCategories().get(i);
+ String name = subCategory.getName();
+ if ("services2".equals(name) || "resource".equals(name))
+ found++;
+ if ("resource".equals(name))
+ resourceSubCat = subCategory;
+ }
+ assert found == 2;
+ assert resourceSubCat != null;
+
+ List<ResourceSubCategory> childSubCats = resourceSubCat.getChildSubCategories();
+ assert childSubCats.size() == 2;
+ subCat = childSubCats.get(1);
+ assert subCat.getName().equals("destinations");
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testSimpleSubCategoryUpdate");
+ }
+ }
+ }
+
+ /**
+ * Test if illegal subcategories will make the deployer bail out as
+ * expected.
+ * @throws Exception
+ */
+ @Test(enabled = ENABLED)
+ public void testAddIllegalSubcategory1() throws Exception {
+ try {
+ registerPlugin("illegal-subcat-1.xml");
+ fail("Exception was not thrown.");
+ } catch (Throwable t) {
+ // expected
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testAddIllegalSubcategory1");
+ }
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void testReferenceToUndefinedChildSubCategory() throws Exception {
+ System.out.println("= testReferenceToUndefinedChildSubCategory");
+ try {
+ try {
+ registerPlugin("undefined-child-subcat-1.xml");
+ fail("Exception was not thrown.");
+ } catch (Exception ignored) {
+ // expected
+ }
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testReferenceToUndefinedChildSubCategory");
+ }
+ }
+ }
+
+ private ResourceSubCategory assertSubCategory(List<ResourceSubCategory> subCats, Integer size, Integer index) {
+ assert subCats != null;
+ assert subCats.size() == size : "Unexpected number of Sub categories. Expected [" + size + "] got ["
+ + subCats.size() + "].";
+ ResourceSubCategory subCat = null;
+ if (index != null) {
+ subCat = subCats.get(index);
+ }
+
+ return subCat;
+ }
+
+ private void assertServicesSubCategory(ResourceSubCategory subCat) {
+ assert subCat != null;
+ assert subCat.getName().equals("services");
+ assert subCat.getDisplayName().equals("Services");
+ assert subCat.getDescription().equals("Some services");
+ }
+
+ private void assertAppsSubCategory(ResourceSubCategory subCat) {
+ assert subCat != null;
+ assert subCat.getName().equals("applications");
+ assert subCat.getDisplayName().equals("Apps");
+ assert subCat.getDescription().equals("The apps.");
+ }
+
+ private void assertApps2SubCategory(ResourceSubCategory subCat) {
+ assert subCat != null;
+ assert subCat.getName().equals("applications");
+ assert subCat.getDisplayName().equals("Apps2");
+ assert subCat.getDescription().equals("The apps2.");
+ }
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateResourceTypeSubsystemTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateResourceTypeSubsystemTest.java
new file mode 100644
index 0000000..dd05cd6
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateResourceTypeSubsystemTest.java
@@ -0,0 +1,363 @@
+/*
+ * 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.resource.metadata.test;
+
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.transaction.Status;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration;
+import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory;
+import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory.Context;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.criteria.ResourceCriteria;
+import org.rhq.core.domain.measurement.DisplayType;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Note, plugins are registered in new transactions. For tests, this means
+ * you can't do everything in a trans and roll back at the end. You must clean up manually.
+ */
+public class UpdateResourceTypeSubsystemTest extends UpdatePluginMetadataTestBase {
+
+ @Override
+ protected String getSubsystemDirectory() {
+ return "resource-type";
+ }
+
+ /**
+ * Tests updating bundle-target config
+ */
+ @Test
+ public void testResourceTypeBundleTarget() throws Exception {
+ try {
+ // register the plugin - it has a platform with child server that is a bundle target
+ registerPlugin("updateResourceTypeBundleTarget-v1.xml");
+ ResourceType platform1 = getResourceType("myPlatform1");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform1 = em.find(ResourceType.class, platform1.getId());
+
+ assert platform1.getResourceTypeBundleConfiguration() == null : "platform should not be a bundle target";
+ Set<ResourceType> servers1 = platform1.getChildResourceTypes();
+
+ assert servers1.size() == 1 : "must only have one child server under the test platform";
+ ResourceType server1 = servers1.iterator().next();
+ ResourceTypeBundleConfiguration bundleConfig1 = server1.getResourceTypeBundleConfiguration();
+ assert bundleConfig1 != null : "server should have been a bundle target";
+
+ Set<BundleDestinationBaseDirectory> baseDirs1 = bundleConfig1.getBundleDestinationBaseDirectories();
+ assert baseDirs1.size() == 2 : "should have been 2 bundle dest base dirs: " + baseDirs1;
+
+ for (BundleDestinationBaseDirectory baseDir : baseDirs1) {
+ if (baseDir.getName().equals("firstDestBaseDir")) {
+ assert baseDir.getValueContext() == Context.pluginConfiguration : "bad context: " + baseDir;
+ assert baseDir.getValueName().equals("prop1") : "bad value" + baseDir;
+ } else if (baseDir.getName().equals("secondDestBaseDir")) {
+ assert baseDir.getValueContext() == Context.fileSystem : "bad context: " + baseDir;
+ assert baseDir.getValueName().equals("/") : "bad value" + baseDir;
+ } else {
+ assert false : "wrong dest base dir was retrieved: " + baseDir;
+ }
+ }
+
+ getTransactionManager().rollback();
+
+ // now upgrade the plugin - the bundle config will have changed in the server
+ registerPlugin("updateResourceTypeBundleTarget-v2.xml");
+ ResourceType platform2 = getResourceType("myPlatform1");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform2 = em.find(ResourceType.class, platform2.getId());
+
+ assert platform1.getResourceTypeBundleConfiguration() == null : "platform should not be a bundle target";
+ Set<ResourceType> servers2 = platform2.getChildResourceTypes();
+
+ assert servers2.size() == 1 : "Expected to find 1 server";
+ ResourceType server2 = servers2.iterator().next();
+ ResourceTypeBundleConfiguration bundleConfig2 = server2.getResourceTypeBundleConfiguration();
+ assert bundleConfig2 != null : "server should have been a bundle target";
+
+ Set<BundleDestinationBaseDirectory> baseDirs2 = bundleConfig2.getBundleDestinationBaseDirectories();
+ assert baseDirs2.size() == 1 : "should have been 1 bundle dest base dir: " + baseDirs2;
+
+ BundleDestinationBaseDirectory baseDir = baseDirs2.iterator().next();
+ assert baseDir.getName().equals("thirdDestBaseDir");
+ assert baseDir.getValueContext() == Context.resourceConfiguration : "bad context: " + baseDir;
+ assert baseDir.getValueName().equals("resourceProp1") : "bad value" + baseDir;
+
+ // make sure the old bundle config was deleted when we upgraded and overwrite it with the new config
+ assert null == em.find(Configuration.class, bundleConfig1.getBundleConfiguration().getId()) : "The configuration "
+ + bundleConfig1 + " should have been deleted";
+
+ getTransactionManager().rollback();
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testResourceTypeBundleTarget");
+ }
+ }
+ }
+
+ /**
+ * See if deletion of a resource type just works
+ *
+ * @throws Exception on error
+ */
+ @Test
+ public void testResourceTypeDeletion() throws Exception {
+ try {
+ registerPlugin("update4-v1_0.xml");
+ ResourceType platform1 = getResourceType("myPlatform4");
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform1 = em.find(ResourceType.class, platform1.getId());
+
+ Set<ResourceType> servers1 = platform1.getChildResourceTypes();
+ assert servers1.size() == 2 : "Expected to find 2 servers in v1";
+ int found = 0;
+ for (ResourceType server : servers1) {
+ if (server.getName().equals("testServer1")) {
+ found++;
+ }
+
+ if (server.getName().equals("testServer2")) {
+ found++;
+ }
+ }
+
+ assert found == 2 : "I did not find the expected servers in v1";
+ getTransactionManager().rollback();
+
+ registerPlugin("update4-v2_0.xml");
+ ResourceType platform2 = getResourceType("myPlatform4");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform2 = em.find(ResourceType.class, platform2.getId());
+
+ Set<ResourceType> servers2 = platform2.getChildResourceTypes();
+ assert servers2.size() == 1 : "Expected to find 1 servers in v2";
+ ResourceType server2 = servers2.iterator().next();
+ assert server2.getName().equals("testServer1");
+ Set<MeasurementDefinition> mdef = server2.getMetricDefinitions();
+ // include the built-in AvailabilityType metric
+ assert mdef.size() == 2 : "Expected 2 MeasurementDefinition in v2";
+ getTransactionManager().rollback();
+
+ registerPlugin("update4-v1_0.xml", "3.0");
+ ResourceType platform3 = getResourceType("myPlatform4");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform3 = em.find(ResourceType.class, platform3.getId());
+
+ Set<ResourceType> servers3 = platform3.getChildResourceTypes();
+ assert servers3.size() == 2 : "Expected to find 2 servers in v1/2";
+ found = 0;
+ for (ResourceType server : servers3) {
+ if (server.getName().equals("testServer1")) {
+ found++;
+ }
+
+ if (server.getName().equals("testServer2")) {
+ found++;
+ }
+ }
+
+ assert found == 2 : "I did not find the expected servers in v1/2";
+
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testResourceTypeDeletion");
+ }
+ }
+ }
+
+ @Test
+ /**
+ * Tests moving a resource type to a new parent resource type.
+ */
+ public void testMoveResourceType() throws Exception {
+ System.out.println("testMoveResourceType --- start");
+ try {
+ registerPlugin("update2-v1_0.xml");
+
+ ResourceType platform1 = getResourceType("myPlatform");
+ Resource platformResource = createResource("foo-myPlatform", "foo-myPlatform", platform1);
+ ResourceType service1 = getResourceType("service1");
+ Resource service1Resource = createResource("foo-service1", "foo-service1", service1);
+ platformResource.addChildResource(service1Resource);
+ ResourceType nestedOne = getResourceType("nestedOne");
+ Resource nestedOneResource = createResource("foo-nestedOne", "foo-nestedOne", nestedOne);
+ service1Resource.addChildResource(nestedOneResource);
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ resourceManager.createResource(overlord, platformResource, -1);
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ platform1 = em.find(ResourceType.class, platform1.getId());
+
+ assert platform1 != null : "I did not find myPlatform";
+ Set<MeasurementDefinition> defs = platform1.getMetricDefinitions();
+ // no built-in AvailabilityType metric for platforms
+ assert defs.size() == 1 : "I was expecting 1 metric definition at platform level in v1";
+ assert DisplayType.DETAIL == defs.iterator().next().getDisplayType() : "Display type should be DETAIL in v1";
+
+ // one child service in v1
+ Set<ResourceType> platformChildren = platform1.getChildResourceTypes();
+ assert platformChildren.size() == 1 : "Expected 1 direct child service of platform in v1";
+ service1 = platformChildren.iterator().next();
+ assert service1.getName().equals("service1") : "Expected 'service1' as name of direct platform child in v1";
+ // include the built-in AvailabilityType metric
+ assert service1.getMetricDefinitions().size() == 2 : "Expected 2 metric for 'service1' in v1";
+ Set<ResourceType> nestedServices = service1.getChildResourceTypes();
+ assert nestedServices.size() == 1 : "Expected 1 nested service of 'service1' in v1";
+ Set<MeasurementDefinition> nestedDefs = nestedServices.iterator().next().getMetricDefinitions();
+ // include the built-in AvailabilityType metric
+ assert nestedDefs.size() == 2 : "Expected 2 definition within 'nestedService' in v1";
+ MeasurementDefinition defThree = nestedDefs.iterator().next();
+ int definitionId = defThree.getId(); // get the id of the definition "Three" and save it for later use
+ getTransactionManager().rollback();
+
+ System.out.println("testMoveResourceType -- done with the first plugin version");
+
+ /*
+ * The nested service got pulled out and put under platform
+ */
+ registerPlugin("update2-v2_0.xml");
+ ResourceType platform2 = getResourceType("myPlatform");
+ getTransactionManager().begin();
+ em = getEntityManager();
+ platform2 = em.find(ResourceType.class, platform2.getId());
+
+ assert platform2 != null : "I did not find myPlatform";
+ Set<MeasurementDefinition> defs2 = platform2.getMetricDefinitions();
+ // no built-in AvailabilityType metric for platforms
+ assert defs2.size() == 1 : "I was expecting 1 definition at platform level in v2";
+ assert DisplayType.SUMMARY == defs2.iterator().next().getDisplayType() : "Display type should be SUMMARY in v2";
+
+ ResourceCriteria resourceCriteria = new ResourceCriteria();
+ resourceCriteria.setStrict(true);
+ resourceCriteria.addFilterResourceKey("foo-myPlatform");
+ resourceCriteria.fetchChildResources(true);
+ Resource platform2Resource = getResource(resourceCriteria);
+ assert platform2Resource != null : "Expected to find platform Resource in db.";
+
+ // two children in v2
+ Set<ResourceType> platformChildren2 = platform2.getChildResourceTypes();
+ assert platformChildren2.size() == 2 : "Expected 2 direct child service types of platform in v2";
+
+ Set<Resource> platform2ChildResources = platform2Resource.getChildResources();
+ assert platform2ChildResources.size() == 2 : "Expected 2 direct child services of platform in v2";
+ boolean foundMovedResource = false;
+ for (Resource childResource : platform2ChildResources) {
+ assert childResource.getChildResources().isEmpty() : "Expected child Resource " + childResource
+ + " to have no children";
+ if (childResource.getResourceKey().equals("foo-nestedOne")) {
+ foundMovedResource = true;
+ }
+ }
+ assert foundMovedResource : "Expected 'foo-nestedOne' Resource to have been moved directly under platform Resource";
+
+ for (ResourceType type : platformChildren2) {
+ String typeName = type.getName();
+ // include the built-in AvailabilityType metric
+ assert type.getMetricDefinitions().size() == 2 : "Expected two definition for " + typeName + " in v2";
+ if (typeName.equals("nestedOne")) // The moved one
+ {
+ Set<MeasurementDefinition> defs3 = type.getMetricDefinitions();
+ MeasurementDefinition three = defs3.iterator().next();
+ assert three.getDisplayName().equals("Three") : "Expected the nestedOne to have a metric withDisplayName Three in v2, but it was "
+ + three.getDisplayName();
+ assert three.getDisplayType() == DisplayType.SUMMARY : "Expected three to be SUMMARY in v2";
+
+ /*
+ * TODO check here if the Definition is the one from above which got moved. this should be the case.
+ * Else we would loose all measurement schedules (and disassociate them from measurement data. But the
+ * latter is a different story. We probably should cascade that anyway.
+ */
+ assert three.getId() == definitionId : "Expected the id of 'Three' to be " + definitionId
+ + ", but it was " + three.getId() + " in v2";
+ } else if (typeName.equals("service1")) {
+ // check that the nested service is gone
+ Set<ResourceType> childrenOfService = type.getChildResourceTypes();
+ assert childrenOfService.size() == 0 : "No children of 'service1' expected in v2, but found: "
+ + childrenOfService.size();
+ } else {
+ assert true == false : "We found an unknown type with name " + typeName;
+ }
+ }
+
+ // TODO now that we're done here, apply v1 again to also test the other direction
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out
+ .println("CANNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testMoveResourceType");
+ }
+ }
+
+ System.out.println("testMoveResourceType --- end");
+ }
+
+ @Test
+ public void testDuplicateResourceType() throws Exception {
+ System.out.println("= testDuplicateResourceType");
+ try {
+ System.out.println("NOTE: A stack trace coming out of this is expected.");
+ registerPlugin("duplicateResourceType.xml");
+ getResourceType("ops");
+ assert false : "We should not have hit this line";
+ } catch (Exception e) {
+ // ignore - We expect an exception to come out of the ResourceMetadataManager
+ } finally {
+ if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) {
+ getTransactionManager().rollback();
+ }
+ try {
+ cleanupTest();
+ } catch (Exception e) {
+ System.out.println("CANNOT CLEAN UP TEST: " + this.getClass().getSimpleName()
+ + ".testDuplicateResourceType");
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceFactoryManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceFactoryManagerBeanTest.java
new file mode 100644
index 0000000..cbcf1dc
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceFactoryManagerBeanTest.java
@@ -0,0 +1,743 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.resource.test;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.ejb.EJBException;
+import javax.persistence.EntityManager;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.agent.PluginContainerException;
+import org.rhq.core.clientapi.agent.inventory.CreateResourceRequest;
+import org.rhq.core.clientapi.agent.inventory.CreateResourceResponse;
+import org.rhq.core.clientapi.agent.inventory.DeleteResourceRequest;
+import org.rhq.core.clientapi.agent.inventory.DeleteResourceResponse;
+import org.rhq.core.clientapi.agent.inventory.ResourceFactoryAgentService;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.content.PackageCategory;
+import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.resource.CreateDeletePolicy;
+import org.rhq.core.domain.resource.CreateResourceHistory;
+import org.rhq.core.domain.resource.CreateResourceStatus;
+import org.rhq.core.domain.resource.DeleteResourceHistory;
+import org.rhq.core.domain.resource.DeleteResourceStatus;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceCreationDataType;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.discovery.DiscoveryBossLocal;
+import org.rhq.enterprise.server.resource.ResourceFactoryManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.StandardServerPluginService;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * A unit test for {@link org.rhq.enterprise.server.resource.ResourceFactoryManagerBean}.
+ *
+ * @author Jason Dobies
+ */
+public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test {
+
+ private static final String TEST_PLUGIN_NAME = "TestPlugin";
+
+ // Attributes --------------------------------------------
+
+ private ResourceFactoryManagerLocal resourceFactoryManager;
+ private ResourceManagerLocal resourceManager;
+ private DiscoveryBossLocal discoveryBoss;
+ private Subject overlord;
+
+ private MockResourceFactoryAgentService mockAgentService = new MockResourceFactoryAgentService();
+
+ // Populated during setupResourceEnvironment
+ private Resource parentResource;
+ private ResourceType parentResourceType;
+ private ResourceType contentBackedChildResourceType;
+ private ResourceType configBackedChildResourceType1;
+ private ResourceType configBackedChildResourceType2;
+ private PackageType packageType;
+
+ // Setup --------------------------------------------
+
+ @BeforeClass
+ public void setupBeforeClass() throws Exception {
+ resourceFactoryManager = LookupUtil.getResourceFactoryManager();
+ resourceManager = LookupUtil.getResourceManager();
+ discoveryBoss = LookupUtil.getDiscoveryBoss();
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+ }
+
+ @BeforeMethod
+ public void setupBeforeMethod() throws Exception {
+ prepareScheduler();
+ TestServerCommunicationsService agentServiceContainer = prepareForTestAgents();
+ agentServiceContainer.resourceFactoryService = mockAgentService;
+
+ //the server plugins are in play when package types are involved
+ StandardServerPluginService serverPluginService = new StandardServerPluginService();
+ prepareCustomServerPluginService(serverPluginService);
+ serverPluginService.startMasterPluginContainer();
+
+ setupResourceEnvironment();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void teardownAfterMethod() throws Exception {
+ unprepareForTestAgents();
+ unprepareScheduler();
+ unprepareServerPluginService();
+
+ teardownResourceEnvironment();
+ }
+
+ // Test Cases --------------------------------------------
+
+ @Test
+ public void createResourceViaConfiguration() throws Exception {
+ // Setup
+ mockAgentService.setCreateReturnStatus(CreateResourceStatus.SUCCESS);
+
+ // Assemble call parameters
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ Configuration resourceConfiguration = new Configuration();
+ resourceConfiguration.put(new PropertySimple("property1", "value1"));
+
+ // Test
+ resourceFactoryManager.createResource(overlord, parentResource.getId(), configBackedChildResourceType1.getId(),
+ "newResource", null, resourceConfiguration);
+
+ // Verify
+ EntityManager entityManager = null;
+ try {
+ getTransactionManager().begin();
+ entityManager = getEntityManager();
+
+ Resource parent = entityManager.find(Resource.class, parentResource.getId());
+ List<CreateResourceHistory> historyList = parent.getCreateChildResourceRequests();
+
+ assert historyList.size() == 1 : "Incorrect number of children found. Expected: 1, Found: "
+ + historyList.size();
+
+ CreateResourceHistory historyItem = historyList.get(0);
+
+ assert historyItem.getStatus() == CreateResourceStatus.SUCCESS : "Incorrect status for history item. Expected: Success, Found: "
+ + historyItem.getStatus();
+ assert historyItem.getNewResourceKey().equals("mockResourceKey") : "Incorrect resource key for history item. Expected: mockResourceKey, Found: "
+ + historyItem.getNewResourceKey();
+ assert historyItem.getErrorMessage() == null : "Error message found for successful call";
+ assert historyItem.getConfiguration() != null : "Null configuration found for history item";
+ } finally {
+ getTransactionManager().rollback();
+ entityManager.close();
+ }
+ }
+
+ @Test
+ public void createResourceViaConfigurationFailure() throws Exception {
+ // Setup
+ mockAgentService.setCreateReturnStatus(CreateResourceStatus.FAILURE);
+
+ // Assemble call parameters
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ Configuration resourceConfiguration = new Configuration();
+ resourceConfiguration.put(new PropertySimple("property1", "value1"));
+
+ // Test
+ resourceFactoryManager.createResource(overlord, parentResource.getId(), configBackedChildResourceType1.getId(),
+ "newResource", null, resourceConfiguration);
+
+ // Verify
+ EntityManager entityManager = null;
+ try {
+ getTransactionManager().begin();
+ entityManager = getEntityManager();
+
+ Resource parent = entityManager.find(Resource.class, parentResource.getId());
+ List<CreateResourceHistory> historyList = parent.getCreateChildResourceRequests();
+
+ assert historyList.size() == 1 : "Incorrect number of children found. Expected: 1, Found: "
+ + historyList.size();
+
+ CreateResourceHistory historyItem = historyList.get(0);
+
+ assert historyItem.getStatus() == CreateResourceStatus.FAILURE : "Incorrect status for history item. Expected: Failure, Found: "
+ + historyItem.getStatus();
+ assert historyItem.getErrorMessage().equals("errorMessage") : "Incorrect error message for history item. Expected: errorMessage, Found: "
+ + historyItem.getErrorMessage();
+ } finally {
+ getTransactionManager().rollback();
+ entityManager.close();
+ }
+ }
+
+ @Test
+ public void createSingletonResourceViaConfiguration() throws Exception {
+ // Setup
+ mockAgentService.setCreateReturnStatus(CreateResourceStatus.SUCCESS);
+
+ // Assemble call parameters
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ Configuration resourceConfiguration = new Configuration();
+ resourceConfiguration.put(new PropertySimple("property1", "value1"));
+
+ // Test
+ CreateResourceHistory history1 = resourceFactoryManager.createResource(overlord, parentResource.getId(), configBackedChildResourceType2.getId(),
+ "newResource", null, resourceConfiguration);
+
+ // Verify
+ EntityManager entityManager = null;
+ try {
+ getTransactionManager().begin();
+ entityManager = getEntityManager();
+
+ Resource parent = entityManager.find(Resource.class, parentResource.getId());
+ List<CreateResourceHistory> historyList = parent.getCreateChildResourceRequests();
+
+ assert historyList.size() == 1 : "Incorrect number of children found. Expected: 1, Found: "
+ + historyList.size();
+
+ CreateResourceHistory historyItem = historyList.get(0);
+
+ assert historyItem.getStatus() == CreateResourceStatus.SUCCESS : "Incorrect status for history item. Expected: Success, Found: "
+ + historyItem.getStatus();
+ assert historyItem.getNewResourceKey().equals("mockResourceKey") : "Incorrect resource key for history item. Expected: mockResourceKey, Found: "
+ + historyItem.getNewResourceKey();
+ assert historyItem.getErrorMessage() == null : "Error message found for successful call";
+ assert historyItem.getConfiguration() != null : "Null configuration found for history item";
+ } finally {
+ getTransactionManager().rollback();
+ entityManager.close();
+ }
+
+ // Invoke the same callbacks the plugin container would to actually commit the new Resource to inventory.
+ resourceFactoryManager.completeCreateResource(new CreateResourceResponse(history1.getId(), "newResource", "key",
+ CreateResourceStatus.SUCCESS, null, new Configuration()));
+ Resource resource = new Resource(1000000);
+ resource.setUuid(UUID.randomUUID().toString());
+ resource.setResourceType(configBackedChildResourceType2);
+ long randomLong = UUID.randomUUID().getLeastSignificantBits();
+ resource.setResourceKey(String.valueOf("key-" + randomLong));
+ resource.setName("name-" + randomLong);
+ resource.setParentResource(parentResource);
+ discoveryBoss.addResource(resource, overlord.getId());
+
+ // Now try to create another Resource of the same singleton type - this should fail.
+ try {
+ CreateResourceHistory history2 = resourceFactoryManager.createResource(overlord, parentResource.getId(),
+ configBackedChildResourceType2.getId(), "newResource2", null, resourceConfiguration);
+ fail("Creating a singleton that already existed succeeded: " + history2);
+ } catch (EJBException e) {
+ assertEquals(String.valueOf(e.getCause()), RuntimeException.class, e.getCause().getClass());
+ assertTrue(String.valueOf(e.getCause()), e.getCause().getMessage().contains("singleton"));
+ }
+ }
+
+ @Test
+ public void createSingletonResourceViaPackage() throws Exception {
+ // Setup
+ mockAgentService.setCreateReturnStatus(CreateResourceStatus.SUCCESS);
+
+ // Assemble call parameters
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ String packageName = "testDataResourcePackage";
+ String packageVersion = "1.0.0";
+ int architectureId = 1; // easier than loading a specific architecture from the DB, just use the first one
+
+ Configuration deploymentTimeConfiguration = new Configuration();
+ deploymentTimeConfiguration.put(new PropertySimple("testProperty", "testValue"));
+
+ // This file should be in the classpath, so use it for the artifact content
+ URL contentResource = this.getClass().getClassLoader().getResource("jndi.properties");
+ assert contentResource != null : "Could not load jndi.properties as package content";
+
+ InputStream packageInputStream = contentResource.openStream();
+
+ // Test
+ CreateResourceHistory history1 = resourceFactoryManager.createResource(overlord, parentResource.getId(), contentBackedChildResourceType.getId(),
+ "newResource", null, packageName, packageVersion, architectureId, deploymentTimeConfiguration,
+ packageInputStream);
+
+ // Verify
+ EntityManager entityManager = null;
+ try {
+ getTransactionManager().begin();
+ entityManager = getEntityManager();
+
+ Resource parent = entityManager.find(Resource.class, parentResource.getId());
+ List<CreateResourceHistory> historyList = parent.getCreateChildResourceRequests();
+
+ assert historyList.size() == 1 : "Incorrect number of children found. Expected: 1, Found: "
+ + historyList.size();
+
+ CreateResourceHistory historyItem = historyList.get(0);
+
+ assert historyItem.getStatus() == CreateResourceStatus.SUCCESS : "Incorrect status for history item. Expected: Success, Found: "
+ + historyItem.getStatus();
+ assert historyItem.getNewResourceKey().equals("mockResourceKey") : "Incorrect resource key for history item. Expected: mockResourceKey, Found: "
+ + historyItem.getNewResourceKey();
+ assert historyItem.getErrorMessage() == null : "Error message found for successful call";
+ } finally {
+ getTransactionManager().rollback();
+ entityManager.close();
+ }
+
+ // Invoke the same callbacks the plugin container would to actually commit the new Resource to inventory.
+ resourceFactoryManager.completeCreateResource(new CreateResourceResponse(history1.getId(), "newResource", "key",
+ CreateResourceStatus.SUCCESS, null, new Configuration()));
+ Resource resource = new Resource(2000000);
+ resource.setUuid(UUID.randomUUID().toString());
+ resource.setResourceType(contentBackedChildResourceType);
+ long randomLong = UUID.randomUUID().getLeastSignificantBits();
+ resource.setResourceKey(String.valueOf("key-" + randomLong));
+ resource.setName("name-" + randomLong);
+ resource.setParentResource(parentResource);
+ discoveryBoss.addResource(resource, overlord.getId());
+
+ // Now try to create another Resource of the same singleton type - this should fail.
+ try {
+ CreateResourceHistory history2 = resourceFactoryManager.createResource(overlord, parentResource.getId(),
+ contentBackedChildResourceType.getId(), "newResource2", null, packageName, packageVersion,
+ architectureId, deploymentTimeConfiguration, packageInputStream);
+ fail("Creating a singleton that already existed succeeded: " + history2);
+ } catch (EJBException e) {
+ assertEquals(String.valueOf(e.getCause()), RuntimeException.class, e.getCause().getClass());
+ assertTrue(String.valueOf(e.getCause()), e.getCause().getMessage().contains("singleton"));
+ }
+ }
+
+ @Test
+ public void deleteResource() throws Exception {
+ // Setup
+ mockAgentService.setDeleteReturnStatus(DeleteResourceStatus.SUCCESS);
+ Resource deleteMe = addResourceToParent();
+
+ assert deleteMe != null : "Child resource to be deleted was not correctly added in the first place";
+
+ // Assemble call parameters
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ // Test
+ resourceFactoryManager.deleteResource(overlord, deleteMe.getId());
+
+ // Verify
+ EntityManager entityManager = null;
+
+ try {
+ getTransactionManager().begin();
+ entityManager = getEntityManager();
+
+ Resource parent = entityManager.find(Resource.class, parentResource.getId());
+ Set<Resource> childResources = parent.getChildResources();
+
+ assert childResources.size() == 1 : "Child resource not found on the parent";
+
+ Resource deletedResource = childResources.iterator().next();
+
+ assert deletedResource.getInventoryStatus() == InventoryStatus.DELETED : "Inventory status for deleted resource was incorrect. Expected: Deleted, Found: "
+ + deletedResource.getInventoryStatus();
+ } finally {
+ getTransactionManager().rollback();
+ entityManager.close();
+ }
+ }
+
+ @Test
+ public void deleteResourceFailure() throws Exception {
+ // Setup
+ mockAgentService.setDeleteReturnStatus(DeleteResourceStatus.FAILURE);
+ Resource deleteMe = addResourceToParent();
+
+ assert deleteMe != null : "Child resource to be deleted was not correctly added in the first place";
+
+ // Assemble call parameters
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ // Test
+ resourceFactoryManager.deleteResource(overlord, deleteMe.getId());
+
+ // Verify
+ EntityManager entityManager = null;
+
+ try {
+ getTransactionManager().begin();
+ entityManager = getEntityManager();
+
+ Resource parent = entityManager.find(Resource.class, parentResource.getId());
+ Set<Resource> childResources = parent.getChildResources();
+
+ assert childResources.size() == 1 : "Child resource not found on the parent";
+
+ Resource deletedResource = childResources.iterator().next();
+
+ assert deletedResource.getInventoryStatus() == InventoryStatus.COMMITTED : "Inventory status for deleted resource was incorrect. Expected: Committed, Found: "
+ + deletedResource.getInventoryStatus();
+ } finally {
+ getTransactionManager().rollback();
+ entityManager.close();
+ }
+ }
+
+ @Test
+ public void createHistory() {
+ // Setup
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ // Have to call getMap() on the configuration instances to trigger lazy instantiation of the properties map
+ Configuration resourceConfiguration;
+
+ resourceConfiguration = new Configuration();
+ resourceConfiguration.getMap();
+ resourceFactoryManager.createResource(overlord, parentResource.getId(), configBackedChildResourceType1.getId(), "resource1",
+ (Configuration) null, resourceConfiguration);
+
+ resourceConfiguration = new Configuration();
+ resourceConfiguration.getMap();
+ resourceFactoryManager.createResource(overlord, parentResource.getId(), configBackedChildResourceType1.getId(), "resource2",
+ (Configuration) null, resourceConfiguration);
+
+ resourceConfiguration = new Configuration();
+ resourceConfiguration.getMap();
+ resourceFactoryManager.createResource(overlord, parentResource.getId(), configBackedChildResourceType1.getId(), "resource3",
+ (Configuration) null, resourceConfiguration);
+
+ // Verify
+ int numRequestsInHistory = resourceFactoryManager.getCreateChildResourceHistoryCount(parentResource.getId(),
+ null, null);
+
+ assert numRequestsInHistory == 3 : "Incorrect history count. Expected: 3, Found: " + numRequestsInHistory;
+
+ PageControl pageControl = new PageControl(0, 10000);
+ pageControl.initDefaultOrderingField("createdResourceName");
+ PageList<CreateResourceHistory> historyList = resourceFactoryManager.findCreateChildResourceHistory(overlord,
+ parentResource.getId(), null, null, pageControl);
+
+ assert historyList.getTotalSize() == 3 : "Incorrect number of entries in page list. Expected: 3, Found: "
+ + historyList.getTotalSize();
+
+ assert historyList.get(0).getCreatedResourceName().equals("resource1") : "History entry 1 is invalid";
+ assert historyList.get(1).getCreatedResourceName().equals("resource2") : "History entry 2 is invalid";
+ assert historyList.get(2).getCreatedResourceName().equals("resource3") : "History entry 3 is invalid";
+ }
+
+ @Test
+ public void deleteHistory() throws Exception {
+ // Setup
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ Resource resource1 = addResourceToParent();
+ Resource resource2 = addResourceToParent();
+ Resource resource3 = addResourceToParent();
+
+ // Delete each one, which should add a history item
+ resourceFactoryManager.deleteResource(overlord, resource1.getId());
+ resourceFactoryManager.deleteResource(overlord, resource2.getId());
+ resourceFactoryManager.deleteResource(overlord, resource3.getId());
+
+ // Verify
+ int numRequestsInHistory = resourceFactoryManager.getDeleteChildResourceHistoryCount(parentResource.getId(),
+ null, null);
+
+ assert numRequestsInHistory == 3 : "Incorrect history count. Expected: 3, Found: " + numRequestsInHistory;
+
+ PageControl pageControl = new PageControl(0, 10000);
+ pageControl.initDefaultOrderingField("drh.id");
+ PageList<DeleteResourceHistory> historyList = resourceFactoryManager.findDeleteChildResourceHistory(overlord,
+ parentResource.getId(), null, null, pageControl);
+
+ assert historyList.getTotalSize() == 3 : "Incorrect number of entries in page list. Expected: 3, Found: "
+ + historyList.getTotalSize();
+
+ assert historyList.get(0).getResource().getId() == resource1.getId() : "History entry 1 is invalid";
+ assert historyList.get(1).getResource().getId() == resource2.getId() : "History entry 2 is invalid";
+ assert historyList.get(2).getResource().getId() == resource3.getId() : "History entry 3 is invalid";
+ }
+
+ @Test
+ public void getHistoryItem() throws Exception {
+ // Setup
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ Configuration resourceConfiguration = new Configuration();
+ resourceConfiguration.getMap();
+ resourceFactoryManager.createResource(overlord, parentResource.getId(), configBackedChildResourceType1.getId(),
+ "NewResource", null, resourceConfiguration);
+ PageList<CreateResourceHistory> historyList = resourceFactoryManager.findCreateChildResourceHistory(overlord,
+ parentResource.getId(), null, null, new PageControl(0, 1000));
+ int historyItemId = historyList.get(0).getId();
+
+ // Test
+ CreateResourceHistory historyItem = resourceFactoryManager.getCreateHistoryItem(historyItemId);
+
+ // Verify
+ assert historyItem != null : "Null history item returned from call";
+ assert historyItem.getCreatedResourceName().equals("NewResource");
+ }
+
+ // Private --------------------------------------------
+
+ /**
+ * Creates a test resource in the database for testing purposes.
+ *
+ * @return persisted but detached resource
+ *
+ * @throws Exception if anything goes wrong
+ */
+ private void setupResourceEnvironment() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ try {
+ // Create parent resource type
+ parentResourceType = new ResourceType("platform-" + System.currentTimeMillis(), TEST_PLUGIN_NAME,
+ ResourceCategory.PLATFORM, null);
+ em.persist(parentResourceType);
+
+ // Create child resource type to parent. Artifact type lives under this resource type.
+ contentBackedChildResourceType = new ResourceType("service-" + System.currentTimeMillis(), TEST_PLUGIN_NAME,
+ ResourceCategory.SERVICE, parentResourceType);
+ contentBackedChildResourceType.setCreateDeletePolicy(CreateDeletePolicy.BOTH);
+ contentBackedChildResourceType.setCreationDataType(ResourceCreationDataType.CONTENT);
+ contentBackedChildResourceType.setSingleton(true);
+ em.persist(contentBackedChildResourceType);
+
+ // Create artifact type under child resource type that is marked as the creation artifact type
+ packageType = new PackageType();
+ packageType.setName("artifact-" + System.currentTimeMillis());
+ packageType.setDescription("");
+ packageType.setCategory(PackageCategory.DEPLOYABLE);
+ packageType.setDisplayName("TestResourceArtifact");
+ packageType.setCreationData(true);
+ packageType.setResourceType(contentBackedChildResourceType);
+ em.persist(packageType);
+
+ // Link artifact type and child resource type
+ contentBackedChildResourceType.addPackageType(packageType);
+
+ configBackedChildResourceType1 = new ResourceType("service1-" + System.currentTimeMillis(), TEST_PLUGIN_NAME,
+ ResourceCategory.SERVICE, parentResourceType);
+ configBackedChildResourceType1.setCreateDeletePolicy(CreateDeletePolicy.BOTH);
+ configBackedChildResourceType1.setCreationDataType(ResourceCreationDataType.CONFIGURATION);
+ em.persist(configBackedChildResourceType1);
+
+ configBackedChildResourceType2 = new ResourceType("service2-" + System.currentTimeMillis(), TEST_PLUGIN_NAME,
+ ResourceCategory.SERVICE, parentResourceType);
+ configBackedChildResourceType2.setCreateDeletePolicy(CreateDeletePolicy.BOTH);
+ configBackedChildResourceType2.setCreationDataType(ResourceCreationDataType.CONFIGURATION);
+ configBackedChildResourceType2.setSingleton(true);
+ em.persist(configBackedChildResourceType2);
+
+ // Create parent resource off of which to hang created resources
+ parentResource = new Resource("parent" + System.currentTimeMillis(), "name", parentResourceType);
+ parentResource.setUuid("" + new Random().nextInt());
+ em.persist(parentResource);
+ } catch (Exception e) {
+ System.out.println(e);
+ getTransactionManager().rollback();
+ throw e;
+ }
+
+ getTransactionManager().commit();
+ } finally {
+ em.close();
+ }
+ }
+
+ /**
+ * Deletes a previously persisted resource from the database.
+ *
+ * @throws Exception if anything goes wrong
+ */
+ private void teardownResourceEnvironment() throws Exception {
+ if (parentResource != null) {
+
+ List<Integer> deletedIds = resourceManager.uninventoryResource(overlord, parentResource.getId());
+ for (Integer deletedResourceId : deletedIds) {
+ resourceManager.uninventoryResourceAsyncWork(overlord, deletedResourceId);
+ }
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ // Remove the children first.
+ ResourceType deleteMeType = em.find(ResourceType.class, contentBackedChildResourceType.getId());
+ em.remove(deleteMeType);
+
+ deleteMeType = em.find(ResourceType.class, configBackedChildResourceType1.getId());
+ em.remove(deleteMeType);
+
+ deleteMeType = em.find(ResourceType.class, configBackedChildResourceType2.getId());
+ em.remove(deleteMeType);
+
+ deleteMeType = em.find(ResourceType.class, parentResourceType.getId());
+ em.remove(deleteMeType);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ System.out.println(e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+
+ throw e;
+ } finally {
+ em.close();
+ }
+ }
+ }
+
+ /**
+ * Creates a new child resource on the test class' parent resource.
+ *
+ * @return the newly created resource
+ *
+ * @throws Exception if anything goes wrong
+ */
+ private Resource addResourceToParent() throws Exception {
+ Resource resource = null;
+
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ try {
+ try {
+ resource = new Resource("child" + System.currentTimeMillis(), "name", parentResourceType);
+ resource.setUuid("" + new Random().nextInt());
+ resource.setParentResource(parentResource);
+ resource.setInventoryStatus(InventoryStatus.COMMITTED);
+ em.persist(resource);
+ } catch (Exception e) {
+ System.out.println(e);
+ getTransactionManager().rollback();
+ }
+
+ getTransactionManager().commit();
+ } finally {
+ em.close();
+ }
+
+ return resource;
+ }
+
+ // Inner Classes --------------------------------------------
+
+ /**
+ * Mocks out the call to the agent. Different results can be achieved by manipulating the attributes on the instance
+ * that is registered with the server communications service.
+ */
+ private class MockResourceFactoryAgentService implements ResourceFactoryAgentService {
+ // Attributes --------------------------------------------
+
+ private CreateResourceStatus createReturnStatus = CreateResourceStatus.SUCCESS;
+
+ private DeleteResourceStatus deleteReturnStatus = DeleteResourceStatus.SUCCESS;
+
+ // Public --------------------------------------------
+
+ /**
+ * Indicates what the result of a call to createResource should be.
+ *
+ * @param createReturnStatus indicates the type of response to send
+ */
+ public void setCreateReturnStatus(CreateResourceStatus createReturnStatus) {
+ this.createReturnStatus = createReturnStatus;
+ }
+
+ /**
+ * Indicates what the result of a call to deleteResource should be.
+ *
+ * @param deleteReturnStatus indicates the type of response to send
+ */
+ public void setDeleteReturnStatus(DeleteResourceStatus deleteReturnStatus) {
+ this.deleteReturnStatus = deleteReturnStatus;
+ }
+
+ // ResourceFactoryAgentService Implementation --------------------------------------------
+
+ public void createResource(CreateResourceRequest request) throws PluginContainerException {
+ CreateResourceResponse response = null;
+
+ switch (createReturnStatus) {
+ case SUCCESS: {
+ response = new CreateResourceResponse(request.getRequestId(), "mockResourceName", "mockResourceKey",
+ CreateResourceStatus.SUCCESS, null, request.getResourceConfiguration());
+ break;
+ }
+
+ case FAILURE: {
+ response = new CreateResourceResponse(request.getRequestId(), null, null, CreateResourceStatus.FAILURE,
+ "errorMessage", request.getResourceConfiguration());
+ break;
+ }
+ }
+
+ ResourceFactoryManagerBeanTest.this.resourceFactoryManager.completeCreateResource(response);
+ }
+
+ public void deleteResource(DeleteResourceRequest request) throws PluginContainerException {
+ DeleteResourceResponse response = null;
+
+ switch (deleteReturnStatus) {
+ case SUCCESS: {
+ response = new DeleteResourceResponse(request.getRequestId(), deleteReturnStatus, null);
+ break;
+ }
+
+ case FAILURE: {
+ response = new DeleteResourceResponse(request.getRequestId(), deleteReturnStatus, "errorMessage");
+ break;
+ }
+ }
+
+ ResourceFactoryManagerBeanTest.this.resourceFactoryManager.completeDeleteResourceRequest(response);
+ }
+
+ public CreateResourceResponse executeCreateResourceImmediately(CreateResourceRequest request)
+ throws PluginContainerException {
+ return null;
+ }
+
+ public DeleteResourceResponse executeDeleteResourceImmediately(DeleteResourceRequest request)
+ throws PluginContainerException {
+ return null;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceGroupManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceGroupManagerBeanTest.java
new file mode 100644
index 0000000..7c8c632
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceGroupManagerBeanTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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.enterprise.server.resource.test;
+
+import javax.persistence.EntityManager;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.authz.Role;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.enterprise.server.authz.PermissionException;
+import org.rhq.enterprise.server.resource.group.ResourceGroupAlreadyExistsException;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
+import org.rhq.enterprise.server.resource.group.ResourceGroupNotFoundException;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.SessionTestHelper;
+
+public class ResourceGroupManagerBeanTest extends AbstractEJB3Test {
+ private static ResourceGroupManagerLocal resourceGroupManager;
+
+ @BeforeMethod
+ @SuppressWarnings("unused")
+ private void init() {
+ try {
+ resourceGroupManager = LookupUtil.getResourceGroupManager();
+ prepareScheduler();
+ } catch (Throwable t) {
+ // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
+ // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+
+ @AfterMethod
+ @SuppressWarnings("unused")
+ private void after() {
+ try {
+ unprepareScheduler();
+ } catch (Throwable t) {
+ // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
+ // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+
+ @Test(groups = "integration.session")
+ public void testGetCompatibleGroupById() throws Exception {
+ getTransactionManager().begin();
+ try {
+ EntityManager em = getEntityManager();
+
+ /* bootstrap */
+ ResourceType type = new ResourceType("type", "plugin", ResourceCategory.PLATFORM, null);
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole");
+ ResourceGroup compatGroup = new ResourceGroup("testCompatGroup", type);
+ compatGroup.addRole(testRole);
+ em.persist(type);
+ em.persist(compatGroup);
+ em.flush();
+ testRole.addResourceGroup(compatGroup);
+ em.merge(testRole);
+ em.flush();
+
+ int id = compatGroup.getId();
+ try {
+ resourceGroupManager.getResourceGroupById(testSubject, id, null);
+ } catch (ResourceGroupNotFoundException e) {
+ assert (false) : "Could not find recently persisted compatible group by id";
+ } catch (PermissionException se) {
+ assert (false) : "Incorrect permissions when getting compatible group by id";
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test(groups = "integration.session")
+ public void testUpdateGroupDescription() throws Exception {
+ getTransactionManager().begin();
+ try {
+ EntityManager em = getEntityManager();
+
+ /* bootstrap */
+ ResourceType type = new ResourceType("type", "plugin", ResourceCategory.PLATFORM, null);
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole");
+ testRole.addPermission(Permission.MANAGE_INVENTORY);
+ ResourceGroup compatGroup = new ResourceGroup("group1", type);
+ compatGroup.addRole(testRole);
+ em.persist(type);
+ em.persist(compatGroup);
+ em.flush();
+ testRole.addResourceGroup(compatGroup);
+ em.merge(testRole);
+ em.flush();
+
+ int id = compatGroup.getId();
+ try {
+ ResourceGroup oldGroup = resourceGroupManager.getResourceGroupById(testSubject, id, null);
+ oldGroup.setDescription("new description goes here ");
+ resourceGroupManager.updateResourceGroup(testSubject, oldGroup);
+ } catch (ResourceGroupAlreadyExistsException rgaee) {
+ fail("ResourceGroupAlreadyExistsException should NOT have been thrown.");
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test(groups = "integration.session")
+ public void testUpdateGroupName() throws Exception {
+ getTransactionManager().begin();
+ try {
+ EntityManager em = getEntityManager();
+
+ /* bootstrap */
+ ResourceType type = new ResourceType("type", "plugin", ResourceCategory.PLATFORM, null);
+ Subject testSubject = SessionTestHelper.createNewSubject(em, "testSubject");
+ Role testRole = SessionTestHelper.createNewRoleForSubject(em, testSubject, "testRole");
+ testRole.addPermission(Permission.MANAGE_INVENTORY);
+ ResourceGroup compatGroup = new ResourceGroup("group1", type);
+ compatGroup.addRole(testRole);
+ em.persist(type);
+ em.persist(compatGroup);
+ em.flush();
+ testRole.addResourceGroup(compatGroup);
+ em.merge(testRole);
+ em.flush();
+
+ int id = compatGroup.getId();
+ try {
+ ResourceGroup oldGroup = resourceGroupManager.getResourceGroupById(testSubject, id, null);
+ oldGroup.setName("newGroup1");
+ resourceGroupManager.updateResourceGroup(testSubject, oldGroup);
+ } catch (ResourceGroupAlreadyExistsException rgaee) {
+ fail("ResourceGroupAlreadyExistsException should NOT have been thrown.");
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ /*
+ * CGroup getCompatibleGroupById(Subject user, int id) MGroup getMixedGroupById(Subject user, int id) List<>
+ * getCompatibleGroupsByResourceType(Subject user, ResourceType type, PC) int getCompatibleGroupCount(Subject
+ * user) int getMixedGroupCount(Subject user)
+ */
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java
new file mode 100644
index 0000000..deac357
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java
@@ -0,0 +1,267 @@
+/*
+ * 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.enterprise.server.resource.test;
+
+import java.util.List;
+import java.util.Random;
+import java.util.UUID;
+
+import javax.persistence.EntityManager;
+import javax.transaction.NotSupportedException;
+import javax.transaction.SystemException;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceError;
+import org.rhq.core.domain.resource.ResourceErrorType;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.discovery.DiscoveryServerServiceImpl;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.metadata.test.UpdatePluginMetadataTestBase;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Test for {@link ResourceManagerLocal} SLSB.
+ */
+@Test
+public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase {
+ private Subject superuser;
+ private Resource newResource;
+
+ TestServerCommunicationsService agentServiceContainer;
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ superuser = LookupUtil.getSubjectManager().getOverlord();
+ newResource = createNewResourceWithNewType();
+ }
+
+ @AfterMethod
+ public void afterMethod() throws Exception {
+ deleteNewResourceAgentResourceType(newResource);
+ }
+
+ public void testResourceErrors() {
+ ResourceError error;
+ List<ResourceError> errors;
+ DiscoveryServerServiceImpl serverService = new DiscoveryServerServiceImpl();
+
+ errors = resourceManager.findResourceErrors(superuser, newResource.getId(),
+ ResourceErrorType.INVALID_PLUGIN_CONFIGURATION);
+ assert errors.size() == 0;
+
+ error = new ResourceError(newResource, ResourceErrorType.INVALID_PLUGIN_CONFIGURATION, "test summary",
+ "test detail", 12345);
+
+ // simulate the agent notifying the server about an error
+ // this will exercise the addResourceError in the SLSB
+ serverService.setResourceError(error);
+ errors = resourceManager.findResourceErrors(superuser, newResource.getId(),
+ ResourceErrorType.INVALID_PLUGIN_CONFIGURATION);
+ assert errors.size() == 1;
+ error = errors.get(0);
+ assert error.getId() > 0;
+ assert error.getSummary().equals("test summary");
+ assert error.getDetail().equals("test detail");
+ assert error.getErrorType() == ResourceErrorType.INVALID_PLUGIN_CONFIGURATION;
+ assert error.getTimeOccurred() == 12345;
+
+ // simulate the agent notifying the server about another error.
+ // there will only be a single invalid plugin config allowed; the prior one will be deleted
+ // this will exercise the addResourceError and deleteResourceError in the SLSB
+ error.setId(0);
+ error.setTimeOccurred(567890);
+ error.setSummary("another summary");
+ error.setDetail("another detail");
+ serverService.setResourceError(error);
+ errors = resourceManager.findResourceErrors(superuser, newResource.getId(),
+ ResourceErrorType.INVALID_PLUGIN_CONFIGURATION);
+ assert errors.size() == 1;
+ error = errors.get(0);
+ assert error.getId() > 0;
+ assert error.getSummary().equals("another summary");
+ assert error.getDetail().equals("another detail");
+ assert error.getErrorType() == ResourceErrorType.INVALID_PLUGIN_CONFIGURATION;
+ assert error.getTimeOccurred() == 567890;
+
+ resourceManager.deleteResourceError(superuser, error.getId());
+ errors = resourceManager.findResourceErrors(superuser, newResource.getId(),
+ ResourceErrorType.INVALID_PLUGIN_CONFIGURATION);
+ assert errors.size() == 0;
+ }
+
+ public void testResourceLineage() throws Exception {
+ // given a resource id for the leaf resource in a resource hierarchy
+ int leafResourceId = givenASampleResourceHierarchy();
+
+ // when
+ List<Resource> resourceLineage = resourceManager.getResourceLineage(leafResourceId);
+
+ assertEquals(resourceLineage.size(), 4);
+
+ // then
+ StringBuilder stringBuilder = new StringBuilder();
+ for (Resource resource : resourceLineage) {
+ stringBuilder.append(resource.getName());
+ if (resourceLineage.indexOf(resource) != resourceLineage.size() - 1) {
+ stringBuilder.append("::");
+ }
+ }
+ System.err.println(stringBuilder.toString());
+
+ // cleanup the DB
+ for (int i = resourceLineage.size() - 1; i >= 0; i--) {
+ deleteNewResourceAgentResourceType(resourceLineage.get(i));
+ }
+ }
+
+ private int givenASampleResourceHierarchy() throws NotSupportedException, SystemException {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ int leafResourceId = 0;
+ try {
+ ResourceType platformType = createResourceType(em, "platform" + System.currentTimeMillis(), "test", null,
+ ResourceCategory.PLATFORM);
+ ResourceType appserverType = createResourceType(em, "jboss AS 5" + System.currentTimeMillis(), "jbossas5",
+ platformType, ResourceCategory.SERVER);
+ ResourceType jvmType = createResourceType(em, "JVM" + System.currentTimeMillis(), "jbossas5",
+ appserverType, ResourceCategory.SERVICE);
+ ResourceType memType = createResourceType(em, "Memory Subsystem" + System.currentTimeMillis(), "jbossas5",
+ jvmType, ResourceCategory.SERVICE);
+ Agent agent = new Agent("agent" + System.currentTimeMillis(), "host" + System.currentTimeMillis(), 1, "",
+ "token" + System.currentTimeMillis());
+ em.persist(agent);
+ em.flush();
+
+ Resource platform = createResource(em, platformType, agent, "platformKey" + System.currentTimeMillis(),
+ "host.dev.corp", null);
+ Resource appserver = createResource(em, appserverType, agent, "JEAP" + System.currentTimeMillis(),
+ "JBOSS EAP 5.1.1", platform);
+ Resource jvm = createResource(em, jvmType, agent, "jvm" + System.currentTimeMillis(), "JBoss AS JVM",
+ appserver);
+ Resource memSubystem = createResource(em, memType, agent, "mem" + System.currentTimeMillis(),
+ "Memory Subsystem", jvm);
+ leafResourceId = memSubystem.getId();
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ System.out.println("CANNOT Prepare TEST: Cause: " + e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+ } finally {
+ em.close();
+ }
+ return leafResourceId;
+ }
+
+ private Resource createResource(EntityManager em, ResourceType platformType, Agent agent, String resourceKey,
+ String resourceName, Resource parent) {
+ Resource resource = new Resource(resourceKey, resourceName, platformType);
+ resource.setUuid(UUID.randomUUID().toString());
+ resource.setAgent(agent);
+ resource.setParentResource(parent);
+ em.persist(resource);
+ return resource;
+ }
+
+ private ResourceType createResourceType(EntityManager em, String name, String pluginName,
+ ResourceType parentResourceType, ResourceCategory resourceCategory) {
+ ResourceType platformType = new ResourceType(name, pluginName, resourceCategory, parentResourceType);
+ ResourceType resourceType = platformType;
+ em.persist(resourceType);
+ return resourceType;
+ }
+
+ private Resource createNewResourceWithNewType() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ Resource resource;
+
+ try {
+ try {
+ ResourceType resourceType = new ResourceType("plat" + System.currentTimeMillis(), "test",
+ ResourceCategory.PLATFORM, null);
+
+ em.persist(resourceType);
+
+ Agent agent = new Agent("testagent", "testaddress", 16163, "", "testtoken");
+ em.persist(agent);
+ em.flush();
+
+ resource = new Resource("reskey" + System.currentTimeMillis(), "resname", resourceType);
+ resource.setUuid("" + new Random().nextInt());
+ resource.setAgent(agent);
+ em.persist(resource);
+ } catch (Exception e) {
+ System.out.println("CANNOT PREPARE TEST: " + e);
+ getTransactionManager().rollback();
+ throw e;
+ }
+
+ getTransactionManager().commit();
+ } finally {
+ em.close();
+ }
+
+ return resource;
+ }
+
+ private void deleteNewResourceAgentResourceType(Resource resource) throws Exception {
+ if (resource != null) {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ Resource res = em.find(Resource.class, resource.getId());
+ System.out.println("Removing " + res + "...");
+ List<Integer> deletedIds = resourceManager.uninventoryResource(superuser, res.getId());
+ for (Integer deletedResourceId : deletedIds) {
+ resourceManager.uninventoryResourceAsyncWork(superuser, deletedResourceId);
+ }
+ em.flush();
+
+ ResourceType type = em.find(ResourceType.class, resource.getResourceType().getId());
+ System.out.println("Removing " + type + "...");
+ em.remove(type);
+ em.flush();
+
+ // NOTE: No need to remove the Agent entity, since uninventorying the platform will do that automatically.
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ System.out.println("CANNOT CLEAN UP TEST: Cause: " + e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+ } finally {
+ em.close();
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceStorageTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceStorageTest.java
new file mode 100644
index 0000000..b8fce18
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceStorageTest.java
@@ -0,0 +1,222 @@
+/*
+ * 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.enterprise.server.resource.test;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+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.domain.resource.composite.ResourceComposite;
+import org.rhq.core.domain.resource.group.GroupCategory;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
+import org.rhq.core.domain.util.OrderingField;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.authz.AuthorizationManagerBean;
+import org.rhq.enterprise.server.authz.AuthorizationManagerLocal;
+import org.rhq.enterprise.server.discovery.DiscoveryBossLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerBean;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+public class ResourceStorageTest extends AbstractEJB3Test {
+ private Log log = LogFactory.getLog(ResourceStorageTest.class);
+
+ // TODO GH: Fixme (setup non-super user and group)@Test(groups = "integration.ejb3")
+ public void testFindResourceComposite() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ PageControl pc = new PageControl(1, 5, new OrderingField("res.name", PageOrdering.ASC));
+ Subject subject = subjectManager.loginUnauthenticated("ghinkle");
+
+ //Subject subject = subjectManager.getOverlord();
+ subject = createSession(subject);
+ ResourceType t = em.getReference(ResourceType.class, new Integer(501064));
+ String typeNameFilter = t == null ? null : t.getName();
+ PageList<ResourceComposite> resources = resourceManager.findResourceComposites(subject,
+ ResourceCategory.SERVER, typeNameFilter, null, null, "g", false, pc);
+ System.out.println("Found resource composites: " + resources.size());
+ for (ResourceComposite resourceComposite : resources) {
+ System.out.println("\t" + resourceComposite);
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ // TODO GH: Is this supposed to work? @Test(groups = "integration.ejb3")
+ @SuppressWarnings("unchecked")
+ public void testBindOrderBy() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ log.error("QUERY TEST!!");
+ Query q = em.createQuery("SELECT r FROM Resource r ORDER BY :col");
+ q.setParameter("col", "r.name desc");
+ List<Resource> resources = q.getResultList();
+ System.out.println("Sorted resources: ");
+ for (Resource r : resources) {
+ System.out.println("\t" + r);
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test(groups = "integration.ejb3")
+ public void testMixedGroupCompositeQuery() throws Exception {
+ getTransactionManager().begin();
+ try {
+ ResourceGroupManagerLocal groupManager = LookupUtil.getResourceGroupManager();
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ PageControl pc = new PageControl(1, 5, new OrderingField("rg.name", PageOrdering.ASC));
+
+ //Subject subject = subjectManager.loginUnauthenticated("ghinkle");
+ Subject subject = subjectManager.getOverlord();
+ subject = createSession(subject);
+ List<ResourceGroupComposite> groups = groupManager.findResourceGroupComposites(subject,
+ GroupCategory.MIXED, null, null, null, null, null, null, pc);
+ System.out.println("Found mixed groups: " + groups.size());
+ for (ResourceGroupComposite group : groups) {
+ System.out.println("\t" + group);
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test(groups = "integration.ejb3")
+ public void testCompatibleGroupCompositeQuery() throws Exception {
+ getTransactionManager().begin();
+ try {
+ ResourceGroupManagerLocal groupManager = LookupUtil.getResourceGroupManager();
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ PageControl pc = new PageControl(0, 5, new OrderingField("rg.name", PageOrdering.ASC));
+ PageList<ResourceGroupComposite> groups = groupManager.findResourceGroupComposites(subjectManager
+ .getOverlord(), GroupCategory.COMPATIBLE, null, null, null, null, null, null, pc);
+ System.out.println("Found compatible groups: " + groups.getTotalSize());
+ for (ResourceGroupComposite group : groups) {
+ System.out.println("\t" + group);
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test(groups = "integration.ejb3")
+ public void testConstructorQuery() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ Query q = em
+ .createQuery("SELECT new org.rhq.enterprise.server.resource.test.ResourceWithStatus(a.availabilityType,r) "
+ + "FROM Resource r, Availability a "
+ + "WHERE r.id = a.resource.id "
+ + "AND a.startTime = (SELECT MAX(aa.startTime) FROM Availability aa WHERE aa.resource.id = r.id)");
+ List<ResourceWithStatus> resourceWithStatuses = q.getResultList();
+
+ for (ResourceWithStatus r : resourceWithStatuses) {
+ System.out.println(r.getAvailabilityType() + " - " + r.getResource().getName());
+ System.out.println("\tchildren: " + r.getResource().getChildResources().size());
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test(groups = "integration.ejb3")
+ public void getDeadResources() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ Query q = em
+ .createQuery("SELECT new org.rhq.enterprise.server.resource.test.ResourceWithStatus(a.availabilityType,r) "
+ + "FROM Resource r, Availability a "
+ + "WHERE r.id = a.resource.id "
+ + "AND a.availabilityType = 1 "
+ + "AND a.startTime = (SELECT MAX(aa.startTime) FROM Availability aa WHERE aa.resource.id = r.id)");
+ List<ResourceWithStatus> resourceWithStatuses = q.getResultList();
+
+ System.out.println("Resource currently down");
+ for (ResourceWithStatus r : resourceWithStatuses) {
+ System.out.println(r.getAvailabilityType() + " - " + r.getResource().getName());
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @Test(groups = "integration.ejb3")
+ public void discoveryQueueTest() throws Exception {
+ getTransactionManager().begin();
+ try {
+ DiscoveryBossLocal discoveryBoss = LookupUtil.getDiscoveryBoss();
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ Subject rhqadmin = subjectManager.loginUnauthenticated("rhqadmin");
+ rhqadmin = createSession(rhqadmin);
+
+ Map<Resource, List<Resource>> queue = discoveryBoss.getQueuedPlatformsAndServers(rhqadmin, PageControl
+ .getUnlimitedInstance());
+ for (Resource root : queue.keySet()) {
+ System.out.println("Queue root resource: " + root);
+ }
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ @Test(groups = "integration.ejb3")
+ public void resourceTest() throws Exception {
+ // TODO GH: Implement actual tests
+
+ System.out.println("foo");
+
+ ResourceManagerLocal resourceManager = (ResourceManagerLocal) getInitialContext().lookup(
+ ResourceManagerBean.class.getSimpleName() + "/local");
+
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ // (SubjectManagerLocal) getInitialContext().lookup(SubjectManagerBean.class.getSimpleName() + "/local");
+
+ AuthorizationManagerLocal authorizationManager = (AuthorizationManagerLocal) getInitialContext().lookup(
+ AuthorizationManagerBean.class.getSimpleName() + "/local");
+
+ Subject rhqadmin = subjectManager.loginUnauthenticated("rhqadmin");
+ System.out.println(rhqadmin);
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceWithStatus.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceWithStatus.java
new file mode 100644
index 0000000..4215126
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceWithStatus.java
@@ -0,0 +1,48 @@
+/*
+ * 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.enterprise.server.resource.test;
+
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.resource.Resource;
+
+public class ResourceWithStatus {
+ private AvailabilityType availabilityType;
+ private Resource resource;
+
+ public ResourceWithStatus(AvailabilityType availabilityType, Resource resource) {
+ this.availabilityType = availabilityType;
+ this.resource = resource;
+ }
+
+ public AvailabilityType getAvailabilityType() {
+ return availabilityType;
+ }
+
+ public void setAvailabilityType(AvailabilityType availabilityType) {
+ this.availabilityType = availabilityType;
+ }
+
+ public Resource getResource() {
+ return resource;
+ }
+
+ public void setResource(Resource resource) {
+ this.resource = resource;
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/scheduler/jobs/DataPurgeJobTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/scheduler/jobs/DataPurgeJobTest.java
new file mode 100644
index 0000000..31d2a87
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/scheduler/jobs/DataPurgeJobTest.java
@@ -0,0 +1,587 @@
+/*
+ * 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.enterprise.server.scheduler.jobs;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.persistence.EntityManager;
+import javax.transaction.NotSupportedException;
+import javax.transaction.SystemException;
+
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.quartz.JobListener;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.alert.Alert;
+import org.rhq.core.domain.alert.AlertCondition;
+import org.rhq.core.domain.alert.AlertConditionCategory;
+import org.rhq.core.domain.alert.AlertConditionLog;
+import org.rhq.core.domain.alert.AlertDampening;
+import org.rhq.core.domain.alert.AlertDefinition;
+import org.rhq.core.domain.alert.AlertPriority;
+import org.rhq.core.domain.alert.BooleanExpression;
+import org.rhq.core.domain.alert.notification.AlertNotificationLog;
+import org.rhq.core.domain.alert.notification.ResultState;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.common.EntityContext;
+import org.rhq.core.domain.event.Event;
+import org.rhq.core.domain.event.EventDefinition;
+import org.rhq.core.domain.event.EventSeverity;
+import org.rhq.core.domain.event.EventSource;
+import org.rhq.core.domain.event.composite.EventComposite;
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.DisplayType;
+import org.rhq.core.domain.measurement.MeasurementCategory;
+import org.rhq.core.domain.measurement.MeasurementDataTrait;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementSchedule;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.domain.measurement.calltime.CallTimeData;
+import org.rhq.core.domain.measurement.calltime.CallTimeDataComposite;
+import org.rhq.core.domain.resource.Agent;
+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.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.core.util.exception.ThrowableUtil;
+import org.rhq.enterprise.server.event.EventManagerLocal;
+import org.rhq.enterprise.server.measurement.CallTimeDataManagerLocal;
+import org.rhq.enterprise.server.measurement.MeasurementDataManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.scheduler.SchedulerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
+import org.rhq.enterprise.server.test.TestServerPluginService;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Tests that we can purge data.
+ */
+@Test
+public class DataPurgeJobTest extends AbstractEJB3Test {
+ private Resource newResource;
+
+ @SuppressWarnings("unused")
+ private int agentId;
+ private int resourceTypeId;
+ private TestServerPluginService testServerPluginService;
+
+ @Override
+ public void beforeMethod() throws Exception {
+ try {
+ //we need this because the drift plugins are referenced from the system settings that we use in our tests
+ testServerPluginService = new TestServerPluginService();
+ prepareCustomServerPluginService(testServerPluginService);
+ testServerPluginService.startMasterPluginContainer();
+
+ prepareScheduler();
+ TestServerCommunicationsService agentContainer = prepareForTestAgents();
+ newResource = createNewResource();
+ } catch (Throwable t) {
+ System.err.println("Cannot prepare test: " + t);
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+
+ @Override
+ public void afterMethod() throws Exception {
+ try {
+ deleteNewResource(newResource);
+ unprepareForTestAgents();
+ unprepareScheduler();
+ unprepareServerPluginService();
+ } catch (Throwable t) {
+ System.err.println("Cannot unprepare test: " + t);
+ t.printStackTrace();
+ throw new RuntimeException(t);
+ }
+ }
+
+ public void testPurge() throws Throwable {
+ addDataToBePurged();
+ triggerDataPurgeJobNow();
+ makeSureDataIsPurged();
+ }
+
+ public void testPurgeWhenDeleting() throws Throwable {
+ addDataToBePurged();
+ try {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+
+ List<Integer> deletedIds = resourceManager.uninventoryResource(overlord, newResource.getId());
+ resourceManager.uninventoryResourceAsyncWork(overlord, newResource.getId());
+
+ assert deletedIds.size() == 1 : "didn't delete resource: " + deletedIds;
+ assert deletedIds.get(0).intValue() == newResource.getId() : "what was deleted? : " + deletedIds;
+
+ // I don't have the resource anymore so I can't use makeSureDataIsPurged to test
+ // this test method will at least ensure no exceptions occur in resource manager
+ } finally {
+ newResource = null; // so our tear-down method doesn't try to delete it again
+ }
+ getTransactionManager().begin();
+ try {
+ EntityManager em = getEntityManager();
+
+ /* agent is now implicitly deleted
+ Agent agent = em.find(Agent.class, agentId);
+ em.remove(agent);
+ */
+
+ ResourceType rt = em.find(ResourceType.class, resourceTypeId);
+ Set<EventDefinition> evDs = rt.getEventDefinitions();
+ if (evDs != null) {
+ Iterator<EventDefinition> evdIter = evDs.iterator();
+ while (evdIter.hasNext()) {
+ EventDefinition evd = evdIter.next();
+ em.remove(evd);
+ evdIter.remove();
+ }
+ }
+ Set<MeasurementDefinition> mDefs = rt.getMetricDefinitions();
+ if (mDefs != null) {
+ Iterator<MeasurementDefinition> mdIter = mDefs.iterator();
+ while (mdIter.hasNext()) {
+ MeasurementDefinition def = mdIter.next();
+ em.remove(def);
+ mdIter.remove();
+ }
+ }
+ em.remove(rt);
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ getTransactionManager().rollback();
+ throw e;
+ }
+ }
+
+ private void addDataToBePurged() throws NotSupportedException, SystemException, Throwable {
+ // add a bunch of data that is to be purged
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ try {
+ // add alerts
+ AlertDefinition ad = newResource.getAlertDefinitions().iterator().next();
+ for (long timestamp = 0L; timestamp < 200L; timestamp++) {
+ Alert newAlert = createNewAlert(em, ad, timestamp);
+ assert newAlert.getCtime() == timestamp : "bad alert persisted:" + newAlert;
+ assert newAlert.getId() > 0 : "alert not persisted:" + newAlert;
+ if (timestamp % 50L == 0) {
+ em.flush();
+ em.clear();
+ }
+ }
+ em.flush();
+ em.clear();
+
+ // add availabilities
+ for (long timestamp = 0L; timestamp < 2000L; timestamp += 2L) {
+ Availability newAvail = createNewAvailability(em, newResource, timestamp, timestamp + 1L);
+ assert newAvail.getStartTime() == timestamp : "bad avail persisted:" + newAvail;
+ assert newAvail.getEndTime() == (timestamp + 1L) : "bad avail persisted:" + newAvail;
+ assert newAvail.getId() > 0 : "avail not persisted:" + newAvail;
+ if (timestamp % 50L == 0) {
+ em.flush();
+ em.clear();
+ }
+ }
+ em.flush();
+ em.clear();
+
+ // add events
+ createNewEvents(newResource, 0, 1000);
+
+ // add calltime/response times
+ createNewCalltimeData(newResource, 0, 1000);
+
+ // add trait data
+ createNewTraitData(newResource, 0L, 100);
+
+ getTransactionManager().commit();
+ } catch (Throwable t) {
+ getTransactionManager().rollback();
+ throw t;
+ }
+ } catch (Throwable t) {
+ System.err.println("!!!!! DataPurgeJobTest.testPurge failed: " + ThrowableUtil.getAllMessages(t));
+ t.printStackTrace();
+ throw t;
+ } finally {
+ em.close();
+ }
+ }
+
+ private void makeSureDataIsPurged() throws NotSupportedException, SystemException {
+ // now that our data purge job is done, make sure none of our test data is left behind
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ Resource res = em.find(Resource.class, newResource.getId());
+
+ // check alerts
+ Set<AlertDefinition> alertDefinitions = res.getAlertDefinitions();
+ assert alertDefinitions.size() == 1 : "why are we missing our alert definitions?: " + alertDefinitions;
+ AlertDefinition ad = alertDefinitions.iterator().next();
+ assert ad.getAlerts().size() == 0 : "didn't purge alerts";
+ Set<AlertConditionLog> clogs = ad.getConditions().iterator().next().getConditionLogs();
+ assert clogs.size() == 0 : "didn't purge condition logs: " + clogs.size();
+
+ // check availabilities, remember, a new resource gets one initial avail record
+ List<Availability> avails = res.getAvailability();
+ assert avails.size() == 1 : "didn't purge availabilities";
+
+ // check events
+ EventSource es = res.getEventSources().iterator().next();
+ assert es.getEvents().size() == 0 : "didn't purge all events";
+
+ // check calltime data
+ int calltimeScheduleId = 0;
+ for (MeasurementSchedule sched : res.getSchedules()) {
+ if (sched.getDefinition().getDataType() == DataType.CALLTIME) {
+ calltimeScheduleId = sched.getId();
+ break;
+ }
+ }
+ assert calltimeScheduleId > 0 : "why don't we have a calltime schedule?";
+ PageList<CallTimeDataComposite> calltimeData = LookupUtil.getCallTimeDataManager()
+ .findCallTimeDataForResource(overlord, calltimeScheduleId, 0, Long.MAX_VALUE, new PageControl());
+ assert calltimeData.getTotalSize() == 0 : "didn't purge all calltime data";
+
+ // check trait data
+ MeasurementSchedule traitSchedule = null;
+ for (MeasurementSchedule sched : res.getSchedules()) {
+ if (sched.getDefinition().getDataType() == DataType.TRAIT) {
+ traitSchedule = sched;
+ break;
+ }
+ }
+ assert traitSchedule != null : "why don't we have a trait schedule?";
+
+ List<MeasurementDataTrait> persistedTraits = LookupUtil.getMeasurementDataManager().findTraits(overlord,
+ res.getId(), traitSchedule.getDefinition().getId());
+ assert persistedTraits.size() == 1 : "bad purge of trait data: " + persistedTraits.size();
+
+ } finally {
+ getTransactionManager().rollback();
+ em.close();
+ }
+ }
+
+ private void triggerDataPurgeJobNow() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+
+ SchedulerLocal schedulerBean = LookupUtil.getSchedulerBean();
+ schedulerBean.scheduleSimpleCronJob(DataPurgeJob.class, true, false, "0 0 0 1 1 ? 2099");
+
+ schedulerBean.addGlobalJobListener(new JobListener() {
+ public String getName() {
+ return "DataPurgeJobTestListener";
+ }
+
+ public void jobExecutionVetoed(JobExecutionContext arg0) {
+ }
+
+ public void jobToBeExecuted(JobExecutionContext arg0) {
+ }
+
+ public void jobWasExecuted(JobExecutionContext c, JobExecutionException e) {
+ if (c.getJobDetail().getJobClass().getName().equals(DataPurgeJob.class.getName())) {
+ latch.countDown(); // the data purge job is finished! let our test continue
+ }
+ }
+ });
+
+ try {
+ // trigger the data purge job so it executes immediately - this does not block
+ DataPurgeJob.purgeNow();
+
+ // wait for the job to finish - abort the test if it takes too long
+ assert latch.await(60, TimeUnit.SECONDS) : "Data purge job didn't complete in a timely fashion";
+ } finally {
+ schedulerBean.deleteJob(DataPurgeJob.class.getName(), DataPurgeJob.class.getName());
+ }
+
+ return;
+ }
+
+ private void createNewTraitData(Resource res, long timestamp, int count) {
+ MeasurementSchedule traitSchedule = null;
+ for (MeasurementSchedule sched : res.getSchedules()) {
+ if (sched.getDefinition().getDataType() == DataType.TRAIT) {
+ traitSchedule = sched;
+ break;
+ }
+ }
+ assert traitSchedule != null : "why don't we have a trait schedule?";
+
+ MeasurementDataManagerLocal mgr = LookupUtil.getMeasurementDataManager();
+
+ MeasurementScheduleRequest msr = new MeasurementScheduleRequest(traitSchedule);
+
+ Set<MeasurementDataTrait> dataset = new HashSet<MeasurementDataTrait>();
+ for (int i = 0; i < count; i++) {
+ dataset.add(new MeasurementDataTrait(timestamp + i, msr, "DataPurgeJobTestTraitValue" + i));
+ }
+ mgr.addTraitData(dataset);
+
+ List<MeasurementDataTrait> persistedTraits = mgr.findTraits(LookupUtil.getSubjectManager().getOverlord(),
+ res.getId(), traitSchedule.getDefinition().getId());
+ assert persistedTraits.size() == count : "did not persist trait data:" + persistedTraits.size() + ":"
+ + persistedTraits;
+ }
+
+ private void createNewCalltimeData(Resource res, long timestamp, int count) {
+ MeasurementSchedule calltimeSchedule = null;
+ for (MeasurementSchedule sched : res.getSchedules()) {
+ if (sched.getDefinition().getDataType() == DataType.CALLTIME) {
+ calltimeSchedule = sched;
+ break;
+ }
+ }
+ assert calltimeSchedule != null : "why don't we have a calltime schedule?";
+
+ MeasurementScheduleRequest msr = new MeasurementScheduleRequest(calltimeSchedule);
+
+ Set<CallTimeData> dataset = new HashSet<CallTimeData>();
+ CallTimeData data = new CallTimeData(msr);
+
+ for (int i = 0; i < count; i++) {
+ for (int j = 0; j < count; j++) {
+ data.addCallData("DataPurgeJobTestCalltimeData" + j, new Date(timestamp), 777);
+ }
+ }
+
+ dataset.add(data);
+
+ CallTimeDataManagerLocal mgr = LookupUtil.getCallTimeDataManager();
+ mgr.addCallTimeData(dataset);
+
+ PageList<CallTimeDataComposite> persistedData = mgr.findCallTimeDataForResource(LookupUtil.getSubjectManager()
+ .getOverlord(), calltimeSchedule.getId(), timestamp - 1L, timestamp + count + 1L, new PageControl());
+ // just a few sanity checks
+ assert persistedData.getTotalSize() == count : "did not persist all calltime data, only persisted: "
+ + persistedData.getTotalSize();
+ assert persistedData.get(0).getCount() == count : "did not persist all endpoint calltime data, only persisted: "
+ + persistedData.get(0).getCount();
+ }
+
+ private void createNewEvents(Resource res, long timestamp, int count) {
+ EventDefinition ed = res.getResourceType().getEventDefinitions().iterator().next();
+ EventSource source = new EventSource("datapurgejobtest", ed, res);
+ Map<EventSource, Set<Event>> eventMap = new HashMap<EventSource, Set<Event>>();
+ Set<Event> events = new HashSet<Event>();
+ for (int i = 0; i < count; i++) {
+ events.add(new Event(ed.getName(), source.getLocation(), timestamp + i, EventSeverity.DEBUG, "details"));
+ }
+ eventMap.put(source, events);
+
+ EventManagerLocal mgr = LookupUtil.getEventManager();
+ mgr.addEventData(eventMap);
+
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ PageList<EventComposite> persistedEvents = mgr.findEventComposites(overlord,
+ EntityContext.forResource(res.getId()), timestamp - 1L, timestamp + count + 1L,
+ new EventSeverity[] { EventSeverity.DEBUG }, null, null, new PageControl());
+ assert persistedEvents.getTotalSize() == count : "did not persist all events, only persisted: "
+ + persistedEvents.getTotalSize();
+
+ return;
+ }
+
+ private Availability createNewAvailability(EntityManager em, Resource res, long start, long end) {
+ Availability a = new Availability(res, start, AvailabilityType.UP);
+ if (end > 0) {
+ a.setEndTime(end);
+ }
+ em.persist(a);
+ return a;
+ }
+
+ private Alert createNewAlert(EntityManager em, AlertDefinition ad, long timestamp) {
+ Alert a = new Alert(ad, timestamp);
+ em.persist(a);
+
+ AlertNotificationLog anl = new AlertNotificationLog(a, "dummy", ResultState.SUCCESS, "message");
+ em.persist(anl);
+
+ AlertCondition ac = ad.getConditions().iterator().next();
+ AlertConditionLog acl = new AlertConditionLog(ac, timestamp);
+ acl.setAlert(a);
+ acl.setValue("dummy value");
+ em.persist(acl);
+
+ return a;
+ }
+
+ private Resource createNewResource() throws Exception {
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+
+ Resource resource;
+
+ try {
+ try {
+ long now = System.currentTimeMillis();
+ ResourceType resourceType = new ResourceType("plat" + now, "test", ResourceCategory.PLATFORM, null);
+
+ em.persist(resourceType);
+ resourceTypeId = resourceType.getId();
+
+ Agent agent = new Agent("testagent" + now, "testaddress" + now, 1, "", "testtoken" + now);
+ em.persist(agent);
+ agentId = agent.getId();
+ em.flush();
+
+ resource = new Resource("reskey" + now, "resname", resourceType);
+ resource.setUuid("" + new Random().nextInt());
+ resource.setAgent(agent);
+ em.persist(resource);
+
+ AlertDefinition ad = new AlertDefinition();
+ ad.setName("alertTest");
+ ad.setEnabled(true);
+ ad.setPriority(AlertPriority.HIGH);
+ ad.setResource(resource);
+ ad.setAlertDampening(new AlertDampening(AlertDampening.Category.NONE));
+ ad.setConditionExpression(BooleanExpression.ALL);
+ ad.setRecoveryId(0);
+ em.persist(ad);
+
+ AlertCondition ac = new AlertCondition(ad, AlertConditionCategory.AVAILABILITY);
+ ac.setComparator("==");
+ em.persist(ac);
+ ad.addCondition(ac);
+
+ EventDefinition ed = new EventDefinition(resourceType, "DataPurgeJobTestEventDefinition");
+ em.persist(ed);
+ resourceType.addEventDefinition(ed);
+
+ // add calltime schedule
+ MeasurementDefinition def = new MeasurementDefinition(resourceType, "DataPurgeJobTestCalltimeMeasDef");
+ def.setCategory(MeasurementCategory.PERFORMANCE);
+ def.setDataType(DataType.CALLTIME);
+ def.setDefaultInterval(12345);
+ def.setDefaultOn(true);
+ def.setDestinationType("DataPurgeJobTestDestType");
+ def.setDisplayName(def.getName());
+ def.setDisplayType(DisplayType.SUMMARY);
+ em.persist(def);
+ MeasurementSchedule schedule = new MeasurementSchedule(def, resource);
+ em.persist(schedule);
+ def.addSchedule(schedule);
+ resource.addSchedule(schedule);
+
+ // add trait schedule
+ def = new MeasurementDefinition(resourceType, "DataPurgeJobTestTraitMeasDef");
+ def.setCategory(MeasurementCategory.PERFORMANCE);
+ def.setDataType(DataType.TRAIT);
+ def.setDefaultInterval(12345);
+ def.setDefaultOn(true);
+ def.setDisplayName(def.getName());
+ def.setDisplayType(DisplayType.SUMMARY);
+ em.persist(def);
+ schedule = new MeasurementSchedule(def, resource);
+ em.persist(schedule);
+ def.addSchedule(schedule);
+ resource.addSchedule(schedule);
+
+ // add normal measurment schedule
+ def = new MeasurementDefinition(resourceType, "DataPurgeJobTestNormalMeasDef");
+ def.setCategory(MeasurementCategory.PERFORMANCE);
+ def.setDataType(DataType.MEASUREMENT);
+ def.setDefaultInterval(12345);
+ def.setDefaultOn(true);
+ def.setDisplayName(def.getName());
+ def.setDisplayType(DisplayType.SUMMARY);
+ em.persist(def);
+ schedule = new MeasurementSchedule(def, resource);
+ em.persist(schedule);
+ def.addSchedule(schedule);
+ resource.addSchedule(schedule);
+
+ } catch (Exception e) {
+ System.out.println("CANNOT PREPARE TEST: " + e);
+ getTransactionManager().rollback();
+ throw e;
+ }
+
+ getTransactionManager().commit();
+ } finally {
+ em.close();
+ }
+
+ return resource;
+ }
+
+ private void deleteNewResource(Resource doomedResource) throws Exception {
+ if (doomedResource != null) {
+ // get the type and agent that we will delete after we delete the resource itself
+ ResourceType doomedResourceType = doomedResource.getResourceType();
+ Agent doomedAgent = doomedResource.getAgent();
+
+ // delete the resource itself
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+ List<Integer> deletedIds = resourceManager.uninventoryResource(overlord, doomedResource.getId());
+ for (Integer deletedResourceId : deletedIds) {
+ resourceManager.uninventoryResourceAsyncWork(overlord, deletedResourceId);
+ }
+
+ // delete the agent and the type
+ getTransactionManager().begin();
+ EntityManager em = getEntityManager();
+ try {
+ Agent agent = em.find(Agent.class, doomedAgent.getId());
+ if (agent != null)
+ em.remove(agent);
+
+ ResourceType type = em.find(ResourceType.class, doomedResourceType.getId());
+ if (type != null)
+ em.remove(type);
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ try {
+ System.out.println("CANNOT CLEAN UP TEST: Cause: " + e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+ } finally {
+ em.close();
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/scheduler/jobs/RepoSyncJobTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/scheduler/jobs/RepoSyncJobTest.java
new file mode 100644
index 0000000..1927932
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/scheduler/jobs/RepoSyncJobTest.java
@@ -0,0 +1,117 @@
+/*
+* RHQ Management Platform
+* Copyright (C) 2009 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.enterprise.server.scheduler.jobs;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.quartz.JobDataMap;
+import org.quartz.JobDetail;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.content.Repo;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+
+/**
+ * @author Jason Dobies
+ */
+public class RepoSyncJobTest extends AbstractEJB3Test {
+
+ private static final boolean ENABLED = true;
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ prepareScheduler();
+ prepareForTestAgents();
+ }
+
+ @AfterMethod
+ public void afterMethod() throws Exception {
+ unprepareForTestAgents();
+ unprepareScheduler();
+ }
+
+ @Test(enabled = ENABLED)
+ public void createJobDataMap() throws Exception {
+ // Setup
+ String repoName = "testRepo";
+ Repo repo = new Repo(repoName);
+
+ JobDataMap existingMap = new JobDataMap();
+ JobDetail detail = new JobDetail();
+ detail.setJobDataMap(existingMap);
+
+ // Test
+ JobDataMap nullDetailsMap = RepoSyncJob.createJobDataMap(null, repo);
+ JobDataMap existingDetailsMap = RepoSyncJob.createJobDataMap(detail, repo);
+
+ // Verify
+ assert nullDetailsMap.getString(RepoSyncJob.KEY_REPO_NAME).equals(repoName);
+
+ assert existingDetailsMap.getString(RepoSyncJob.KEY_REPO_NAME).equals(repoName);
+ assert existingDetailsMap == existingMap;
+ }
+
+ @Test(enabled = ENABLED)
+ public void createJobName() throws Exception {
+ // Setup
+ Repo repo = new Repo("testRepo");
+
+ // Test
+ Set<String> jobNames = new HashSet<String>(1);
+
+ jobNames.add(RepoSyncJob.createJobName(repo));
+ jobNames.add(RepoSyncJob.createJobName(repo));
+ jobNames.add(RepoSyncJob.createJobName(repo));
+ jobNames.add(RepoSyncJob.createJobName(repo));
+ jobNames.add(RepoSyncJob.createJobName(repo));
+
+ // Verify
+ assert jobNames.size() == 1 : "Number of jobs found: " + jobNames.size();
+ }
+
+ @Test(enabled = ENABLED)
+ public void createUniqueJobName() throws Exception {
+ // Setup
+ Repo repo = new Repo("testRepo");
+
+ // Test
+ Set<String> jobNames = new HashSet<String>(1);
+
+ jobNames.add(RepoSyncJob.createUniqueJobName(repo));
+ Thread.sleep(100); // Need a quick pause to allow for uniqueness
+ jobNames.add(RepoSyncJob.createUniqueJobName(repo));
+ Thread.sleep(100);
+ jobNames.add(RepoSyncJob.createUniqueJobName(repo));
+ Thread.sleep(100);
+ jobNames.add(RepoSyncJob.createUniqueJobName(repo));
+ Thread.sleep(100);
+ jobNames.add(RepoSyncJob.createUniqueJobName(repo));
+
+ // Verify
+ assert jobNames.size() == 5 : "Number of jobs found: " + jobNames.size();
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/search/GenericSearchAssistTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/search/GenericSearchAssistTest.java
new file mode 100644
index 0000000..dbbeb64
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/search/GenericSearchAssistTest.java
@@ -0,0 +1,109 @@
+package org.rhq.enterprise.server.search;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.search.SearchSubsystem;
+import org.rhq.core.domain.search.SearchSuggestion;
+import org.rhq.enterprise.server.search.execution.SearchAssistManager;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+public class GenericSearchAssistTest extends AbstractEJB3Test {
+
+ @Test
+ public void testGenericAssist() throws Exception {
+ BufferedReader reader = null;
+ try {
+ InputStream stream = getClass().getClassLoader().getResourceAsStream("test-assist-color-number.txt");
+ reader = new BufferedReader(new InputStreamReader(stream));
+ String expression = null;
+ String expected = null;
+
+ int count = 0;
+ while (true) {
+ expression = reader.readLine();
+ if (expression == null) {
+ break;
+ }
+ expected = reader.readLine();
+ if (expected == null) {
+ break;
+ }
+
+ count++;
+ List<SearchSuggestion> results = new TestAutoCompletionManager().getAdvancedSuggestions(expression,
+ expression.length(), null);
+ List<String> expectedResults = Arrays.asList(expected.split(" "));
+
+ System.out.println();
+ System.out.println("Expression: " + expression);
+ try {
+ compare(results, expectedResults);
+ System.out.println("Assist worked: " + parenthesize(expectedResults.toString()));
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+ System.out.println("Tested " + count + " expressions for assist");
+ } catch (Exception e) {
+ System.out.println("Error testing GenericSearchAssistTest: " + e);
+ e.printStackTrace(System.out);
+ throw e;
+ } finally {
+ if (reader != null) {
+ reader.close();
+ }
+ }
+ }
+
+ @Test
+ public void test2() throws Exception {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ SearchAssistManager mgr = new SearchAssistManager(overlord, SearchSubsystem.RESOURCE);
+ List<SearchSuggestion> suggestions = mgr.getSuggestions("category=PLATFORM",0);
+ System.out.println("Number of suggestions: " + suggestions.size());
+ for (SearchSuggestion s : suggestions) {
+ System.out.println(s);
+ }
+
+
+ }
+
+ private void compare(List<SearchSuggestion> results, List<String> expected) {
+ List<String> rawResults = new ArrayList<String>();
+ for (SearchSuggestion suggestion : results) {
+ rawResults.add(suggestion.getValue());
+ }
+
+ Collections.sort(rawResults);
+ Collections.sort(expected);
+
+ assert rawResults.size() == expected.size() : print(expected, rawResults);
+ for (int i = 0; i < rawResults.size(); i++) {
+ String nextRaw = rawResults.get(i);
+ String nextExpected = expected.get(i);
+ assert nextRaw.equals(nextExpected) : print(expected, rawResults);
+ }
+ }
+
+ private String print(List<String> expected, List<String> results) {
+ return "expected" + parenthesize(expected.toString()) + ", results" + parenthesize(results.toString());
+ }
+
+ private String parenthesize(String data) {
+ return "(" + data.substring(1, data.length() - 1) + ")";
+ }
+
+ public static void main(String[] args) throws Exception {
+ new GenericSearchAssistTest().testGenericAssist();
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/search/RHQLTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/search/RHQLTest.java
new file mode 100644
index 0000000..be9b48a
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/search/RHQLTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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, 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.enterprise.server.search;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.antlr.runtime.ANTLRStringStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.testng.AssertJUnit;
+import org.testng.annotations.*;
+
+import org.rhq.enterprise.server.search.RHQLParser.searchExpression_return;
+
+/**
+ * Test harness to verify correctness of RHQL grammar
+ *
+ * @author Joseph Marques
+ */
+public class RHQLTest extends AssertJUnit {
+
+ private enum TestResult {
+ SUCCESS, FAILURE, TIMEOUT, SKIPPED;
+ }
+
+ private class AntlrTask implements Callable<TestResult> {
+ private String line;
+
+ public AntlrTask(String line) {
+ this.line = line;
+ }
+
+ public TestResult call() throws Exception {
+ try {
+ System.out.println(line);
+ ANTLRStringStream input = new ANTLRStringStream(line); // Create an input character stream from standard in
+ RHQLLexer lexer = new RHQLLexer(input); // Create an echoLexer that feeds from that stream
+ CommonTokenStream tokens = new CommonTokenStream(lexer); // Create a stream of tokens fed by the lexer
+ RHQLParser parser = new RHQLParser(tokens); // Create a parser that feeds off the token stream
+ searchExpression_return parseResults = parser.searchExpression(); // Begin parsing at 'searchExpression' rule
+ System.out.println(parseResults.tree.toStringTree()); // Print result
+ return TestResult.SUCCESS;
+ } catch (Throwable t) {
+ return TestResult.FAILURE;
+ }
+ }
+ };
+
+ private ExecutorService executor;
+
+ @BeforeClass
+ public void init() {
+ executor = Executors.newSingleThreadExecutor();
+ }
+
+ @AfterClass
+ public void teardown() {
+ executor.shutdownNow();
+ }
+
+ @Test
+ public void testSingleLineRHQL() throws Exception {
+ BufferedReader reader = null;
+ List<String> successes = new java.util.ArrayList<String>();
+ List<String> failures = new java.util.ArrayList<String>();
+ int count = 0;
+ try {
+ InputStream stream = getClass().getClassLoader().getResourceAsStream("single-line-rhql.txt");
+ reader = new BufferedReader(new InputStreamReader(stream));
+ String line = null;
+ long timeout = 2000;
+ while ((line = reader.readLine()) != null) {
+ TestResult result = testSuccess(line, timeout);
+ if (result == TestResult.SKIPPED) {
+ continue;
+ }
+ count++;
+ if (result == TestResult.SUCCESS) {
+ successes.add(line);
+ } else if (result == TestResult.FAILURE) {
+ failures.add(line);
+ } else if (result == TestResult.TIMEOUT) {
+ System.out.println("Parsing took more than " + timeout
+ + "ms, does your grammar have an infinite loop?");
+ }
+ }
+ } catch (Exception e) {
+ System.out.println("Error testing single line RHQL: " + e);
+ throw e;
+ } finally {
+ if (reader != null) {
+ reader.close();
+ }
+ }
+
+ System.out.println();
+ for (String success : successes) {
+ System.out.println("Parse success: " + success);
+ }
+ for (String failure : failures) {
+ System.out.println("Parse failure: " + failure);
+ }
+
+ System.out.println();
+ System.out.printf("RHQL expressions parsed: %1$s, Failures: %2$s", count, failures.size());
+ System.out.println();
+
+ assert failures.size() == 0;
+ }
+
+ private TestResult testSuccess(final String line, long timeout) {
+ if (shouldSkip(line)) {
+ return TestResult.SKIPPED; // skip empty lines used for visual separation in test file
+ }
+
+ AntlrTask task = new AntlrTask(line);
+ Future<TestResult> futureTask = executor.submit(task);
+ TestResult result = null;
+ try {
+ result = futureTask.get(timeout, TimeUnit.MILLISECONDS);
+ } catch (ExecutionException ee) {
+ } catch (TimeoutException te) {
+ futureTask.cancel(true);
+ result = TestResult.TIMEOUT;
+ } catch (InterruptedException ie) {
+ futureTask.cancel(true);
+ }
+
+ return result;
+ }
+
+ private boolean shouldSkip(String line) {
+ line = line.trim();
+ if (line.equals("")) {
+ return true; // ignore empty lines
+ }
+ if (line.startsWith("#")) {
+ return true; // ignore comments
+ }
+ return false;
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/search/TestAutoCompletionManager.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/search/TestAutoCompletionManager.java
new file mode 100644
index 0000000..67bff40
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/search/TestAutoCompletionManager.java
@@ -0,0 +1,83 @@
+package org.rhq.enterprise.server.search;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.search.SearchSubsystem;
+import org.rhq.enterprise.server.search.assist.AbstractSearchAssistant;
+import org.rhq.enterprise.server.search.assist.SearchAssistant;
+import org.rhq.enterprise.server.search.execution.SearchAssistManager;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+public class TestAutoCompletionManager extends SearchAssistManager {
+ public static class TestAutoCompletor extends AbstractSearchAssistant {
+ /*
+ * color[primary] = red, green, blue
+ * color[other] = red-green, green-blue, blue-red
+ * number = two, four, twenty-two, twenty-four, forty-two
+ */
+
+ private static Map<String, List<String>> suggestionMap = new HashMap<String, List<String>>();
+
+ static {
+ suggestionMap.put("color:params", build("primary", "other"));
+ suggestionMap.put("color:primary", build("red", "green", "blue"));
+ suggestionMap.put("color:other", build("red-green", "green-blue", "blue-red"));
+ suggestionMap.put("number:", build("two", "four", "twenty-two", "twenty-four", "forty-two"));
+ }
+
+ private static List<String> build(String... items) {
+ return Collections.unmodifiableList(Arrays.asList(items));
+ }
+
+ public TestAutoCompletor(Subject subject) {
+ super(subject);
+ }
+
+ @Override
+ public SearchSubsystem getSearchSubsystem() {
+ return null;
+ }
+
+ @Override
+ public List<String> getSimpleContexts() {
+ return Arrays.asList("number");
+ }
+
+ @Override
+ public List<String> getParameterizedContexts() {
+ return Arrays.asList("color");
+ }
+
+ @Override
+ public List<String> getParameters(String context, String filter) {
+ super.getParameters(context, filter);
+ return filter(suggestionMap.get("color:params"), filter);
+ }
+
+ @Override
+ public List<String> getValues(String context, String param, String filter) {
+ super.getValues(context, param, filter);
+ String lookup = context + ":" + (param == null ? "" : param);
+ return filter(suggestionMap.get(lookup), filter);
+ }
+ }
+
+ public TestAutoCompletionManager() {
+ super(LookupUtil.getSubjectManager().getOverlord(), null);
+ }
+
+ @Override
+ protected AbstractSearchAssistant getSearchAssistant() {
+ return new TestAutoCompletor(LookupUtil.getSubjectManager().getOverlord());
+ }
+
+ @Override
+ protected SearchAssistant getTabAwareSearchAssistant(String tab) {
+ return new TestAutoCompletor(LookupUtil.getSubjectManager().getOverlord());
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/DeployedAgentPluginsValidatorTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/DeployedAgentPluginsValidatorTest.java
new file mode 100644
index 0000000..061d803
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/DeployedAgentPluginsValidatorTest.java
@@ -0,0 +1,220 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.sync.test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.fail;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jmock.Expectations;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginStatusType;
+import org.rhq.enterprise.server.resource.metadata.PluginManagerLocal;
+import org.rhq.enterprise.server.sync.ExportReader;
+import org.rhq.enterprise.server.sync.ExportWriter;
+import org.rhq.enterprise.server.sync.validators.DeployedAgentPluginsValidator;
+import org.rhq.enterprise.server.sync.validators.InconsistentStateException;
+import org.rhq.test.JMockTest;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+//@Test - switching this off for now because this validator is no longer used in any
+//of the default synchronizers
+public class DeployedAgentPluginsValidatorTest extends JMockTest {
+
+ private static final Log LOG = LogFactory.getLog(DeployedAgentPluginsValidator.class);
+
+ public void testCanExportAndImportState() throws Exception {
+ final PluginManagerLocal pluginManager = context.mock(PluginManagerLocal.class);
+
+ final DeployedAgentPluginsValidator validator = new DeployedAgentPluginsValidator(pluginManager);
+
+ context.checking(new Expectations() {
+ {
+ oneOf(pluginManager).getInstalledPlugins();
+ will(returnValue(new ArrayList<Plugin>(getDeployedPlugins())));
+ }
+ });
+
+ validator.initialize(null, null);
+
+ StringWriter output = new StringWriter();
+ try {
+ XMLOutputFactory ofactory = XMLOutputFactory.newInstance();
+
+ XMLStreamWriter wrt = ofactory.createXMLStreamWriter(output);
+ //wrap the exported plugins in "something" so that we produce
+ //a valid xml
+ wrt.writeStartDocument();
+ wrt.writeStartElement("root");
+
+ validator.exportState(new ExportWriter(wrt));
+
+ wrt.writeEndDocument();
+
+ wrt.close();
+
+ StringReader input = new StringReader(output.toString());
+
+ try {
+ XMLInputFactory ifactory = XMLInputFactory.newInstance();
+ XMLStreamReader rdr = ifactory.createXMLStreamReader(input);
+
+ //push the reader to the start of the plugin elements
+ //this is what is expected by the validators
+ rdr.nextTag();
+
+ validator.initializeExportedStateValidation(new ExportReader(rdr));
+
+ rdr.close();
+
+ assertEquals(validator.getPluginsToValidate(), getDeployedPlugins());
+ } finally {
+ input.close();
+ }
+ } catch (Exception e) {
+ LOG.error("Test failed. Output generated so far:\n" + output, e);
+ throw e;
+ } finally {
+ output.close();
+ }
+ }
+
+ public void testDetectsPluginDifferencies() {
+ final PluginManagerLocal pluginManager = context.mock(PluginManagerLocal.class);
+
+ //this is what we are going to return from the mocked plugin manager
+ final List<Plugin> installedPlugins = new ArrayList<Plugin>(getDeployedPlugins());
+
+ context.checking(new Expectations() {
+ {
+ allowing(pluginManager).getInstalledPlugins();
+ will(returnValue(installedPlugins));
+ }
+ });
+
+ DeployedAgentPluginsValidator validator = new DeployedAgentPluginsValidator(pluginManager);
+
+ Set<DeployedAgentPluginsValidator.ConsistentPlugin> pluginsToValidate = getDeployedPlugins();
+
+ validator.initialize(null, null);
+
+ validator.setPluginsToValidate(pluginsToValidate);
+
+ //this should validate cleanly
+ validator.validateExportedState();
+
+ //now add 1 plugin to the validated state
+ DeployedAgentPluginsValidator.ConsistentPlugin newPlugin = createPlugin("superfluous", "1", "md5_4");
+ pluginsToValidate.add(newPlugin);
+
+ try {
+ validator.validateExportedState();
+ fail("validation should have detected that the current installation has one plugin less.");
+ } catch (InconsistentStateException e) {
+ //this is expected
+ }
+
+ //ok, remove the new plugin from the "exported state" and put it in the current state
+ pluginsToValidate.remove(newPlugin);
+ installedPlugins.add(newPlugin);
+
+ try {
+ validator.validateExportedState();
+ fail("validation should have detected that the current installation has one plugin more.");
+ } catch (InconsistentStateException e) {
+ //ok
+ }
+
+ //make the current state and exported state be in sync again
+ DeployedAgentPluginsValidator.ConsistentPlugin newPluginCopy = new DeployedAgentPluginsValidator.ConsistentPlugin(newPlugin);
+ pluginsToValidate.add(newPluginCopy);
+
+ //change the newPlugin to not be equal
+ newPlugin.setMd5("md5_different");
+
+ try {
+ validator.validateExportedState();
+ fail("validation should have failed because one of the plugins differs between current and exported states.");
+ } catch (InconsistentStateException e) {
+ //ok
+ }
+
+ newPlugin.setMd5(newPluginCopy.getMd5());
+ newPluginCopy.setMd5("md5_different");
+
+ try {
+ validator.validateExportedState();
+ fail("validation should have failed because one of the plugins differs between current and exported states.");
+ } catch (InconsistentStateException e) {
+ //ok
+ }
+ }
+
+ public void testAllValidatorsEqual() {
+ PluginManagerLocal pluginManager = context.mock(PluginManagerLocal.class);
+
+ DeployedAgentPluginsValidator v1 = new DeployedAgentPluginsValidator(pluginManager);
+ DeployedAgentPluginsValidator v2 = new DeployedAgentPluginsValidator(pluginManager);
+ DeployedAgentPluginsValidator v3 = new DeployedAgentPluginsValidator(pluginManager);
+ Object o = new Object();
+
+ assertEquals(v1, v2);
+ assertEquals(v1, v3);
+ assertEquals(v2, v3);
+
+ assertFalse(v1.equals(o));
+ assertFalse(v2.equals(o));
+ assertFalse(v3.equals(o));
+ }
+
+ private static Set<DeployedAgentPluginsValidator.ConsistentPlugin> getDeployedPlugins() {
+ HashSet<DeployedAgentPluginsValidator.ConsistentPlugin> ret = new HashSet<DeployedAgentPluginsValidator.ConsistentPlugin>();
+
+ ret.add(createPlugin("p1", "1", "md5_1"));
+ ret.add(createPlugin("p2", "1", "md5_2"));
+ ret.add(createPlugin("p3", "1", "md5_3"));
+
+ return ret;
+ }
+
+ private static DeployedAgentPluginsValidator.ConsistentPlugin createPlugin(String name, String version, String md5) {
+ return new DeployedAgentPluginsValidator.ConsistentPlugin(new Plugin(0, name, null, null, true, PluginStatusType.INSTALLED, null, null, md5, version, null, 0, 0));
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/ExportingInputStreamTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/ExportingInputStreamTest.java
new file mode 100644
index 0000000..6d56969
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/ExportingInputStreamTest.java
@@ -0,0 +1,458 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.sync.test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jmock.Expectations;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.sync.ExporterMessages;
+import org.rhq.enterprise.server.sync.ExportReader;
+import org.rhq.enterprise.server.sync.ExportWriter;
+import org.rhq.enterprise.server.sync.ExportingInputStream;
+import org.rhq.enterprise.server.sync.NoSingleEntity;
+import org.rhq.enterprise.server.sync.SynchronizationConstants;
+import org.rhq.enterprise.server.sync.Synchronizer;
+import org.rhq.enterprise.server.sync.exporters.AbstractDelegatingExportingIterator;
+import org.rhq.enterprise.server.sync.exporters.Exporter;
+import org.rhq.enterprise.server.sync.exporters.ExportingIterator;
+import org.rhq.enterprise.server.sync.importers.ExportedEntityMatcher;
+import org.rhq.enterprise.server.sync.importers.Importer;
+import org.rhq.enterprise.server.sync.validators.ConsistencyValidator;
+import org.rhq.enterprise.server.sync.validators.EntityValidator;
+import org.rhq.test.JMockTest;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+@Test
+public class ExportingInputStreamTest extends JMockTest {
+
+ private static final Log LOG = LogFactory.getLog(ExportingInputStreamTest.class);
+
+ private static class ListToStringExporter<T> implements Exporter<NoSingleEntity, T> {
+
+ List<T> valuesToExport;
+
+ public static final String NOTE_PREFIX = "Wow, I just exported an item from a list: ";
+
+ private class Iterator extends AbstractDelegatingExportingIterator<T, T> {
+ public Iterator() {
+ super(valuesToExport.iterator());
+ }
+
+ public void export(ExportWriter output) throws XMLStreamException {
+ output.writeCData(getCurrent().toString());
+ }
+
+ public String getNotes() {
+ return NOTE_PREFIX + getCurrent();
+ }
+
+ protected T convert(T object) {
+ return object;
+ }
+ }
+
+ public ListToStringExporter(List<T> valuesToExport) {
+ this.valuesToExport = valuesToExport;
+ }
+
+ public ExportingIterator<T> getExportingIterator() {
+ return new Iterator();
+ }
+
+ public String getNotes() {
+ return valuesToExport.toString();
+ }
+ }
+
+ private static class DummyImporter<T> implements Importer<NoSingleEntity, T> {
+
+ @Override
+ public ConfigurationDefinition getImportConfigurationDefinition() {
+ return null;
+ }
+
+ @Override
+ public void configure(Configuration importConfiguration) {
+ }
+
+ @Override
+ public ExportedEntityMatcher<NoSingleEntity, T> getExportedEntityMatcher() {
+ return null;
+ }
+
+ @Override
+ public void update(NoSingleEntity entity, T exportedEntity) throws Exception {
+ }
+
+ @Override
+ public T unmarshallExportedEntity(ExportReader reader) throws XMLStreamException {
+ return null;
+ }
+
+ @Override
+ public String finishImport() throws Exception {
+ return null;
+ }
+
+ @Override
+ public Set<EntityValidator<T>> getEntityValidators() {
+ return Collections.emptySet();
+ }
+
+ }
+
+ private static class ListToStringSynchronizer<T> implements Synchronizer<NoSingleEntity, T> {
+ private List<T> list;
+
+ public ListToStringSynchronizer(List<T> list) {
+ this.list = list;
+ }
+
+ @Override
+ public Exporter<NoSingleEntity, T> getExporter() {
+ return new ListToStringExporter<T>(list);
+ }
+
+ @Override
+ public Importer<NoSingleEntity, T> getImporter() {
+ return new DummyImporter<T>();
+ }
+
+ @Override
+ public Set<ConsistencyValidator> getRequiredValidators() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public void initialize(Subject subject, EntityManager entityManager) {
+ }
+ }
+
+ private static class StringListSynchronizer extends ListToStringSynchronizer<String> {
+ public StringListSynchronizer(List<String> list) {
+ super(list);
+ }
+ }
+
+ private static class IntegerListSynchronizer extends ListToStringSynchronizer<Integer> {
+ public IntegerListSynchronizer(List<Integer> list) {
+ super(list);
+ }
+ }
+
+
+ public void testSucessfulExport() throws Exception {
+ List<String> list1 = Arrays.asList("a", "b", "c");
+ List<Integer> list2 = Arrays.asList(1, 2, 3);
+
+ StringListSynchronizer ex1 = new StringListSynchronizer(list1);
+ IntegerListSynchronizer ex2 = new IntegerListSynchronizer(list2);
+
+ Set<Synchronizer<?, ?>> exporters = this.<Synchronizer<?, ?>>asSet(ex1, ex2);
+
+ InputStream export = new ExportingInputStream(exporters, new HashMap<String, ExporterMessages>(), 1024, false);
+
+// String exportContents = readAll(new InputStreamReader(export, "UTF-8"));
+//
+// LOG.info("Export contents:\n" + exportContents);
+//
+// export = new ByteArrayInputStream(exportContents.getBytes("UTF-8"));
+
+ DocumentBuilder bld = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+
+ Document doc = bld.parse(export);
+
+ Element root = doc.getDocumentElement();
+
+ assertEquals(SynchronizationConstants.CONFIGURATION_EXPORT_ELEMENT, root.getNodeName());
+
+ NodeList entities = root.getElementsByTagName(SynchronizationConstants.ENTITIES_EXPORT_ELEMENT);
+ assertEquals(entities.getLength(), 2, "Unexpected number of entities elements");
+
+ Element export1 = (Element) entities.item(0);
+ Element export2 = (Element) entities.item(1);
+
+ assertEquals(export1.getAttribute("id"), StringListSynchronizer.class.getName());
+ assertEquals(export2.getAttribute("id"), IntegerListSynchronizer.class.getName());
+
+ String[] expectedNotes = new String[] {list1.toString(), list2.toString()};
+
+ for(int i = 0, elementIndex = 0; i < root.getChildNodes().getLength(); ++i) {
+ Node node = root.getChildNodes().item(i);
+ if (!(node instanceof Element)) {
+ continue;
+ }
+
+ Element entitiesElement = (Element) node;
+
+ assertEquals(entitiesElement.getNodeName(), SynchronizationConstants.ENTITIES_EXPORT_ELEMENT);
+
+ NodeList errorMessages = entitiesElement.getElementsByTagName(SynchronizationConstants.ERROR_MESSAGE_ELEMENT);
+ assertEquals(errorMessages.getLength(), 0, "Unexpected number of error message elements in an entities export.");
+
+ Node note = getDirectChildByTagName(entitiesElement, SynchronizationConstants.NOTES_ELEMENT);
+
+ assertNotNull(note, "Couldn't find exporter notes.");
+
+ String notesText = ((Element)note).getTextContent();
+ assertEquals(notesText, expectedNotes[elementIndex], "Unexpected notes for entities.");
+
+ NodeList entityElements = entitiesElement.getElementsByTagName(SynchronizationConstants.ENTITY_EXPORT_ELEMENT);
+
+ assertEquals(entityElements.getLength(), 3, "Unexpected number of exported entities.");
+
+ for(int j = 0; j < entityElements.getLength(); ++j) {
+ Element entityElement = (Element) entityElements.item(j);
+
+ errorMessages = entityElement.getElementsByTagName(SynchronizationConstants.ERROR_MESSAGE_ELEMENT);
+ assertEquals(errorMessages.getLength(), 0, "Unexpected number of error message elements in an entity.");
+
+ note = getDirectChildByTagName(entityElement, SynchronizationConstants.NOTES_ELEMENT);
+ assertNotNull(note, "Could not find notes for an exported entity.");
+
+ Node data = getDirectChildByTagName(entityElement, SynchronizationConstants.DATA_ELEMENT);
+ assertNotNull(data, "Could not find data element in the entity.");
+
+ String dataText = ((Element)data).getTextContent();
+ notesText = ((Element)note).getTextContent();
+
+ assertEquals(notesText, ListToStringExporter.NOTE_PREFIX + dataText, "Unexpected discrepancy between data and notes in the export.");
+ }
+
+ ++elementIndex;
+ }
+ }
+
+ @Test(expectedExceptions = IOException.class)
+ public void testExceptionHandling_Exporter_getExportingIterator() throws Exception {
+ final Exporter<?, ?> failingExporter = context.mock(Exporter.class);
+
+ final Synchronizer<?, ?> syncer = context.mock(Synchronizer.class);
+
+ context.checking(new Expectations() {
+ {
+ RuntimeException failure = new RuntimeException("Injected failure");
+
+ allowing(failingExporter).getExportingIterator();
+ will(throwException(failure));
+
+ allowing(syncer).getRequiredValidators();
+ will(returnValue(Collections.emptySet()));
+
+ allowing(syncer).getExporter();
+ will(returnValue(failingExporter));
+ }
+ });
+
+ Set<Synchronizer<?, ?>> syncers = this.<Synchronizer<?, ?>>asSet(syncer);
+
+ InputStream export = new ExportingInputStream(syncers, new HashMap<String, ExporterMessages>(), 1024, false);
+
+ readAll(new InputStreamReader(export, "UTF-8"));
+
+ //this should never be invoked, because reading the input stream should cause the exporter
+ //to fail...
+
+ fail("Successfully read the export even though one of the exporters threw an exception when asked for the exported entity iterator.");
+ }
+
+ @Test(expectedExceptions = IOException.class)
+ public void testExceptionHandling_ExportingIterator_next() throws Exception {
+ final ExportingIterator<?> iterator = context.mock(ExportingIterator.class);
+ final Exporter<?, ?> exporter = context.mock(Exporter.class);
+ final Importer<?, ?> importer = context.mock(Importer.class);
+ final Synchronizer<?, ?> syncer = context.mock(Synchronizer.class);
+
+ context.checking(new Expectations() {
+ {
+ RuntimeException failure = new RuntimeException("Injected failure");
+
+ allowing(iterator).hasNext();
+ will(returnValue(true));
+
+ allowing(iterator).next();
+ will(onConsecutiveCalls(returnValue("Success"), throwException(failure)));
+
+ allowing(iterator).export(with(any(ExportWriter.class)));
+
+ allowing(iterator).getNotes();
+
+ allowing(exporter).getExportingIterator();
+ will(returnValue(iterator));
+
+ allowing(exporter).getNotes();
+
+ allowing(syncer).getRequiredValidators();
+ will(returnValue(Collections.emptySet()));
+
+ allowing(syncer).getExporter();
+ will(returnValue(exporter));
+
+ allowing(syncer).getImporter();
+ will(returnValue(importer));
+
+ allowing(importer).getImportConfigurationDefinition();
+ }
+ });
+
+ Set<Synchronizer<?, ?>> syncers = this.<Synchronizer<?, ?>>asSet(syncer);
+
+ InputStream export = new ExportingInputStream(syncers, new HashMap<String, ExporterMessages>(), 1024, false);
+
+ readAll(new InputStreamReader(export, "UTF-8"));
+
+ //this should never be invoked, because reading the input stream should cause the exporter
+ //to fail...
+
+ fail("Successfully read the export even though one of the exporters threw an exception when asked for the next exported entity.");
+ }
+
+ public void testExceptionHandling_ExportingIterator_export() throws Exception {
+ final ExportingIterator<?> iterator = context.mock(ExportingIterator.class);
+ final Exporter<?, ?> exporter = context.mock(Exporter.class);
+ final Importer<?, ?> importer = context.mock(Importer.class);
+ final Synchronizer<?, ?> syncer = context.mock(Synchronizer.class);
+
+ context.checking(new Expectations() {
+ {
+ RuntimeException failure = new RuntimeException("Injected failure");
+
+ allowing(iterator).hasNext();
+ will(onConsecutiveCalls(returnValue(true), returnValue(true), returnValue(false)));
+
+ allowing(iterator).next();
+
+ allowing(iterator).export(with(any(ExportWriter.class)));
+ will(onConsecutiveCalls(returnValue(null), throwException(failure)));
+
+ allowing(iterator).getNotes();
+
+ allowing(exporter).getExportingIterator();
+ will(returnValue(iterator));
+
+ allowing(exporter).getNotes();
+
+ allowing(syncer).getRequiredValidators();
+ will(returnValue(Collections.emptySet()));
+
+ allowing(syncer).getExporter();
+ will(returnValue(exporter));
+
+ allowing(syncer).getImporter();
+ will(returnValue(importer));
+
+ allowing(importer).getImportConfigurationDefinition();
+ }
+ });
+
+ Set<Synchronizer<?, ?>> syncers = this.<Synchronizer<?, ?>>asSet(syncer);
+
+ InputStream export = new ExportingInputStream(syncers, new HashMap<String, ExporterMessages>(), 1024, false);
+
+ String exportContents = readAll(new InputStreamReader(export, "UTF-8"));
+
+ LOG.warn("Export contents:\n" + exportContents);
+
+ export = new ByteArrayInputStream(exportContents.getBytes("UTF-8"));
+
+ DocumentBuilder bld = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+
+ Document doc = bld.parse(export);
+
+ Element root = doc.getDocumentElement();
+
+ NodeList entities = root.getElementsByTagName(SynchronizationConstants.ENTITY_EXPORT_ELEMENT);
+
+ assertEquals(entities.getLength(), 2, "Unexpected number of exported elements");
+
+ //get the entity with the error
+ Element failedEntity = (Element) entities.item(1);
+ Node errorMessage = getDirectChildByTagName(failedEntity, SynchronizationConstants.ERROR_MESSAGE_ELEMENT);
+ assertNotNull(errorMessage, "Could not find the error-message element at the entity that failed to export.");
+ }
+
+ private <T> LinkedHashSet<T> asSet(T... ts) {
+ LinkedHashSet<T> ret = new LinkedHashSet<T>();
+ for (T t : ts) {
+ ret.add(t);
+ }
+
+ return ret;
+ }
+
+ private static String readAll(Reader rdr) throws IOException {
+ try {
+ StringBuilder bld = new StringBuilder();
+ int c;
+ while((c = rdr.read()) != -1) {
+ bld.append((char) c);
+ }
+
+ return bld.toString();
+ } finally {
+ rdr.close();
+ }
+ }
+
+ private static Node getDirectChildByTagName(Node node, String tagName) {
+ for(int i = 0; i < node.getChildNodes().getLength(); ++i) {
+ Node n = node.getChildNodes().item(i);
+ if (n.getNodeName().equals(tagName)) {
+ return n;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/MaxCountValidatorTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/MaxCountValidatorTest.java
new file mode 100644
index 0000000..b18662b
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/MaxCountValidatorTest.java
@@ -0,0 +1,52 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.sync.test;
+
+import static org.testng.Assert.fail;
+
+import org.testng.annotations.Test;
+
+import org.rhq.enterprise.server.sync.ValidationException;
+import org.rhq.enterprise.server.sync.validators.MaxCountValidator;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+@Test
+public class MaxCountValidatorTest {
+
+ public void testThrowsValidationExceptionAfterMaxEntitiesValidated() {
+ MaxCountValidator<String> validator = new MaxCountValidator<String>(3);
+
+ validator.initialize(null, null);
+
+ validator.validateExportedEntity("1");
+ validator.validateExportedEntity("2");
+ validator.validateExportedEntity("3");
+ try {
+ validator.validateExportedEntity("4");
+ fail("The max count validator shouldn't have accepted the 4th entry.");
+ } catch (ValidationException e) {
+ //expected
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/MetricTemplateExporterTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/MetricTemplateExporterTest.java
new file mode 100644
index 0000000..6987001
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/MetricTemplateExporterTest.java
@@ -0,0 +1,221 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.sync.test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jmock.Expectations;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.criteria.MeasurementDefinitionCriteria;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.sync.ExporterMessages;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerLocal;
+import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal;
+import org.rhq.enterprise.server.sync.ExportingInputStream;
+import org.rhq.enterprise.server.sync.MetricTemplateSynchronizer;
+import org.rhq.enterprise.server.sync.SynchronizationConstants;
+import org.rhq.enterprise.server.sync.Synchronizer;
+import org.rhq.enterprise.server.sync.validators.ConsistencyValidator;
+import org.rhq.test.JMockTest;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+@Test
+public class MetricTemplateExporterTest extends JMockTest {
+
+ private static final Log LOG = LogFactory.getLog(MetricTemplateExporterTest.class);
+
+ public void testCanExport() throws Exception {
+ final MeasurementDefinitionManagerLocal measurementDefinitionManager = context.mock(MeasurementDefinitionManagerLocal.class);
+ final MeasurementScheduleManagerLocal measurementScheduleManager = context.mock(MeasurementScheduleManagerLocal.class);
+ context.checking(new Expectations() {
+ {
+ allowing(measurementDefinitionManager).findMeasurementDefinitionsByCriteria(with(any(Subject.class)), with(any(MeasurementDefinitionCriteria.class)));
+ will(returnValue(getFakeMeasurementDefinitions()));
+ }
+ });
+
+ MetricTemplateSynchronizer exporter = new MetricTemplateSynchronizer(measurementDefinitionManager, measurementScheduleManager);
+
+ Set<Synchronizer<?, ?>> exporters = new HashSet<Synchronizer<?, ?>>();
+ exporters.add(exporter);
+
+ InputStream eis = new ExportingInputStream(exporters, new HashMap<String, ExporterMessages>(), 65536, false);
+
+ // String exportContents = readAll(new InputStreamReader(eis, "UTF-8"));
+ //
+ // LOG.warn("Export contents:\n" + exportContents);
+ //
+ // eis = new ByteArrayInputStream(exportContents.getBytes("UTF-8"));
+
+ // <?xml version="1.0" ?>
+ // <configuration-export>
+ // <validator class="org.rhq.enterprise.server.sync.validators.DeployedAgentPluginsValidator">
+ // <plugin name="fakePlugin" hash="12345" version="1.0.0.test"></plugin>
+ // </validator>
+ // <entities id="org.rhq.enterprise.server.sync.exporters.MetricTemplatesExporter">
+ // <entity>
+ // <data>
+ // <metricTemplate referencedEntityId="1" enabled="false" defaultInterval="0" metricName="m1" resourceTypePlugin="fakePlugin" resourceTypeName="fakeType"></metricTemplate>
+ // </data>
+ // </entity>
+ // <entity>
+ // <data>
+ // <metricTemplate referencedEntityId="2" enabled="false" defaultInterval="0" metricName="m2" resourceTypePlugin="fakePlugin" resourceTypeName="fakeType"></metricTemplate>
+ // </data>
+ // </entity>
+ // <entity>
+ // <data>
+ // <metricTemplate referencedEntityId="3" enabled="false" defaultInterval="0" metricName="m3" resourceTypePlugin="fakePlugin" resourceTypeName="fakeType"></metricTemplate>
+ // </data>
+ // </entity>
+ // </entities>
+ // </configuration-export>
+
+ DocumentBuilder bld = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+
+ Document doc = bld.parse(eis);
+
+ Element root = doc.getDocumentElement();
+
+ List<Node> validators = getDirectChildrenByTagName(root, SynchronizationConstants.VALIDATOR_ELEMENT);
+ Set<ConsistencyValidator> declaredValidators = exporter.getRequiredValidators();
+ assertEquals(validators.size(), declaredValidators.size(), "Unexpected number of validators in the export xml");
+
+ for (Node v : validators) {
+ Element validator = (Element) v;
+
+ String cls = validator.getAttribute(SynchronizationConstants.CLASS_ATTRIBUTE);
+
+ boolean found = false;
+ for (ConsistencyValidator dv : declaredValidators) {
+ if (cls.equals(dv.getClass().getName())) {
+ found = true;
+ break;
+ }
+ }
+
+ assertTrue(found, "The metric template exporter doesn't seem to declare a validator with class: " + cls
+ + ", but one such appeared in the export");
+ }
+
+ Element entities = (Element) getFirstDirectChildByTagName(root, SynchronizationConstants.ENTITIES_EXPORT_ELEMENT);
+
+ assertEquals(entities.getAttribute(SynchronizationConstants.ID_ATTRIBUTE), MetricTemplateSynchronizer.class.getName(), "Unexpected id of the entities element.");
+
+ NodeList metricTemplates = entities.getElementsByTagName("metricTemplate");
+
+ assertEquals(metricTemplates.getLength(), 3, "Unexpected number of exported metric templates.");
+
+ for(int i = 0; i < metricTemplates.getLength(); ++i) {
+ Element m = (Element) metricTemplates.item(i);
+ String index = Integer.toString(i + 1);
+ String expectedName = "m" + index;
+
+ assertEquals(m.getAttribute("referencedEntityId"), index, "Unexpected referencedEntityId value");
+ assertEquals(m.getAttribute("enabled"), "false", "Unexpected enabled value");
+ assertEquals(m.getAttribute("defaultInterval"), "0", "Unexpected defaultInterval value");
+ assertEquals(m.getAttribute("metricName"), expectedName, "Unexpected metricName value");
+ assertEquals(m.getAttribute("resourceTypePlugin"), "fakePlugin", "Unexpected resourceTypePlugin value");
+ assertEquals(m.getAttribute("resourceTypeName"), "fakeType", "Unexpected resourceTypeName value");
+ }
+ }
+
+ private static String readAll(Reader rdr) throws IOException {
+ try {
+ StringBuilder bld = new StringBuilder();
+ int c;
+ while ((c = rdr.read()) != -1) {
+ bld.append((char) c);
+ }
+
+ return bld.toString();
+ } finally {
+ rdr.close();
+ }
+ }
+
+ private static Node getFirstDirectChildByTagName(Node node, String tagName) {
+ for (int i = 0; i < node.getChildNodes().getLength(); ++i) {
+ Node n = node.getChildNodes().item(i);
+ if (n.getNodeName().equals(tagName)) {
+ return n;
+ }
+ }
+
+ return null;
+ }
+
+ private static List<Node> getDirectChildrenByTagName(Node node, String tagName) {
+ List<Node> ret = new ArrayList<Node>();
+ for (int i = 0; i < node.getChildNodes().getLength(); ++i) {
+ Node n = node.getChildNodes().item(i);
+ if (n.getNodeName().equals(tagName)) {
+ ret.add(n);
+ }
+ }
+
+ return ret;
+ }
+
+ private static PageList<MeasurementDefinition> getFakeMeasurementDefinitions() {
+ List<MeasurementDefinition> ret = new ArrayList<MeasurementDefinition>();
+
+ ResourceType rt = new ResourceType("fakeType", "fakePlugin", ResourceCategory.PLATFORM, null);
+
+ ret.add(new MeasurementDefinition(rt, "m1"));
+ ret.add(new MeasurementDefinition(rt, "m2"));
+ ret.add(new MeasurementDefinition(rt, "m3"));
+
+ for(int i = 0; i < ret.size(); ++i) {
+ ret.get(i).setId(i + 1);
+ }
+
+ return new PageList<MeasurementDefinition>(ret, PageControl.getUnlimitedInstance());
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/MetricTemplateImporterTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/MetricTemplateImporterTest.java
new file mode 100644
index 0000000..8c615b4
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/MetricTemplateImporterTest.java
@@ -0,0 +1,412 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.sync.test;
+
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.hamcrest.Description;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.api.Action;
+import org.jmock.api.Invocation;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertyList;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.NumericType;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.sync.entity.MetricTemplate;
+import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal;
+import org.rhq.enterprise.server.sync.importers.ExportedEntityMatcher;
+import org.rhq.enterprise.server.sync.importers.MetricTemplateImporter;
+import org.rhq.test.JMockTest;
+
+/**
+ * @author Lukas Krejci
+ */
+@Test
+public class MetricTemplateImporterTest extends JMockTest {
+
+ private static class TestPrerequisities {
+ private EntityManager em;
+ private Query q;
+ private MeasurementScheduleManagerLocal msm;
+ private List<MeasurementDefinition> defs;
+
+ public TestPrerequisities(Mockery context) {
+ em = context.mock(EntityManager.class);
+ msm = context.mock(MeasurementScheduleManagerLocal.class);
+ q = context.mock(Query.class);
+ }
+
+ public Query getQuery() {
+ return q;
+ }
+
+ public EntityManager getEntityManager() {
+ return em;
+ }
+
+ public MeasurementScheduleManagerLocal getMeasurementScheduleManager() {
+ return msm;
+ }
+
+ public void setMeasurementDefinitions(List<MeasurementDefinition> defs) {
+ this.defs = defs;
+ }
+
+ @SuppressWarnings("static-access")
+ public void addExpectations(Expectations expectations) {
+ expectations.allowing(em).createQuery(expectations.with(expectations.any(String.class)));
+ expectations.will(Expectations.returnValue(q));
+
+ expectations.allowing(q).getResultList();
+ expectations.will(Expectations.returnValue(defs));
+ }
+ };
+
+ private static final ResourceType FAKE_RESOURCE_TYPE = new ResourceType("fake", "fake", ResourceCategory.PLATFORM,
+ null);
+
+ public void testNonMatchingMeasurementDefinitionsAreIgnored() {
+ final TestPrerequisities prereqs = new TestPrerequisities(context);
+
+ //some data to supply
+ MeasurementDefinition def = new MeasurementDefinition(FAKE_RESOURCE_TYPE, "fake");
+ def.setId(1);
+ def.setDefaultOn(true);
+ def.setDefaultInterval(1000);
+
+ //now we setup the prerequisites to return the faked results from the database
+ //for the non-matching template, we want the "database" to return no results
+ //while for the matching template, we want the "database" to return our own def.
+ prereqs.setMeasurementDefinitions(Collections.singletonList(def));
+
+ //setup the expected behavior
+ context.checking(new Expectations() {
+ {
+ prereqs.addExpectations(this);
+
+ MeasurementScheduleManagerLocal msm = prereqs.getMeasurementScheduleManager();
+
+ //this is what we expect the measurement schedule manager msm to be
+ //called with when the importer finishes its work.
+ one(msm).updateDefaultCollectionIntervalAndEnablementForMeasurementDefinitions(with(any(Subject.class)),
+ with(new int[] { 1 }), with(1000L), with(true), with(false));
+ }
+ });
+
+ MetricTemplateImporter importer =
+ new MetricTemplateImporter(null, prereqs.getEntityManager(), prereqs.getMeasurementScheduleManager());
+
+ MetricTemplate nonMatching = new MetricTemplate();
+ nonMatching.setResourceTypeName("asf");
+ nonMatching.setResourceTypePlugin("asfd");
+ nonMatching.setMetricName("asf");
+
+ MetricTemplate matching = new MetricTemplate(def);
+
+ importer.configure(null);
+
+ ExportedEntityMatcher<MeasurementDefinition, MetricTemplate> matcher = importer.getExportedEntityMatcher();
+
+ assertNull(matcher.findMatch(nonMatching), "The non-matching metric template shouldn't have been matched.");
+ assertSame(matcher.findMatch(matching), def,
+ "The matching metric template should have found the defined measurement definition");
+
+ //this is the "meat" of the test..
+ //we call update() twice but only get 1 actual change pour down to database
+ //and the importer not choking on this.
+ importer.update(null, nonMatching);
+ importer.update(def, matching);
+
+ //this should invoke the mocked measurement schedule manager and the expectations should check it gets called
+ //correctly by the importer.
+ importer.finishImport();
+ }
+
+ public void testCanUpdateEnablements() {
+ MeasurementDefinition defToEnable = new MeasurementDefinition(FAKE_RESOURCE_TYPE, "enabled");
+ MeasurementDefinition defToDisable = new MeasurementDefinition(FAKE_RESOURCE_TYPE, "disable");
+
+ defToEnable.setId(1);
+ defToEnable.setDefaultOn(true);
+ defToEnable.setDefaultInterval(1000);
+
+ defToDisable.setId(2);
+ defToDisable.setDefaultOn(false);
+ defToDisable.setDefaultInterval(2000);
+
+ final TestPrerequisities prereqs = new TestPrerequisities(context);
+ prereqs.setMeasurementDefinitions(Arrays.asList(defToEnable, defToDisable));
+
+ context.checking(new Expectations() {
+ {
+ prereqs.addExpectations(this);
+ MeasurementScheduleManagerLocal msm = prereqs.getMeasurementScheduleManager();
+
+ //this is what we expect the measurement schedule manager msm to be
+ //called with when the importer finishes its work.
+ one(msm).updateDefaultCollectionIntervalAndEnablementForMeasurementDefinitions(with(any(Subject.class)),
+ with(new int[] { 1 }), with(1000L), with(true), with(false));
+ one(msm).updateDefaultCollectionIntervalAndEnablementForMeasurementDefinitions(with(any(Subject.class)),
+ with(new int[] { 2 }), with(2000L), with(false), with(false));
+ }
+ });
+
+ MetricTemplateImporter importer =
+ new MetricTemplateImporter(null, prereqs.getEntityManager(), prereqs.getMeasurementScheduleManager());
+
+ importer.configure(null);
+
+ ExportedEntityMatcher<MeasurementDefinition, MetricTemplate> matcher = importer.getExportedEntityMatcher();
+
+ MetricTemplate match1 = new MetricTemplate(defToEnable);
+ MetricTemplate match2 = new MetricTemplate(defToDisable);
+
+ assertSame(matcher.findMatch(match1), defToEnable,
+ "The matching metric template should have found the defined measurement definition");
+ assertSame(matcher.findMatch(match2), defToDisable,
+ "The matching metric template should have found the defined measurement definition");
+
+ importer.update(defToEnable, match1);
+ importer.update(defToDisable, match2);
+
+ //this should invoke the mocked measurement schedule manager and the expectations should check it gets called
+ //correctly by the importer.
+ importer.finishImport();
+
+ }
+
+ public void testCanUpdateSchedules() {
+ MeasurementDefinition def = new MeasurementDefinition(FAKE_RESOURCE_TYPE, "def");
+ def.setId(1);
+ def.setDefaultOn(true);
+ def.setDefaultInterval(1000);
+
+ final TestPrerequisities prereqs = new TestPrerequisities(context);
+ prereqs.setMeasurementDefinitions(Collections.singletonList(def));
+
+ context.checking(new Expectations() {
+ {
+ prereqs.addExpectations(this);
+
+ MeasurementScheduleManagerLocal msm = prereqs.getMeasurementScheduleManager();
+
+ one(msm).updateDefaultCollectionIntervalAndEnablementForMeasurementDefinitions(with(any(Subject.class)),
+ with(new int[] { 1 }), with(1000L), with(true), with(true));
+ }
+ });
+
+ MetricTemplateImporter importer =
+ new MetricTemplateImporter(null, prereqs.getEntityManager(), prereqs.getMeasurementScheduleManager());
+
+ Configuration importConfig = new Configuration();
+ importConfig.put(new PropertySimple(MetricTemplateImporter.UPDATE_ALL_SCHEDULES_PROPERTY, true));
+
+ importer.configure(importConfig);
+
+ ExportedEntityMatcher<MeasurementDefinition, MetricTemplate> matcher = importer.getExportedEntityMatcher();
+
+ MetricTemplate template = new MetricTemplate(def);
+
+ assertSame(matcher.findMatch(template), def,
+ "The matching metric template should have found the defined measurement definition");
+
+ importer.update(def, template);
+
+ //this should invoke the mocked measurement schedule manager and the expectations should check it gets called
+ //correctly by the importer.
+ importer.finishImport();
+ }
+
+ public void testPerMetricUpdateScheduleOverrides() {
+ MeasurementDefinition updatedDef = new MeasurementDefinition(FAKE_RESOURCE_TYPE, "def");
+ updatedDef.setId(1);
+ updatedDef.setDefaultOn(true);
+ updatedDef.setDefaultInterval(1000);
+ MeasurementDefinition notUpdatedDef = new MeasurementDefinition(FAKE_RESOURCE_TYPE, "ndef");
+ notUpdatedDef.setId(2);
+ notUpdatedDef.setDefaultOn(true);
+ notUpdatedDef.setDefaultInterval(2000);
+
+ final TestPrerequisities prereqs = new TestPrerequisities(context);
+ prereqs.setMeasurementDefinitions(Arrays.asList(updatedDef, notUpdatedDef));
+
+ context.checking(new Expectations() {
+ {
+ prereqs.addExpectations(this);
+
+ MeasurementScheduleManagerLocal msm = prereqs.getMeasurementScheduleManager();
+
+ one(msm).updateDefaultCollectionIntervalAndEnablementForMeasurementDefinitions(with(any(Subject.class)),
+ with(new int[] { 1 }), with(1000L), with(true), with(true));
+ one(msm).updateDefaultCollectionIntervalAndEnablementForMeasurementDefinitions(with(any(Subject.class)),
+ with(new int[] { 2 }), with(2000L), with(true), with(false));
+ }
+ });
+
+ MetricTemplateImporter importer =
+ new MetricTemplateImporter(null, prereqs.getEntityManager(), prereqs.getMeasurementScheduleManager());
+
+ Configuration importConfig = new Configuration();
+
+ //this is the default, but let's be specific here so that this doesn't start failing if we change the
+ //default in the future.
+ importConfig.put(new PropertySimple(MetricTemplateImporter.UPDATE_ALL_SCHEDULES_PROPERTY, false));
+
+ //set the def to update the schedules anyway
+ PropertyList list = new PropertyList(MetricTemplateImporter.METRIC_UPDATE_OVERRIDES_PROPERTY);
+ importConfig.put(list);
+ PropertyMap map = new PropertyMap(MetricTemplateImporter.METRIC_UPDATE_OVERRIDE_PROPERTY);
+ list.add(map);
+ map.put(new PropertySimple(MetricTemplateImporter.METRIC_NAME_PROPERTY, "def"));
+ map.put(new PropertySimple(MetricTemplateImporter.RESOURCE_TYPE_NAME_PROPERTY, FAKE_RESOURCE_TYPE.getName()));
+ map.put(new PropertySimple(MetricTemplateImporter.RESOURCE_TYPE_PLUGIN_PROPERTY, FAKE_RESOURCE_TYPE.getPlugin()));
+ map.put(new PropertySimple(MetricTemplateImporter.UPDATE_SCHEDULES_PROPERTY, true));
+
+ importer.configure(importConfig);
+
+ ExportedEntityMatcher<MeasurementDefinition, MetricTemplate> matcher = importer.getExportedEntityMatcher();
+
+ MetricTemplate template1 = new MetricTemplate(updatedDef);
+ MetricTemplate template2 = new MetricTemplate(notUpdatedDef);
+
+ assertSame(matcher.findMatch(template1), updatedDef,
+ "The matching metric template should have found the defined measurement definition");
+ assertSame(matcher.findMatch(template2), notUpdatedDef,
+ "The matching metric template should have found the defined measurement definition");
+
+ importer.update(updatedDef, template1);
+ importer.update(notUpdatedDef, template2);
+
+ //this should invoke the mocked measurement schedule manager and the expectations should check it gets called
+ //correctly by the importer.
+ importer.finishImport();
+ }
+
+ public void testNullConfigurationInterpretedAsDefault() {
+ //this doesn't need to be implemented as long as at least one of the other
+ //test methods passes null to the importer.configure() and succeeds.
+ testNonMatchingMeasurementDefinitionsAreIgnored();
+ }
+
+ public void testDistinguishingBetweenNormalAndPerMinuteTemplates() {
+ MeasurementDefinition normalDef = new MeasurementDefinition(FAKE_RESOURCE_TYPE, "def");
+ MeasurementDefinition perMinuteDef = new MeasurementDefinition(FAKE_RESOURCE_TYPE, "def");
+
+ normalDef.setId(1);
+ normalDef.setDefaultOn(true);
+ normalDef.setDefaultInterval(1000);
+
+ perMinuteDef.setId(2);
+ perMinuteDef.setDefaultOn(false);
+ perMinuteDef.setDefaultInterval(2000);
+ perMinuteDef.setRawNumericType(NumericType.TRENDSUP);
+
+ final TestPrerequisities prereqs = new TestPrerequisities(context);
+ prereqs.setMeasurementDefinitions(Arrays.asList(normalDef, perMinuteDef));
+
+ context.checking(new Expectations() {
+ {
+ prereqs.addExpectations(this);
+
+ MeasurementScheduleManagerLocal msm = prereqs.getMeasurementScheduleManager();
+
+ one(msm).updateDefaultCollectionIntervalAndEnablementForMeasurementDefinitions(with(any(Subject.class)),
+ with(new int[] { 1 }), with(1000L), with(true), with(false));
+ one(msm).updateDefaultCollectionIntervalAndEnablementForMeasurementDefinitions(with(any(Subject.class)),
+ with(new int[] { 2 }), with(2000L), with(false), with(false));
+ }
+ });
+
+ MetricTemplateImporter importer =
+ new MetricTemplateImporter(null, prereqs.getEntityManager(), prereqs.getMeasurementScheduleManager());
+
+ importer.configure(null);
+
+ ExportedEntityMatcher<MeasurementDefinition, MetricTemplate> matcher = importer.getExportedEntityMatcher();
+
+ MetricTemplate template1 = new MetricTemplate(normalDef);
+ MetricTemplate template2 = new MetricTemplate(perMinuteDef);
+
+ assertSame(matcher.findMatch(template1), normalDef,
+ "The matching metric template should have found the defined measurement definition");
+ assertSame(matcher.findMatch(template2), perMinuteDef,
+ "The matching metric template should have found the defined measurement definition");
+
+ importer.update(normalDef, template1);
+ importer.update(perMinuteDef, template2);
+
+ //this should invoke the mocked measurement schedule manager and the expectations should check it gets called
+ //correctly by the importer.
+ importer.finishImport();
+ }
+
+ public void testNotifiesAboutIgnoredMetricTemplates() throws Exception {
+ final TestPrerequisities prereqs = new TestPrerequisities(context);
+ prereqs.setMeasurementDefinitions(Collections.<MeasurementDefinition>emptyList());
+
+ context.checking(new Expectations() {
+ {
+ prereqs.addExpectations(this);
+ }
+ });
+
+ MetricTemplateImporter importer =
+ new MetricTemplateImporter(null, prereqs.getEntityManager(), prereqs.getMeasurementScheduleManager());
+
+ importer.configure(null);
+
+ importer.configure(null);
+
+ MetricTemplate unmatched = new MetricTemplate();
+ unmatched.setMetricName("made-up");
+ unmatched.setResourceTypeName("made-up");
+ unmatched.setResourceTypePlugin("made-up");
+
+ ExportedEntityMatcher<MeasurementDefinition, MetricTemplate> matcher = importer.getExportedEntityMatcher();
+
+ assertNull(matcher.findMatch(unmatched));
+
+ importer.update(null, unmatched);
+
+ String notes = importer.finishImport();
+
+ String expectedNotes =
+ MetricTemplateImporter.getUnmatchedMetricTemplatesReport(Collections.singleton(unmatched));
+
+ assertEquals(notes, expectedNotes);
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SynchronizationManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SynchronizationManagerBeanTest.java
new file mode 100644
index 0000000..a0a3cc5
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SynchronizationManagerBeanTest.java
@@ -0,0 +1,740 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.sync.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.UUID;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+import javax.persistence.EntityManager;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathFactory;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.criteria.MeasurementDefinitionCriteria;
+import org.rhq.core.domain.criteria.ResourceCriteria;
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.DisplayType;
+import org.rhq.core.domain.measurement.MeasurementCategory;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementSchedule;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.resource.InventoryStatus;
+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.domain.sync.ExportReport;
+import org.rhq.core.domain.sync.ImportConfiguration;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.authz.PermissionException;
+import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerLocal;
+import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.sync.ExportReader;
+import org.rhq.enterprise.server.sync.ExportWriter;
+import org.rhq.enterprise.server.sync.MetricTemplateSynchronizer;
+import org.rhq.enterprise.server.sync.NoSingleEntity;
+import org.rhq.enterprise.server.sync.SynchronizationConstants;
+import org.rhq.enterprise.server.sync.SynchronizationManagerLocal;
+import org.rhq.enterprise.server.sync.Synchronizer;
+import org.rhq.enterprise.server.sync.SynchronizerFactory;
+import org.rhq.enterprise.server.sync.SystemSettingsSynchronizer;
+import org.rhq.enterprise.server.sync.ValidationException;
+import org.rhq.enterprise.server.sync.exporters.Exporter;
+import org.rhq.enterprise.server.sync.exporters.ExportingIterator;
+import org.rhq.enterprise.server.sync.importers.ExportedEntityMatcher;
+import org.rhq.enterprise.server.sync.importers.Importer;
+import org.rhq.enterprise.server.sync.validators.ConsistencyValidator;
+import org.rhq.enterprise.server.sync.validators.EntityValidator;
+import org.rhq.enterprise.server.system.SystemManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestServerPluginService;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.ResourceTreeHelper;
+
+/**
+ * Tests the SynchronizationManagerBean on a live dataset.
+ *
+ * @author Lukas Krejci
+ */
+@Test
+public class SynchronizationManagerBeanTest extends AbstractEJB3Test {
+
+ private SynchronizationManagerLocal synchronizationManager;
+ private Subject user;
+ private ExportReport export;
+
+ private static final String RESOURCE_TYPE_NAME = "SynchronizationManagerBeanTest";
+ private static final String PLUGIN_NAME = "SynchronizationManagerBeanTest";
+ private static final String METRIC_NAME = "SynchronizationManagerBeanTest";
+
+ private static class TestData {
+ public Properties systemSettings;
+ public ResourceType fakeType;
+ public Resource fakePlatform;
+ public TestServerPluginService testServerPluginService;
+ }
+
+ //this can't be mocked out because the config sync machinery has to be able to
+ //instantiate this class
+ public static class ImportConfigurationCheckingSynchronizer implements Synchronizer<NoSingleEntity, String> {
+
+ public static boolean importerConfigured;
+ public static boolean importValidatorsObtainedAfterConfiguration;
+
+ public static void reset() {
+ importerConfigured = false;
+ importValidatorsObtainedAfterConfiguration = false;
+ }
+
+ @Override
+ public void initialize(Subject subject, EntityManager entityManager) {
+ }
+
+ @Override
+ public Exporter<NoSingleEntity, String> getExporter() {
+ return new Exporter<NoSingleEntity, String>() {
+
+ @Override
+ public ExportingIterator<String> getExportingIterator() {
+ return new ExportingIterator<String>() {
+ boolean ran = false;
+
+ @Override
+ public boolean hasNext() {
+ if (ran) {
+ return false;
+ }
+
+ ran = true;
+ return true;
+ }
+
+ @Override
+ public String next() {
+ return null;
+ }
+
+ @Override
+ public void remove() {
+ }
+
+ @Override
+ public void export(ExportWriter output) throws XMLStreamException {
+ output.writeStartElement("my-entity");
+ output.writeCharacters("value");
+ output.writeEndElement();
+ }
+
+ @Override
+ public String getNotes() {
+ return null;
+ }
+
+ };
+ }
+
+ @Override
+ public String getNotes() {
+ return null;
+ }
+
+ };
+ }
+
+ @Override
+ public Importer<NoSingleEntity, String> getImporter() {
+ return new Importer<NoSingleEntity, String>() {
+
+ @Override
+ public ConfigurationDefinition getImportConfigurationDefinition() {
+ return new ConfigurationDefinition("fake", null);
+ }
+
+ @Override
+ public void configure(Configuration importConfiguration) {
+ importerConfigured = true;
+ }
+
+ @Override
+ public ExportedEntityMatcher<NoSingleEntity, String> getExportedEntityMatcher() {
+ return null;
+ }
+
+ @Override
+ public Set<EntityValidator<String>> getEntityValidators() {
+ EntityValidator<String> v = new EntityValidator<String>() {
+
+ @Override
+ public void validateExportedEntity(String entity) throws ValidationException {
+ }
+
+ @Override
+ public void initialize(Subject subject, EntityManager entityManager) {
+ }
+ };
+
+ if (importerConfigured) {
+ importValidatorsObtainedAfterConfiguration = true;
+ }
+
+ return Collections.singleton(v);
+ }
+
+ @Override
+ public void update(NoSingleEntity entity, String exportedEntity) throws Exception {
+ }
+
+ @Override
+ public String unmarshallExportedEntity(ExportReader reader) throws XMLStreamException {
+ return reader.getElementText();
+ }
+
+ @Override
+ public String finishImport() throws Exception {
+ return null;
+ }
+
+ };
+ }
+
+ @Override
+ public Set<ConsistencyValidator> getRequiredValidators() {
+ return Collections.emptySet();
+ }
+
+ }
+
+ private TestData testData;
+
+ //I just don't get why this can't be a @BeforeTest
+ //but when it was declared as such (together with tearDown() being an @AfterTest)
+ //no tests would work. I have no idea why...
+ private void setup(boolean createExport) throws Exception {
+ testData = new TestData();
+ getTransactionManager().begin();
+ try {
+ EntityManager em = getEntityManager();
+
+ //add our new metric template that we are going to perform the tests with
+ testData.fakeType = new ResourceType(RESOURCE_TYPE_NAME, PLUGIN_NAME, ResourceCategory.PLATFORM, null);
+
+ MeasurementDefinition mdef = new MeasurementDefinition(METRIC_NAME, MeasurementCategory.PERFORMANCE,
+ MeasurementUnits.NONE, DataType.MEASUREMENT, true, 600000, DisplayType.SUMMARY);
+ testData.fakeType.addMetricDefinition(mdef);
+
+ em.persist(testData.fakeType);
+
+ testData.fakePlatform = new Resource(RESOURCE_TYPE_NAME, RESOURCE_TYPE_NAME, testData.fakeType);
+ testData.fakePlatform.setUuid(UUID.randomUUID().toString());
+ testData.fakePlatform.setInventoryStatus(InventoryStatus.COMMITTED);
+
+ MeasurementSchedule sched = new MeasurementSchedule(mdef, testData.fakePlatform);
+ sched.setInterval(600000);
+
+ testData.fakePlatform.addSchedule(sched);
+
+ em.persist(testData.fakePlatform);
+
+ em.persist(sched);
+
+ em.flush();
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ getTransactionManager().rollback();
+ throw e;
+ }
+
+ //we need this because the drift plugins are referenced from the system settings that we use in our tests
+ testData.testServerPluginService = new TestServerPluginService();
+ prepareCustomServerPluginService(testData.testServerPluginService);
+ testData.testServerPluginService.startMasterPluginContainer();
+
+ synchronizationManager = LookupUtil.getSynchronizationManager();
+
+ SystemManagerLocal systemManager = LookupUtil.getSystemManager();
+ //make sure the system manager is in sync w/ the db we just changed in dbsetup
+ systemManager.loadSystemConfigurationCache();
+
+ testData.systemSettings = systemManager.getSystemConfiguration(freshUser());
+
+ if (createExport) {
+ export = synchronizationManager.exportAllSubsystems(freshUser());
+ }
+ }
+
+ private void tearDown() throws Exception {
+ try {
+ getTransactionManager().begin();
+ try {
+ LookupUtil.getSystemManager().setSystemConfiguration(freshUser(), testData.systemSettings, true);
+
+ EntityManager em = getEntityManager();
+
+ MeasurementSchedule sched = em.find(MeasurementSchedule.class, testData.fakePlatform.getSchedules()
+ .iterator().next().getId());
+ em.remove(sched);
+
+ Resource attachedPlatform = em.find(Resource.class, testData.fakePlatform.getId());
+ ResourceTreeHelper.deleteResource(em, attachedPlatform);
+
+ ResourceType attachedType = em.find(ResourceType.class, testData.fakeType.getId());
+ em.remove(attachedType);
+
+ em.flush();
+
+ getTransactionManager().commit();
+ } catch (Exception e) {
+ getTransactionManager().rollback();
+ throw e;
+ }
+ } finally {
+ unprepareServerPluginService();
+ //unnecessary, done by above method
+ //testData.testServerPluginService.stopMasterPluginContainer();
+
+ export = null;
+ testData = null;
+ synchronizationManager = null;
+ }
+ }
+
+ public void testExport() throws Exception {
+ setup(true);
+ try {
+ assertNull("Export shouldn't generate an error message.", export.getErrorMessage());
+ assertTrue("The export should contain some data.", export.getExportFile().length > 0);
+ } finally {
+ tearDown();
+ }
+ }
+
+ public void testImportWithDefaultConfiguration() throws Exception {
+ setup(true);
+
+ try {
+ SystemManagerLocal systemManager = LookupUtil.getSystemManager();
+ MeasurementDefinitionManagerLocal measurementDefinitionManager = LookupUtil
+ .getMeasurementDefinitionManager();
+
+ Properties beforeSystemSettings = systemManager.getSystemConfiguration(freshUser());
+ MeasurementDefinitionCriteria criteria = new MeasurementDefinitionCriteria();
+ criteria.setPageControl(PageControl.getUnlimitedInstance());
+ criteria.fetchResourceType(true);
+
+ List<MeasurementDefinition> beforeMeasurementDefinitions = measurementDefinitionManager
+ .findMeasurementDefinitionsByCriteria(freshUser(), criteria);
+
+ synchronizationManager.importAllSubsystems(freshUser(), export.getExportFile(), null);
+
+ //this is to work around BZ 735810
+ systemManager.loadSystemConfigurationCache();
+
+ Properties afterSystemSettings = systemManager.getSystemConfiguration(freshUser());
+ List<MeasurementDefinition> afterMeasurementDefinitions = measurementDefinitionManager
+ .findMeasurementDefinitionsByCriteria(freshUser(), criteria);
+
+ assertEquals("System settings unexpectedly differ", beforeSystemSettings, afterSystemSettings);
+
+ //make sure we don't fail on simple order differences, which are not important here..
+ Set<MeasurementDefinition> beforeDefsToCheck = new HashSet<MeasurementDefinition>(
+ beforeMeasurementDefinitions);
+ Set<MeasurementDefinition> afterDefsToCheck = new HashSet<MeasurementDefinition>(
+ afterMeasurementDefinitions);
+ assertEquals("Measurement definitions unexpectedly differ", beforeDefsToCheck, afterDefsToCheck);
+ } finally {
+ tearDown();
+ }
+ }
+
+ public void testImportWithRedefinedConfigurationInExportFile() throws Exception {
+ setup(true);
+
+ try {
+ String exportXML = getExportData();
+
+ exportXML = updateSystemSettingsImportConfiguration(exportXML);
+ exportXML = updateMetricTemplatesImportConfiguration(exportXML);
+
+ InputStream exportData = createCompressedStream(exportXML);
+
+ try {
+ synchronizationManager.importAllSubsystems(freshUser(), exportData, null);
+ } finally {
+ exportData.close();
+ }
+
+ //now check that everything got imported according to the changed configuration
+ SystemManagerLocal systemManager = LookupUtil.getSystemManager();
+ Properties settings = systemManager.getSystemConfiguration(freshUser());
+
+ assertEquals(settings.getProperty("CAM_BASE_URL"), "http://testing.domain:7080");
+
+ MeasurementDefinitionManagerLocal measurementDefinitionManager = LookupUtil
+ .getMeasurementDefinitionManager();
+ MeasurementDefinitionCriteria crit = new MeasurementDefinitionCriteria();
+ crit.addFilterResourceTypeName(RESOURCE_TYPE_NAME);
+ crit.addFilterName(METRIC_NAME);
+ MeasurementDefinition mdef = measurementDefinitionManager.findMeasurementDefinitionsByCriteria(freshUser(),
+ crit).get(0);
+
+ assertEquals("The " + METRIC_NAME + " metric should have been updated with default interval of 30s",
+ Long.valueOf(30000), new Long(mdef.getDefaultInterval()));
+
+ //ok, and now test that the platform resource schedule was updated as well
+
+ //get the resource id first
+ ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+ ResourceCriteria rcrit = new ResourceCriteria();
+ rcrit.addFilterResourceTypeName(RESOURCE_TYPE_NAME);
+ List<Resource> platforms = resourceManager.findResourcesByCriteria(freshUser(), rcrit);
+
+ assertEquals("Unexpected number of platform resources found.", 1, platforms.size());
+
+ int platformResourceId = platforms.get(0).getId();
+
+ //now find the schedule for the measurement
+ MeasurementScheduleManagerLocal measurementScheduleManager = LookupUtil.getMeasurementScheduleManager();
+ List<MeasurementSchedule> schedules = measurementScheduleManager.findSchedulesByResourceIdAndDefinitionIds(
+ freshUser(), platformResourceId, new int[] { mdef.getId() });
+
+ assertEquals("Unexpected number of '" + METRIC_NAME + "' schedules found.", 1, schedules.size());
+
+ assertEquals("The schedule should have been updated along with the definition during the config sync",
+ 30000, schedules.get(0).getInterval());
+
+ } finally {
+ tearDown();
+ }
+ }
+
+ public void testManuallyPassedImportConfigurationHasPrecendenceOverTheInlinedOne() throws Exception {
+ setup(true);
+
+ try {
+ //let's read the original values from the database, so that we know what to compare against
+ SystemManagerLocal systemManager = LookupUtil.getSystemManager();
+ Properties settings = systemManager.getSystemConfiguration(freshUser());
+
+ String originalBaseUrl = settings.getProperty("CAM_BASE_URL");
+
+ MeasurementDefinitionManagerLocal measurementDefinitionManager = LookupUtil
+ .getMeasurementDefinitionManager();
+ MeasurementDefinitionCriteria crit = new MeasurementDefinitionCriteria();
+ crit.addFilterResourceTypeName(RESOURCE_TYPE_NAME);
+ crit.addFilterName(METRIC_NAME);
+ MeasurementDefinition distroNameDef = measurementDefinitionManager.findMeasurementDefinitionsByCriteria(
+ freshUser(), crit).get(0);
+
+ long originalInterval = distroNameDef.getDefaultInterval();
+
+ //now modify the default configuration in the export file
+ String exportXML = getExportData();
+
+ exportXML = updateSystemSettingsImportConfiguration(exportXML);
+ exportXML = updateMetricTemplatesImportConfiguration(exportXML);
+
+ InputStream exportData = createCompressedStream(exportXML);
+
+ //let's just use the default configs so that we don't apply the changes suggested in
+ //the changed default configs created above
+ ImportConfiguration systemSettingsConfiguration = new ImportConfiguration(
+ SystemSettingsSynchronizer.class.getName(), new SystemSettingsSynchronizer().getImporter()
+ .getImportConfigurationDefinition().getDefaultTemplate().createConfiguration());
+ ImportConfiguration metricTemplatesConfiguration = new ImportConfiguration(
+ MetricTemplateSynchronizer.class.getName(), new MetricTemplateSynchronizer().getImporter()
+ .getImportConfigurationDefinition().getDefaultTemplate().createConfiguration());
+
+ try {
+ synchronizationManager.importAllSubsystems(freshUser(), exportData,
+ Arrays.asList(systemSettingsConfiguration, metricTemplatesConfiguration));
+ } finally {
+ exportData.close();
+ }
+
+ //now check that we import using the manually create configurations, not the inlined ones
+ settings = systemManager.getSystemConfiguration(freshUser());
+
+ assertEquals(settings.getProperty("CAM_BASE_URL"), originalBaseUrl);
+
+ measurementDefinitionManager = LookupUtil.getMeasurementDefinitionManager();
+ distroNameDef = measurementDefinitionManager.findMeasurementDefinitionsByCriteria(freshUser(), crit).get(0);
+
+ //the definition should have been updated by the data from the export file
+ assertEquals("The " + METRIC_NAME + " metric shouldn't have changed its default interval", 30000,
+ distroNameDef.getDefaultInterval());
+
+ //ok, and now test that the platform resource schedule was NOT updated because it was configured not to.
+
+ //get the resource id first
+ ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+ ResourceCriteria rcrit = new ResourceCriteria();
+ rcrit.addFilterResourceTypeName(RESOURCE_TYPE_NAME);
+ List<Resource> platforms = resourceManager.findResourcesByCriteria(freshUser(), rcrit);
+
+ assertEquals("Unexpected number of platform resources found.", 1, platforms.size());
+
+ int platformResourceId = platforms.get(0).getId();
+
+ //now find the schedule for the measurement
+ MeasurementScheduleManagerLocal measurementScheduleManager = LookupUtil.getMeasurementScheduleManager();
+ List<MeasurementSchedule> schedules = measurementScheduleManager.findSchedulesByResourceIdAndDefinitionIds(
+ freshUser(), platformResourceId, new int[] { distroNameDef.getId() });
+
+ assertEquals("Unexpected number of '" + METRIC_NAME + "' schedules found.", 1, schedules.size());
+
+ assertEquals("The schedule should have been updated along with the definition during the config sync",
+ originalInterval, schedules.get(0).getInterval());
+
+ } finally {
+ tearDown();
+ }
+ }
+
+ public void testUnknownValidatorsAreIgnored() throws Exception {
+ setup(true);
+
+ try {
+ String export = getExportData();
+
+ Document xml = DocumentBuilderFactory.newInstance().newDocumentBuilder()
+ .parse(new InputSource(new StringReader(export)));
+
+ Element unknownValidator = xml.createElement("validator");
+ unknownValidator.setAttribute(SynchronizationConstants.CLASS_ATTRIBUTE, "org.nothing.UnknownValidator");
+
+ xml.getDocumentElement().insertBefore(unknownValidator, xml.getDocumentElement().getFirstChild());
+
+ export = documentToString(xml);
+
+ InputStream exportStream = createCompressedStream(export);
+
+ synchronizationManager.importAllSubsystems(freshUser(), exportStream, null);
+ } finally {
+ tearDown();
+ }
+ }
+
+ public void testImporterConfiguredBeforeValidatorsObtained() throws Exception {
+ setup(false);
+
+ try {
+ ImportConfigurationCheckingSynchronizer.reset();
+
+ synchronizationManager.setSynchronizerFactory(new SynchronizerFactory() {
+ @Override
+ public Set<Synchronizer<?, ?>> getAllSynchronizers() {
+ return Collections.<Synchronizer<?, ?>> singleton(new ImportConfigurationCheckingSynchronizer());
+ }
+ });
+
+ export = synchronizationManager.exportAllSubsystems(freshUser());
+
+ //and import it back again, so that we actually invoke the import validation
+ synchronizationManager.importAllSubsystems(freshUser(), export.getExportFile(), null);
+
+ assertTrue(ImportConfigurationCheckingSynchronizer.importerConfigured);
+ assertTrue(ImportConfigurationCheckingSynchronizer.importValidatorsObtainedAfterConfiguration);
+ } finally {
+ //reset the factory so that other tests work w/ the default syncers
+ synchronizationManager.setSynchronizerFactory(new SynchronizerFactory());
+ tearDown();
+ }
+ }
+
+ private String getExportData() throws IOException {
+ InputStreamReader str = new InputStreamReader(new GZIPInputStream(new ByteArrayInputStream(
+ export.getExportFile())), "UTF-8");
+ try {
+ char[] buf = new char[32768];
+ StringBuilder bld = new StringBuilder();
+
+ int cnt = 0;
+ while ((cnt = str.read(buf)) >= 0) {
+ bld.append(buf, 0, cnt);
+ }
+
+ return bld.toString();
+ } finally {
+ str.close();
+ }
+ }
+
+ private static String documentToString(Document document) throws TransformerFactoryConfigurationError,
+ TransformerException, IOException {
+
+ StringWriter ret = new StringWriter();
+ try {
+ Source source = new DOMSource(document);
+ Result result = new StreamResult(ret);
+
+ Transformer xformer = TransformerFactory.newInstance().newTransformer();
+ xformer.transform(source, result);
+
+ return ret.toString();
+ } finally {
+ ret.close();
+ }
+ }
+
+ private String updateSystemSettingsImportConfiguration(String exportXML) throws Exception {
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ xpath.setNamespaceContext(SynchronizationConstants.createConfigurationExportNamespaceContext());
+
+ XPathExpression systemSettingsConfigurationPath = xpath
+ .compile("/:configuration-export/:entities[@id='org.rhq.enterprise.server.sync.SystemSettingsSynchronizer']/:default-configuration/ci:simple-property[@name='propertiesToImport']");
+
+ XPathExpression baseUrlSettingPath = xpath
+ .compile("/:configuration-export/:entities[@id='org.rhq.enterprise.server.sync.SystemSettingsSynchronizer']/:entity/:data/systemSettings/entry[@key='CAM_BASE_URL']");
+
+ Element systemSettingsConfiguration = (Element) systemSettingsConfigurationPath.evaluate(new InputSource(
+ new StringReader(exportXML)), XPathConstants.NODE);
+ String propsToImport = systemSettingsConfiguration.getAttribute("value");
+
+ propsToImport += ", CAM_BASE_URL";
+
+ systemSettingsConfiguration.setAttribute("value", propsToImport);
+
+ exportXML = documentToString(systemSettingsConfiguration.getOwnerDocument());
+
+ Element baseUrlSetting = (Element) baseUrlSettingPath.evaluate(new InputSource(new StringReader(exportXML)),
+ XPathConstants.NODE);
+
+ baseUrlSetting.setTextContent("http://testing.domain:7080");
+
+ return documentToString(baseUrlSetting.getOwnerDocument());
+ }
+
+ private String updateMetricTemplatesImportConfiguration(String exportXML) throws Exception {
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ xpath.setNamespaceContext(SynchronizationConstants.createConfigurationExportNamespaceContext());
+
+ XPathExpression overridesPath = xpath
+ .compile("/:configuration-export/:entities[@id='org.rhq.enterprise.server.sync.MetricTemplateSynchronizer']/:default-configuration/ci:list-property[@name='metricUpdateOverrides']");
+
+ Element overrides = (Element) overridesPath.evaluate(new InputSource(new StringReader(exportXML)),
+ XPathConstants.NODE);
+
+ Document doc = overrides.getOwnerDocument();
+
+ String ns = SynchronizationConstants.CONFIGURATION_INSTANCE_NAMESPACE;
+ String prefix = SynchronizationConstants.CONFIGURATION_INSTANCE_NAMESPACE_PREFIX;
+
+ Element values = doc.createElementNS(ns, prefix + ":values");
+ overrides.appendChild(values);
+
+ Element mapValue = doc.createElementNS(ns, prefix + ":map-value");
+ values.appendChild(mapValue);
+
+ addSimpleValue(mapValue, "metricName", METRIC_NAME);
+ addSimpleValue(mapValue, "resourceTypeName", RESOURCE_TYPE_NAME);
+ addSimpleValue(mapValue, "resourceTypePlugin", PLUGIN_NAME);
+ addSimpleValue(mapValue, "updateSchedules", "true");
+
+ exportXML = documentToString(doc);
+
+ //now redefine the collection interval of the above metric so that we can see the change after the import
+ XPathExpression distroNameMetricPath = xpath
+ .compile("/:configuration-export/:entities[@id='org.rhq.enterprise.server.sync.MetricTemplateSynchronizer']/:entity/:data/metricTemplate[@metricName='"
+ + METRIC_NAME + "']");
+
+ Element metric = (Element) distroNameMetricPath.evaluate(new InputSource(new StringReader(exportXML)),
+ XPathConstants.NODE);
+
+ doc = metric.getOwnerDocument();
+
+ metric.setAttribute("defaultInterval", "30000");
+
+ return documentToString(doc);
+ }
+
+ private static void addSimpleValue(Element parent, String propertyName, String value) {
+ String ns = SynchronizationConstants.CONFIGURATION_INSTANCE_NAMESPACE;
+ String prefix = SynchronizationConstants.CONFIGURATION_INSTANCE_NAMESPACE_PREFIX;
+ Element simpleValue = parent.getOwnerDocument().createElementNS(ns, prefix + ":simple-value");
+ simpleValue.setAttribute("property-name", propertyName);
+ simpleValue.setAttribute("value", value);
+
+ parent.appendChild(simpleValue);
+ }
+
+ private Subject freshUser() {
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+
+ if (user != null) {
+ try {
+ subjectManager.logout(user);
+ } catch (PermissionException e) {
+ //we can safely ignore a permission exception during logout...
+ }
+ }
+
+ user = subjectManager.getOverlord();
+ return user;
+ }
+
+ private InputStream createCompressedStream(String exportData) throws UnsupportedEncodingException, IOException {
+ ByteArrayOutputStream compressed = new ByteArrayOutputStream();
+ OutputStreamWriter wrt = new OutputStreamWriter(new GZIPOutputStream(compressed), "UTF-8");
+ try {
+ wrt.write(exportData);
+ } finally {
+ wrt.close();
+ }
+
+ return new ByteArrayInputStream(compressed.toByteArray());
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsExporterTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsExporterTest.java
new file mode 100644
index 0000000..2837982
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsExporterTest.java
@@ -0,0 +1,166 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.sync.test;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jmock.Expectations;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.sync.ExporterMessages;
+import org.rhq.core.domain.sync.entity.SystemSettings;
+import org.rhq.enterprise.server.sync.ExportingInputStream;
+import org.rhq.enterprise.server.sync.SynchronizationConstants;
+import org.rhq.enterprise.server.sync.Synchronizer;
+import org.rhq.enterprise.server.sync.SystemSettingsSynchronizer;
+import org.rhq.enterprise.server.system.SystemManagerLocal;
+import org.rhq.test.JMockTest;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+@Test
+public class SystemSettingsExporterTest extends JMockTest {
+
+ private static final Log LOG = LogFactory.getLog(MetricTemplateExporterTest.class);
+
+ public void testCanExport() throws Exception {
+ final SystemManagerLocal systemManager = context.mock(SystemManagerLocal.class);
+
+ context.checking(new Expectations() {
+ {
+ allowing(systemManager).getSystemConfiguration(with(any(Subject.class)));
+ will(returnValue(getFakeSystemConfiguration()));
+ }
+ });
+
+ SystemSettingsSynchronizer exporter = new SystemSettingsSynchronizer(systemManager);
+
+ Set<Synchronizer<?, ?>> exporters = new HashSet<Synchronizer<?, ?>>();
+ exporters.add(exporter);
+
+ InputStream eis = new ExportingInputStream(exporters, new HashMap<String, ExporterMessages>(), 65536, false);
+
+// String exportContents = readAll(new InputStreamReader(eis, "UTF-8"));
+//
+// LOG.warn("Export contents:\n" + exportContents);
+//
+// eis = new ByteArrayInputStream(exportContents.getBytes("UTF-8"));
+
+// <?xml version="1.0" ?>
+// <configuration-export>
+// <entities id="org.rhq.enterprise.server.sync.importers.SystemSettingsImporter">
+// <entity>
+// <data>
+// <systemSettings referencedEntityId="0">
+// <entry key="BaseUrl">herethereandeverywhere</entry>
+// </systemSettings>
+// </data>
+// </entity>
+// </entities>
+// </configuration-export>
+ DocumentBuilder bld = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+
+ Document doc = bld.parse(eis);
+
+ Element root = doc.getDocumentElement();
+
+ Element entities = (Element) getFirstDirectChildByTagName(root, SynchronizationConstants.ENTITIES_EXPORT_ELEMENT);
+
+ assertEquals(entities.getAttribute(SynchronizationConstants.ID_ATTRIBUTE), SystemSettingsSynchronizer.class.getName(),
+ "Unexpected id of the entities element.");
+
+ NodeList systemSettings = entities.getElementsByTagName("systemSettings");
+
+ assertEquals(systemSettings.getLength(), 1, "Unexpected number of exported system settings.");
+
+ for (int i = 0; i < systemSettings.getLength(); ++i) {
+ Element m = (Element) systemSettings.item(i);
+
+ assertEquals(m.getAttribute("referencedEntityId"), "0", "Unexpected referencedEntityId value");
+
+ NodeList entries = m.getElementsByTagName("entry");
+
+ assertEquals(entries.getLength(), 1, "Unexpected number of entry elements in the system settings export.");
+
+ Element baseURL = (Element) entries.item(0);
+
+ assertEquals(baseURL.getAttribute("key"), "BaseURL");
+ assertEquals(baseURL.getTextContent(), "herethereandeverywhere", "Unexpected value of baseURL");
+ }
+ }
+
+ private static String readAll(Reader rdr) throws IOException {
+ try {
+ StringBuilder bld = new StringBuilder();
+ int c;
+ while ((c = rdr.read()) != -1) {
+ bld.append((char) c);
+ }
+
+ return bld.toString();
+ } finally {
+ rdr.close();
+ }
+ }
+
+ private static Node getFirstDirectChildByTagName(Node node, String tagName) {
+ for (int i = 0; i < node.getChildNodes().getLength(); ++i) {
+ Node n = node.getChildNodes().item(i);
+ if (n.getNodeName().equals(tagName)) {
+ return n;
+ }
+ }
+
+ return null;
+ }
+
+ private static Properties getFakeSystemConfiguration() {
+ HashMap<String, String> values = new HashMap<String, String>();
+ values.put("BaseURL", "herethereandeverywhere");
+ SystemSettings settings = new SystemSettings(values);
+
+ return settings.toProperties();
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsImporterTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsImporterTest.java
new file mode 100644
index 0000000..7935e5f
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsImporterTest.java
@@ -0,0 +1,119 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.sync.test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Properties;
+
+import org.jmock.Expectations;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.sync.entity.SystemSettings;
+import org.rhq.core.util.StringUtil;
+import org.rhq.enterprise.server.sync.importers.SystemSettingsImporter;
+import org.rhq.enterprise.server.system.SystemManagerLocal;
+import org.rhq.test.JMockTest;
+
+/**
+ * @author Lukas Krejci
+ */
+@Test
+public class SystemSettingsImporterTest extends JMockTest {
+
+ public void testNullConfigurationUnderstoodAsDefault() throws Exception {
+ final SystemManagerLocal systemManager = context.mock(SystemManagerLocal.class);
+
+ SystemSettingsImporter importer = new SystemSettingsImporter(null, systemManager);
+
+ final HashMap<String, String> settings = new HashMap<String, String>();
+ settings.put("CAM_BASE_URL", "url");
+ settings.put("SOME_UNKNOWN_PROPERTY", "asdf");
+ String[] importableProps = SystemSettingsImporter.DEFAULT_IMPORTED_PROPERTIES_LIST.split("\\s*,\\s*");
+ for (String p : importableProps) {
+ settings.put(p, "value");
+ }
+ final SystemSettings importedSettings = new SystemSettings(settings);
+
+ context.checking(new Expectations() {
+ {
+ Properties expectedImport = new Properties();
+ expectedImport.putAll(settings);
+ //base url is not imported by default
+ expectedImport.remove("CAM_BASE_URL");
+ expectedImport.remove("SOME_UNKNOWN_PROPERTY");
+
+ oneOf(systemManager).setSystemConfiguration(with(any(Subject.class)), with(expectedImport), with(true));
+ }
+ });
+
+ importer.configure(null);
+
+ importer.update(null, importedSettings);
+
+ importer.finishImport();
+ }
+
+ public void testImportConfigurationHonored() throws Exception {
+ final SystemManagerLocal systemManager = context.mock(SystemManagerLocal.class);
+
+ SystemSettingsImporter importer = new SystemSettingsImporter(null, systemManager);
+
+ String[] importableProps = SystemSettingsImporter.DEFAULT_IMPORTED_PROPERTIES_LIST.split("\\s*,\\s*");
+
+ final HashMap<String, String> settings = new HashMap<String, String>();
+ for (String p : importableProps) {
+ settings.put(p, "value");
+ }
+ final SystemSettings importedSettings = new SystemSettings(settings);
+
+ final List<String> allowedSettings = new ArrayList<String>();
+ for (int i = 0; i < importableProps.length; ++i) {
+ if (i % 2 == 0) {
+ allowedSettings.add(importableProps[i]);
+ }
+ }
+
+ context.checking(new Expectations() {
+ {
+ Properties expectedImport = new Properties();
+ for (String s : allowedSettings) {
+ expectedImport.put(s, settings.get(s));
+ }
+
+ oneOf(systemManager).setSystemConfiguration(with(any(Subject.class)), with(expectedImport), with(true));
+ }
+ });
+
+ Configuration importConfig = new Configuration();
+ importConfig.put(new PropertySimple(SystemSettingsImporter.PROPERTIES_TO_IMPORT_PROPERTY, StringUtil
+ .collectionToString(allowedSettings, ", ")));
+
+ importer.configure(importConfig);
+
+ importer.update(null, importedSettings);
+
+ importer.finishImport();
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsValidatorTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsValidatorTest.java
new file mode 100644
index 0000000..0966080
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/SystemSettingsValidatorTest.java
@@ -0,0 +1,59 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.sync.test;
+
+import java.util.Properties;
+
+import org.jmock.Expectations;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.sync.entity.SystemSettings;
+import org.rhq.enterprise.server.sync.validators.SystemSettingsValidator;
+import org.rhq.enterprise.server.system.SystemManagerLocal;
+import org.rhq.test.JMockTest;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+@Test
+public class SystemSettingsValidatorTest extends JMockTest {
+
+ public void testValidatorCallsSystemManager() {
+ final SystemManagerLocal systemManager = context.mock(SystemManagerLocal.class);
+
+ SystemSettingsValidator validator = new SystemSettingsValidator(systemManager);
+
+ final Properties settings = new Properties();
+ settings.put("A", "a");
+ settings.put("B", "b");
+ SystemSettings importedSettings = new SystemSettings(settings);
+
+ context.checking(new Expectations() {
+ {
+ oneOf(systemManager).validateSystemConfiguration(with(any(Subject.class)), with(settings));
+ }
+ });
+
+ validator.validateExportedEntity(importedSettings);
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/UniquenessValidatorTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/UniquenessValidatorTest.java
new file mode 100644
index 0000000..33a0207
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/sync/test/UniquenessValidatorTest.java
@@ -0,0 +1,51 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.sync.test;
+
+import static org.testng.Assert.fail;
+
+import org.testng.annotations.Test;
+
+import org.rhq.enterprise.server.sync.ValidationException;
+import org.rhq.enterprise.server.sync.validators.UniquenessValidator;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+@Test
+public class UniquenessValidatorTest {
+
+ public void testDetectsDuplicitEntries() throws Exception {
+ UniquenessValidator<String> validator = new UniquenessValidator<String>();
+
+ validator.initialize(null, null);
+
+ validator.validateExportedEntity("1");
+ validator.validateExportedEntity("2");
+ try {
+ validator.validateExportedEntity("1");
+ fail("Uniqueness validator should have detected a duplicate entry.");
+ } catch (ValidationException e) {
+ //expected
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/system/SystemManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/system/SystemManagerBeanTest.java
new file mode 100644
index 0000000..ede29a4
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/system/SystemManagerBeanTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.enterprise.server.system;
+
+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.db.DatabaseType;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.common.composite.SystemSetting;
+import org.rhq.core.domain.common.composite.SystemSettings;
+import org.rhq.enterprise.server.RHQConstants;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestServerPluginService;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+@Test
+public class SystemManagerBeanTest extends AbstractEJB3Test {
+ private Subject overlord;
+ private SystemManagerLocal systemManager;
+ private TestServerPluginService testServerPluginService;
+
+ @BeforeClass
+ public void setupServer() {
+ systemManager = LookupUtil.getSystemManager();
+ }
+
+ @BeforeMethod
+ public void beforeMethod() {
+ // do this each method so it doesn't expire
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ //we need this because the drift plugins are referenced from the system settings that we use in our tests
+ testServerPluginService = new TestServerPluginService();
+ prepareCustomServerPluginService(testServerPluginService);
+ testServerPluginService.startMasterPluginContainer();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDownServer() throws Exception {
+ unprepareServerPluginService();
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testGetSystemConfiguration() {
+ assert null != systemManager.getSystemConfiguration(overlord);
+ }
+
+ public void testAnalyze() {
+ systemManager.analyze(overlord);
+ }
+
+ public void testEnableHibernateStatistics() {
+ systemManager.enableHibernateStatistics();
+ }
+
+ public void testGetDatabaseType() {
+ assert systemManager.getDatabaseType() instanceof DatabaseType;
+ }
+
+ public void testReindex() {
+ systemManager.reindex(overlord);
+ }
+
+ public void testVacuum() {
+ systemManager.vacuum(overlord);
+ }
+
+ public void testVacuumAppdef() {
+ systemManager.vacuumAppdef(overlord);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testLegacySystemSettingsInCorrectFormat() throws Exception {
+ //some of the properties are represented differently
+ //in the new style settings and the the old style
+ //settings (and consequently database).
+ //These two still co-exist together in the codebase
+ //so let's make sure the values correspond to each other.
+
+ SystemSettings settings = systemManager.getSystemSettings(overlord);
+ Properties config = systemManager.getSystemConfiguration(overlord);
+
+ SystemSettings origSettings = new SystemSettings(settings);
+
+ try {
+ //let's make sure the values are the same
+ checkFormats(settings, config);
+
+ boolean currentJaasProvider = Boolean.valueOf(settings.get(SystemSetting.LDAP_BASED_JAAS_PROVIDER));
+ settings.put(SystemSetting.LDAP_BASED_JAAS_PROVIDER, Boolean.toString(!currentJaasProvider));
+
+ boolean currentUseSslForLdap = Boolean.valueOf(settings.get(SystemSetting.USE_SSL_FOR_LDAP));
+ settings.put(SystemSetting.USE_SSL_FOR_LDAP, Boolean.toString(!currentUseSslForLdap));
+
+ systemManager.setSystemSettings(overlord, settings);
+
+ settings = systemManager.getSystemSettings(overlord);
+ config = systemManager.getSystemConfiguration(overlord);
+
+ checkFormats(settings, config);
+ } finally {
+ systemManager.setSystemSettings(overlord, origSettings);
+ }
+ }
+
+ private void checkFormats(SystemSettings settings, Properties config) {
+ assert settings.size() == config.size() : "The old and new style system settings differ in size";
+
+ for (String name : config.stringPropertyNames()) {
+ SystemSetting setting = SystemSetting.getByInternalName(name);
+
+ String oldStyleValue = config.getProperty(name);
+ String newStyleValue = settings.get(setting);
+
+ assert setting != null : "Could not find a system setting called '" + name + "'.";
+
+ switch (setting) {
+ case USE_SSL_FOR_LDAP:
+ if (RHQConstants.LDAP_PROTOCOL_SECURED.equals(oldStyleValue)) {
+ assert Boolean.valueOf(newStyleValue) : "Secured LDAP protocol should be represented by a 'true' in new style settings.";
+ } else if (RHQConstants.LDAP_PROTOCOL_UNSECURED.equals(oldStyleValue)) {
+ assert !Boolean.valueOf(newStyleValue) : "Unsecured LDAP protocol should be represented by a 'false' in the new style settings.";
+ } else {
+ assert false : "Unknown value for system setting '" + setting + "': [" + oldStyleValue + "].";
+ }
+ break;
+ case LDAP_BASED_JAAS_PROVIDER:
+ if (RHQConstants.LDAPJAASProvider.equals(oldStyleValue)) {
+ assert Boolean.valueOf(newStyleValue) : "LDAP JAAS provider should be represented by a 'true' in new style settings.";
+ } else if (RHQConstants.JDBCJAASProvider.equals(oldStyleValue)) {
+ assert !Boolean.valueOf(newStyleValue) : "JDBC JAAS provider should be represented by a 'false' in the new style settings.";
+ } else {
+ assert false : "Unknown value for system setting '" + setting + "': [" + oldStyleValue + "].";
+ }
+ break;
+ default:
+ assert oldStyleValue != null && newStyleValue != null && oldStyleValue.equals(newStyleValue) : "Old and new style values unexpectedly differ for system setting '"
+ + setting + "': old=[" + oldStyleValue + "], new=[" + newStyleValue + "].";
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3PerformanceTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3PerformanceTest.java
new file mode 100644
index 0000000..161316d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3PerformanceTest.java
@@ -0,0 +1,199 @@
+/*
+ * 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.test;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.rhq.helpers.perftest.support.reporting.PerformanceReportExporter;
+import org.rhq.helpers.perftest.support.testng.PerformanceReporting;
+import org.testng.ITestResult;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+import javax.persistence.EntityManager;
+import java.lang.reflect.Method;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * Helper that introduces timing functionality on top of the Abstract EJB tests.
+ *
+ * @author Heiko W. Rupp
+ */
+public class AbstractEJB3PerformanceTest extends AbstractEJB3Test {
+
+ private static final Log log = LogFactory.getLog("TIMING_INFO");
+
+
+ private static final String DEFAULT = "-default-";
+ private Map<String,Long> timings ;
+ private Map<String,Long> startTime ;
+
+
+ protected void startTiming(String name) {
+
+ if (startTime==null) {
+ System.err.println("startTime is null, setupTimings was not called by TestNG!!");
+ return;
+ }
+
+ long now = System.currentTimeMillis();
+ startTime.put(name,now);
+
+ }
+
+ protected void endTiming(String name) {
+
+ boolean found = startTime.containsKey(name);
+ assert found : "No start time information for name [" + name + "] found - did you call startTiming()?";
+
+
+ long now = System.currentTimeMillis();
+ long start = startTime.get(name);
+ long duration = (now - start);
+ if (timings.containsKey(name)) {
+ long timing = timings.get(name);
+ timing+=duration;
+ timings.put(name,timing);
+ }
+ else {
+ timings.put(name,duration);
+ }
+ }
+
+ protected void startTiming() {
+ startTiming(DEFAULT);
+ }
+
+ protected void endTiming() {
+ endTiming(DEFAULT);
+ }
+
+ protected long getTiming(String name) {
+ if (timings.containsKey(name)) {
+ return timings.get(name);
+ }
+ else
+ return -1;
+ }
+
+ protected long getTiming() {
+ return getTiming(DEFAULT);
+ }
+
+ @AfterMethod
+ protected void reportTimings(ITestResult result, Method meth) {
+
+ printTimings(meth.getName());
+
+ Class clazz = meth.getDeclaringClass();
+ PerformanceReporting pr = (PerformanceReporting) clazz.getAnnotation(PerformanceReporting.class);
+ if (pr != null) {
+ String file = pr.baseFilename();
+ Class<? extends PerformanceReportExporter> exporterClazz = pr.exporter();
+ try {
+ PerformanceReportExporter exporter = exporterClazz.newInstance();
+ exporter.setBaseFile(file);
+ exporter.setRolling(pr.rolling());
+ exporter.export(timings,result);
+ }
+ catch (Throwable e) {
+ System.err.println("Error writing to reporting file " + file +" : " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ }
+
+ System.out.flush();
+ System.err.flush();
+
+ timings.clear();
+ startTime.clear();
+
+ }
+
+// @BeforeMethod
+ protected void setupTimings(Method meth) {
+ timings = new HashMap<String, Long>();
+ startTime = new HashMap<String, Long>();
+
+ }
+
+
+
+ protected void printTimings(String testName) {
+ System.out.println("=== " + testName + " ===");
+ Set<Map.Entry<String,Long>> data = timings.entrySet();
+ SortedSet <Map.Entry<String,Long>> sorted = new TreeSet<Map.Entry<String,Long>>(new Comparator<Map.Entry<String,Long>>() {
+
+ public int compare(Map.Entry<String,Long> item1, Map.Entry<String,Long> item2) {
+
+ return item1.getKey().compareTo(item2.getKey());
+ }
+ });
+ sorted.addAll(data);
+ long summaryTime = 0L;
+ for (Map.Entry<String,Long> item : sorted) {
+ log.info(":| " + item.getKey() + " => " + item.getValue());
+ System.out.println(":| " + item.getKey() + " => " + item.getValue());
+ summaryTime += item.getValue();
+ }
+ System.out.println("Total: " + summaryTime + " ms");
+ }
+
+ protected void assertTiming(String name, long maxDuration) {
+
+ boolean found = timings.containsKey(name);
+ assert found : "No timing information for name [" + name + "] found";
+
+ long duration = timings.get(name);
+
+ assert duration < maxDuration : "Execution took longer than given max ( " + duration + " > " + maxDuration + ")";
+
+ }
+
+ protected void assertTiming(long maxDuration) {
+ assertTiming(DEFAULT,maxDuration);
+ }
+
+ /**
+ * Make sure the passed value is within a band of <code>[0.80* x, 1.2*x]</code> with
+ * <code>x = ( ref * multiplier )</code>.
+ * @param ref base value to calculate the reference from
+ * @param value value to compare to the band
+ * @param multiplier multiplier for the base value of the band.
+ * @param text text to prepend to a line if check fails.
+ */
+ protected void assertLinear(long ref,long value, double multiplier, String text ) {
+
+System.out.println(">>> assertLinear " + text + " " + ref + ", " + value + ", " + multiplier );
+ long low = (long) (ref * multiplier * 0.80);
+ long hi = (long) (ref * multiplier * 1.2);
+
+ // comment out the low check for now TODO reenable when we know more
+// assert value >= low : text + " [low] Val2 (" + value + ") is not > " + low;
+// assert value <= hi : text + " [hi] Val2 (" + value + ") is not < " + hi;
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
new file mode 100644
index 0000000..1167807
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
@@ -0,0 +1,741 @@
+package org.rhq.enterprise.server.test;
+
+import java.io.File;
+import java.lang.management.ManagementFactory;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.regex.Pattern;
+
+import javax.management.MBeanServer;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.PersistenceContext;
+import javax.transaction.TransactionManager;
+
+import org.testng.AssertJUnit;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.arquillian.testng.Arquillian;
+import org.jboss.shrinkwrap.api.ArchivePaths;
+import org.jboss.shrinkwrap.api.Filters;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+import org.jboss.shrinkwrap.api.spec.EnterpriseArchive;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.impl.base.exporter.zip.ZipExporterImpl;
+import org.jboss.shrinkwrap.resolver.api.DependencyResolvers;
+import org.jboss.shrinkwrap.resolver.api.maven.MavenDependencyResolver;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.core.util.exception.ThrowableUtil;
+import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.RHQConstants;
+import org.rhq.enterprise.server.auth.SessionManager;
+import org.rhq.enterprise.server.core.plugin.PluginDeploymentScanner;
+import org.rhq.enterprise.server.core.plugin.PluginDeploymentScannerMBean;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+import org.rhq.enterprise.server.scheduler.SchedulerService;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.test.AssertUtils;
+import org.rhq.test.MatchResult;
+import org.rhq.test.PropertyMatchException;
+import org.rhq.test.PropertyMatcher;
+
+public abstract class AbstractEJB3Test extends Arquillian {
+
+ protected static final String JNDI_RHQDS = "java:jboss/datasources/RHQDS";
+
+ private SchedulerService schedulerService;
+ private ServerPluginService serverPluginService;
+ private MBeanServer dummyJBossMBeanServer;
+ private PluginDeploymentScannerMBean pluginScannerService;
+
+ @PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
+ protected EntityManager em;
+
+ @ArquillianResource
+ protected InitialContext initialContext;
+
+ // We originally deployed the jar as a JavaArchive (JAR file). But this ran into problems because
+ // of the dependent 3rd party jars. There isn't an obvious way to deploy the dependent jars of a jar.
+ // Also, AS7 makes it hard to put them in a globally accessibly /lib directory due to
+ // its classloader isolation and module approach. So, we now deploy an EnterpriseArchive (ear)
+ // where the ejb jar is deployed as a module and the 3rd party libraries are put in the ear's /lib.
+
+ @Deployment
+ protected static EnterpriseArchive getBaseDeployment() {
+
+ // depending on the db in use, set up the necessary datasource
+ String dialect = System.getProperty("hibernate.dialect");
+ if (dialect == null) {
+ System.out.println("!!! hibernate.dialect is not set! Assuming you want to test on postgres");
+ dialect = "postgres";
+ }
+
+ String dataSourceXml;
+ if (dialect.toLowerCase().contains("postgres")) {
+ dataSourceXml = "jbossas-postgres-ds.xml";
+ } else {
+ dataSourceXml = "jbossas-oracle-ds.xml";
+ }
+
+ MavenDependencyResolver jarResolver = DependencyResolvers.use(MavenDependencyResolver.class);
+ //resolver.loadMetadataFromPom("pom.xml");
+
+ // Create the ejb jar which will subsequently be packaged in the ear deployment
+ // JavaArchive serverJar = ShrinkWrap.create(JavaArchive.class, "rhq-enterprise-server-ejb3.jar") //
+ // .addAsManifestResource(dataSourceXml) // the datasource
+ // .addAsManifestResource("ejb-jar.xml") // the empty ejb jar descriptor
+ // .addAsManifestResource("test-persistence.xml", "persistence.xml") // the test persistence context
+ // .addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml") // add CDI injection (needed by arquillian injection)
+ // );
+
+ // server jar classes
+ // serverJar = addClasses(serverJar, new File("../jar/target/classes/org"), null);
+ // JavaArchive serverJar = ShrinkWrap.create(JavaArchive.class, "rhq-enterprise-server-ejb3.jar");
+ // JavaArchive artifact = jarResolver.artifact("org.rhq:rhq-enterprise-server:4.6.0-SNAPSHOT")
+ // .resolveAs(JavaArchive.class).iterator().next();
+ // serverJar.merge(artifact, Filters.exclude(".*META-INF.*"));
+ // serverJar.addAsManifestResource(dataSourceXml) // the datasource
+ // .addAsManifestResource("ejb-jar.xml") // the empty ejb jar descriptor
+ // .addAsManifestResource("test-persistence.xml", "persistence.xml") // the test persistence context
+ // .addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml")); // add CDI injection (needed by arquillian injection)
+
+ // System.out.println("** The Deployment EJB JAR: " + serverJar.toString(true) + "\n");
+
+ JavaArchive testClassesJar = ShrinkWrap.create(JavaArchive.class, "test-classes.jar");
+ testClassesJar = addClasses(testClassesJar, new File("target/test-classes/org"), null);
+
+ // non itests-2 RHQ classes in use by test classes
+ testClassesJar.addClass(ThrowableUtil.class);
+ testClassesJar.addClass(MessageDigestGenerator.class);
+ testClassesJar.addClass(StreamUtil.class);
+ testClassesJar.addClass(AssertUtils.class);
+ testClassesJar.addClasses(PropertyMatcher.class, MatchResult.class, PropertyMatchException.class);
+ testClassesJar.addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml")); // add CDI injection (needed by arquillian injection);
+ testClassesJar.addAsResource("test-scheduler.properties");
+
+ // create test ear
+ MavenDependencyResolver earResolver = DependencyResolvers.use(MavenDependencyResolver.class);
+ // this must be named rhq.ear because the "rhq" portion is used in the jndi names
+ EnterpriseArchive ear = ShrinkWrap.create(EnterpriseArchive.class, "rhq.ear");
+ EnterpriseArchive ear2 = earResolver.artifact("org.rhq:rhq-enterprise-server-ear:ear:4.6.0-SNAPSHOT")
+ .resolveAs(EnterpriseArchive.class).iterator().next();
+ //ear = ear.merge(ear2, Filters.exclude(".*\\.war.*|.*application.xml.*|.*rhq-enterprise-server-ejb3.*"));
+ ear = ear.merge(ear2, Filters.include("/lib.*|/rhq.*ejb3\\.jar.*|/rhq-enterprise-server-services-sar.*"));
+
+ // ear.addAsModule((resolver.artifact("org.rhq:rhq-enterprise-server:4.6.0-SNAPSHOT").resolveAsFiles())[0],
+ // "rhq-core-enterprise-server-ejb3.jar");
+ // ear.addAsModule((resolver.artifact("org.rhq:rhq-core-domain:4.6.0-SNAPSHOT").resolveAsFiles())[0],
+ // "rhq-core-domain-ejb3.jar");
+ //ear.getAsType(JavaArchive.class, "rhq-enterprise-server-ejb3.jar")
+ //ear = ear.addAsModule(serverJar); // the jar under test
+ ear = ear.addAsLibrary(testClassesJar); // the actual test classes
+ ear = ear.addAsManifestResource("jboss-deployment-structure.xml");
+ ear = ear.setApplicationXML("application.xml"); // the application xml declaring the ejb jar
+ //ear = ear.addAsLibrary("persistence.jar");
+
+ //System.out.println("** The Deployment EAR: " + ear.toString(true) + "\n");
+
+ //ear.delete("rhq-portal.war");
+ //ear.delete("coregui.war");
+
+ // ear.merge(resolver.artifact("org.rhq:rhq-enterprise-server-ear:4.6.0-SNAPSHOT")
+ // .resolveAs(EnterpriseArchive.class).iterator().next());
+ // .addAsModule(ejbJar) // the jar under test
+ // .addAsLibrary(testClassesJar) // the actual test classes
+ // .setApplicationXML("application.xml"); // the application xml declaring the ejb jar
+
+ // Adding the 3rd party jars is not easy. There were basically two approaches I could think of:
+ //
+ // 1) Use the MavenDependencyResolver to figure out and add all of the test deps and put them in lib
+ //
+ // This immediately ran into trouble as there were way more jars sucked in than were actually necessary.
+ // Furthermore, it included arquillian, shrinkwrap, jboss, etc.. lots of jars that actually caused
+ // issues like locking and other horrible things due, I suppose, to just stepping all over the test env
+ // set up by Arquillian. So, the next step was to try and start excluding the unwanted jars. This was
+ // tedious and difficult and I didn't really get it close to working before giving up and going with
+ // option 2.
+ //
+ // 2) Use the MavenDependencyResolver to locate and pull just the artifacts we need.
+ //
+ // This is annoying because it's basically duplicating the same sort of effort that we already
+ // use maven to do for us. It involves running, failing on NoClassDefFound, fixing it, repeat. It
+ // does pull in necessary transitive deps but sometimes it pulls in unwanted transitive deps. So,
+ // we still end up having to do some exclusion filtering. Since Shrinkwrap has weak and buggy
+ // filtering, we have some homegrown filtering methods below.
+ // TODO: Is there any way to not have to specify the versions for the transitive deps? This is brittle as is.
+
+ //load 3rd party deps explicitly
+ MavenDependencyResolver resolver = DependencyResolvers.use(MavenDependencyResolver.class);
+ resolver.loadMetadataFromPom("pom.xml");
+ Collection<JavaArchive> dependencies = new HashSet<JavaArchive>();
+ dependencies.addAll(resolver.artifact("org.powermock:powermock-api-mockito").resolveAs(JavaArchive.class));
+ dependencies.addAll(resolver.artifact("org.liquibase:liquibase-core").resolveAs(JavaArchive.class));
+ dependencies.addAll(resolver.artifact("org.rhq:test-utils").resolveAs(JavaArchive.class));
+ dependencies.addAll(resolver.artifact("org.rhq.helpers:perftest-support").resolveAs(JavaArchive.class));
+ //dependencies.addAll(resolver.artifact("commons-io:commons-io").resolveAs(JavaArchive.class));
+ //dependencies.addAll(resolver.artifact("org.unitils:unitils-testng:3.1").resolveAs(JavaArchive.class));
+
+ //dependencies.addAll(resolver.artifact("org.rhq:rhq-core-domain").resolveAs(JavaArchive.class));
+ String[] excludeFilters = { "testng.*jdk", "rhq-core-domain.*jar" };
+ //
+ dependencies = exclude(dependencies, excludeFilters);
+ ear = ear.addAsLibraries(dependencies);
+ // ear.addAsModule((resolver.artifact("org.rhq:rhq-core-domain").resolveAsFiles())[0], "rhq-core-domain-ejb3.jar");
+
+ //System.out.println("** The Deployment EAR: " + ear.toString(true) + "\n");
+
+ try {
+ ZipExporter exporter = new ZipExporterImpl(ear);
+ exporter.exportTo(new File("/home/jshaughn/temp/test-ear.ear"), true);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return ear;
+ }
+
+ /**
+ * @param dependencies The current set of deps - THIS IS FILTERED, not copied
+ * @param filters regex filters
+ * @return the filtered set of deps
+ */
+ public static Collection<JavaArchive> exclude(Collection<JavaArchive> dependencies, String... filters) {
+
+ for (String filter : filters) {
+ Pattern p = Pattern.compile(filter);
+
+ for (Iterator<JavaArchive> i = dependencies.iterator(); i.hasNext();) {
+ JavaArchive dependency = i.next();
+ if (p.matcher(dependency.getName()).find()) {
+ i.remove();
+ }
+ }
+ }
+
+ return dependencies;
+ }
+
+ /**
+ * @param dependencies The current set of deps - this is not changed
+ * @param filters regex filters
+ * @return set set of JavaArchives in dependencies that matched an include filter
+ */
+ public static Collection<JavaArchive> include(Collection<JavaArchive> dependencies, String... filters) {
+
+ Collection<JavaArchive> result = new HashSet<JavaArchive>();
+
+ for (String filter : filters) {
+ Pattern p = Pattern.compile(filter);
+
+ for (Iterator<JavaArchive> i = dependencies.iterator(); i.hasNext();) {
+ JavaArchive dependency = i.next();
+ if (p.matcher(dependency.getName()).find()) {
+ result.add(dependency);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public static JavaArchive addClasses(JavaArchive archive, File dir, String packageName) {
+
+ packageName = (null == packageName) ? "" + dir.getName() : packageName + "." + dir.getName();
+
+ for (File file : dir.listFiles()) {
+ String fileName = file.getName();
+ if (file.isDirectory()) {
+ archive = addClasses(archive, file, packageName);
+ } else if (fileName.endsWith(".class")) {
+ int dot = fileName.indexOf('.');
+ try {
+ //Class<?> clazz = Class.forName(packageName + "." + fileName.substring(0, dot));
+ archive.addClass(packageName + "." + fileName.substring(0, dot));
+ } catch (Exception e) {
+ System.out.println("WARN: Could not add class:" + e);
+ }
+ }
+ }
+
+ return archive;
+ }
+
+ /**
+ * <p>DO NOT OVERRIDE.</p>
+ * <p>DO NOT DEFINE AN @BeforeMethod</p>
+ *
+ * Instead, override {@link #beforeMethod()}. If you must override, for example, if you
+ * need to use special attributes on your annotation, then ensure you protect the code with
+ * and {@link #inContainer()} call.
+ */
+ @BeforeMethod
+ protected void __beforeMethod() throws Throwable {
+ // Note that Arquillian calls the testng BeforeMethod twice (as of 1.0.2.Final, once
+ // out of container and once in container. In general the expectation is to execute it
+ // one time, and doing it in container allows for the expected injections and context.
+ if (inContainer()) {
+ try {
+ beforeMethod();
+ } catch (Throwable t) {
+ // Arquillian is eating these, make sure they show up in some way
+ System.out.println("BEFORE METHOD FAILURE, TEST DID NOT RUN!!! " + t.getMessage());
+ throw t;
+ }
+ }
+ }
+
+ /**
+ * <p>DO NOT OVERRIDE.</p>
+ * <p>DO NOT DEFINE AN @AfterMethod</p>
+ *
+ * Instead, override {@link #afterMethod()}.
+ */
+ @AfterMethod
+ protected void __afterMethod() throws Exception {
+ if (inContainer()) {
+ afterMethod();
+ }
+ }
+
+ protected boolean inContainer() {
+ // If the injection is done we're running in the container.
+ return (null != initialContext);
+ }
+
+ /**
+ * Override Point! Do not implement a @BeforeMethod, instead override this method.
+ */
+ protected void beforeMethod() throws Exception {
+ // do nothing if we're not overridden
+ }
+
+ /**
+ * Override Point! Do not implement an @AfterMethod, instead override this method.
+ */
+ protected void afterMethod() throws Exception {
+ // do nothing if we're not overridden
+ }
+
+ protected void startTransaction() throws Exception {
+ getTransactionManager().begin();
+ }
+
+ protected void commitTransaction() throws Exception {
+ getTransactionManager().commit();
+ }
+
+ protected void rollbackTransaction() throws Exception {
+ getTransactionManager().rollback();
+ }
+
+ protected InitialContext getInitialContext() {
+ // may be null if not yet injected (as of 1.0.1.Final, only injected inside @Test)
+ if (null != initialContext) {
+ return initialContext;
+ }
+
+ InitialContext result = null;
+
+ try {
+ Properties jndiProperties = new Properties();
+ jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.as.naming.InitialContextFactory");
+ result = new InitialContext(jndiProperties);
+
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to get InitialContext", e);
+ }
+
+ return result;
+ }
+
+ public TransactionManager getTransactionManager() {
+ TransactionManager result = null;
+
+ try {
+ result = (TransactionManager) getInitialContext().lookup("java:jboss/TransactionManager");
+ if (null == result) {
+ result = (TransactionManager) getInitialContext().lookup("TransactionManager");
+ }
+
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to get TransactionManager", e);
+ }
+
+ return result;
+ }
+
+ protected EntityManager getEntityManager() {
+ // may be null if not yet injected (as of 1.0.1.Final, only injected inside @Test)
+ if (null != em) {
+ return em;
+ }
+
+ EntityManager result = null;
+
+ try {
+ EntityManagerFactory emf = (EntityManagerFactory) getInitialContext().lookup(
+ "java:jboss/RHQEntityManagerFactory");
+ result = emf.createEntityManager();
+
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to get EntityManagerFactory", e);
+ }
+
+ return result;
+ }
+
+ /**
+ * Equivalent to <pre>executeInTransaction(true, callback)</pre>.
+ * @param callback
+ */
+ protected void executeInTransaction(TransactionCallback callback) {
+ executeInTransaction(true, callback);
+ }
+
+ protected void executeInTransaction(boolean rollback, final TransactionCallback callback) {
+ executeInTransaction(rollback, new TransactionCallbackReturnable<Void>() {
+
+ public Void execute() throws Exception {
+ callback.execute();
+ return null;
+ }
+ });
+ }
+
+ protected <T> T executeInTransaction(TransactionCallbackReturnable<T> callback) {
+ return executeInTransaction(true, callback);
+ }
+
+ protected <T> T executeInTransaction(boolean rollback, TransactionCallbackReturnable<T> callback) {
+ try {
+ startTransaction();
+ T result = callback.execute();
+ return result;
+
+ } catch (Throwable t) {
+ rollback = true;
+ RuntimeException re = new RuntimeException(ThrowableUtil.getAllMessages(t), t);
+ throw re;
+
+ } finally {
+ try {
+ if (!rollback) {
+ commitTransaction();
+ } else {
+ rollbackTransaction();
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to " + (rollback ? "rollback" : "commit") + " transaction", e);
+ }
+ }
+ }
+
+ /* The old AbstractEJB3Test impl extended AssertJUnit. Continue to support the used methods
+ * with various call-thru methods.
+ */
+
+ protected void assertNotNull(Object o) {
+ AssertJUnit.assertNotNull(o);
+ }
+
+ protected void assertNotNull(String msg, Object o) {
+ AssertJUnit.assertNotNull(msg, o);
+ }
+
+ protected void assertNull(Object o) {
+ AssertJUnit.assertNull(o);
+ }
+
+ protected void assertNull(String msg, Object o) {
+ AssertJUnit.assertNull(msg, o);
+ }
+
+ protected void assertFalse(boolean b) {
+ AssertJUnit.assertFalse(b);
+ }
+
+ protected void assertFalse(String msg, boolean b) {
+ AssertJUnit.assertFalse(msg, b);
+ }
+
+ protected void assertTrue(boolean b) {
+ AssertJUnit.assertTrue(b);
+ }
+
+ protected void assertTrue(String msg, boolean b) {
+ AssertJUnit.assertTrue(msg, b);
+ }
+
+ protected void assertEquals(int expected, int actual) {
+ AssertJUnit.assertEquals(expected, actual);
+ }
+
+ protected void assertEquals(String msg, int expected, int actual) {
+ AssertJUnit.assertEquals(msg, expected, actual);
+ }
+
+ protected void assertEquals(long expected, long actual) {
+ AssertJUnit.assertEquals(expected, actual);
+ }
+
+ protected void assertEquals(String msg, long expected, long actual) {
+ AssertJUnit.assertEquals(msg, expected, actual);
+ }
+
+ protected void assertEquals(String expected, String actual) {
+ AssertJUnit.assertEquals(expected, actual);
+ }
+
+ protected void assertEquals(String msg, String expected, String actual) {
+ AssertJUnit.assertEquals(msg, expected, actual);
+ }
+
+ protected void assertEquals(boolean expected, boolean actual) {
+ AssertJUnit.assertEquals(expected, actual);
+ }
+
+ protected void assertEquals(String msg, boolean expected, boolean actual) {
+ AssertJUnit.assertEquals(msg, expected, actual);
+ }
+
+ protected void assertEquals(Object expected, Object actual) {
+ AssertJUnit.assertEquals(expected, actual);
+ }
+
+ protected void assertEquals(String msg, Object expected, Object actual) {
+ AssertJUnit.assertEquals(msg, expected, actual);
+ }
+
+ protected void fail() {
+ AssertJUnit.fail();
+ }
+
+ protected void fail(String message) {
+ AssertJUnit.fail(message);
+ }
+
+ private final long DEFAULT_OFFSET = 50;
+ private long referenceTime = new Date().getTime();
+
+ public Date getAnotherDate() {
+ return getAnotherDate(DEFAULT_OFFSET);
+ }
+
+ public Date getAnotherDate(long offset) {
+ referenceTime += offset;
+ return new Date(referenceTime);
+ }
+
+ /**
+ * If you need to test server plugins, you must first prepare the server plugin service.
+ * After this returns, the caller must explicitly start the PC by using the appropriate API
+ * on the given mbean; this method will only start the service, it will NOT start the master PC.
+ *
+ * @param testServiceMBean the object that will house your test server plugins
+ *
+ * @throws RuntimeException
+ */
+ public void prepareCustomServerPluginService(ServerPluginService testServiceMBean) {
+ try {
+ // TODO: Fix
+ // MBeanServer mbs = getJBossMBeanServer();
+ // testServiceMBean.start();
+ // mbs.registerMBean(testServiceMBean, ServerPluginServiceMBean.OBJECT_NAME);
+ // serverPluginService = testServiceMBean;
+ return;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void unprepareServerPluginService() throws Exception {
+ unprepareServerPluginService(false);
+ }
+
+ public void unprepareServerPluginService(boolean beanOnly) throws Exception {
+ if (serverPluginService != null) {
+ serverPluginService.stopMasterPluginContainer();
+ serverPluginService.stop();
+ if (beanOnly) {
+ // TODO: Fix
+ // if (mbs.isRegistered(ServerPluginService.OBJECT_NAME)) {
+ // getJBossMBeanServer().unregisterMBean(ServerPluginService.OBJECT_NAME);
+ // }
+ // if (mbs.isRegistered(ServerPluginServiceMBean.OBJECT_NAME)) {
+ // getJBossMBeanServer().unregisterMBean(ServerPluginServiceMBean.OBJECT_NAME);
+ // }
+
+ } else {
+ // releaseJBossMBeanServer();
+ }
+ serverPluginService = null;
+ }
+ }
+
+ public SchedulerService getSchedulerService() {
+ return schedulerService;
+ }
+
+ public void prepareScheduler() {
+ try {
+ if (schedulerService != null) {
+ return;
+ }
+
+ Properties quartzProps = new Properties();
+ quartzProps.load(this.getClass().getClassLoader().getResourceAsStream("test-scheduler.properties"));
+
+ schedulerService = new SchedulerService();
+ schedulerService.setQuartzProperties(quartzProps);
+ schedulerService.start();
+ //getJBossMBeanServer().registerMBean(schedulerService, SchedulerServiceMBean.SCHEDULER_MBEAN_NAME);
+ schedulerService.startQuartzScheduler();
+ return;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void unprepareScheduler() throws Exception {
+ unprepareScheduler(false);
+ }
+
+ public void unprepareScheduler(boolean beanOnly) throws Exception {
+ if (schedulerService != null) {
+ schedulerService.stop();
+ if (beanOnly) {
+ // MBeanServer mbs = getJBossMBeanServer();
+ // if (mbs.isRegistered(SchedulerServiceMBean.SCHEDULER_MBEAN_NAME)) {
+ // getJBossMBeanServer().unregisterMBean(SchedulerServiceMBean.SCHEDULER_MBEAN_NAME);
+ // }
+ } else {
+ // releaseJBossMBeanServer();
+ }
+
+ schedulerService = null;
+ }
+ }
+
+ public PluginDeploymentScannerMBean getPluginScannerService() {
+ return pluginScannerService;
+ }
+
+ protected void preparePluginScannerService() {
+ preparePluginScannerService(null);
+ }
+
+ public void preparePluginScannerService(PluginDeploymentScannerMBean scannerService) {
+ try {
+ if (scannerService == null) {
+ scannerService = new PluginDeploymentScanner();
+ }
+ // MBeanServer mbs = getJBossMBeanServer();
+ // mbs.registerMBean(scannerService, PluginDeploymentScannerMBean.OBJECT_NAME);
+ // pluginScannerService = scannerService;
+ return;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void unpreparePluginScannerService() throws Exception {
+ unpreparePluginScannerService(false);
+ }
+
+ public void unpreparePluginScannerService(boolean beanOnly) throws Exception {
+ if (pluginScannerService != null) {
+ pluginScannerService.stop();
+ if (beanOnly) {
+ // MBeanServer mbs = getJBossMBeanServer();
+ // if (mbs.isRegistered(PluginDeploymentScannerMBean.OBJECT_NAME)) {
+ // getJBossMBeanServer().unregisterMBean(PluginDeploymentScannerMBean.OBJECT_NAME);
+ }
+ } else {
+ // releaseJBossMBeanServer();
+ }
+
+ pluginScannerService = null;
+ }
+
+ /**
+ * If you need to test round trips from server to agent and back, you first must install the server communications
+ * service that houses all the agent clients. Call this method and add your test agent services to the public fields
+ * in the returned object.
+ *
+ * @return the object that will house your test agent service impls and the agent clients.
+ *
+ * @throws RuntimeException
+ */
+ public TestServerCommunicationsService prepareForTestAgents() {
+ try {
+ // MBeanServer mbs = getJBossMBeanServer();
+ // if (mbs.isRegistered(ServerCommunicationsServiceMBean.OBJECT_NAME)) {
+ // mbs.unregisterMBean(ServerCommunicationsServiceMBean.OBJECT_NAME);
+ // }
+ TestServerCommunicationsService testAgentContainer = new TestServerCommunicationsService();
+ // mbs.registerMBean(testAgentContainer, ServerCommunicationsServiceMBean.OBJECT_NAME);
+ return testAgentContainer;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Call this after your tests have finished. You only need to call this if your test previously called
+ * {@link #prepareForTestAgents()}.
+ */
+ public void unprepareForTestAgents() {
+ unprepareForTestAgents(false);
+ }
+
+ public void unprepareForTestAgents(boolean beanOnly) {
+ try {
+ if (beanOnly) {
+ // MBeanServer mbs = getJBossMBeanServer();
+ // if (mbs.isRegistered(ServerCommunicationsServiceMBean.OBJECT_NAME)) {
+ // mbs.unregisterMBean(ServerCommunicationsServiceMBean.OBJECT_NAME);
+ // }
+ } else {
+ // releaseJBossMBeanServer();
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public MBeanServer getPlatformMBeanServer() {
+ return ManagementFactory.getPlatformMBeanServer();
+ }
+
+ /**
+ * This creates a session for the given user and associates that session with the subject. You can test the security
+ * annotations by creating sessions for different users with different permissions.
+ *
+ * @param subject a JON subject
+ * @return the session activated subject, a copy of the subject passed in.
+ */
+ public Subject createSession(Subject subject) {
+ return SessionManager.getInstance().put(subject);
+ }
+
+ public static Connection getConnection() throws SQLException {
+ return LookupUtil.getDataSource().getConnection();
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/LargeGroupTestBase.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/LargeGroupTestBase.java
new file mode 100644
index 0000000..cb7d301
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/LargeGroupTestBase.java
@@ -0,0 +1,411 @@
+/*
+ * 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.test;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+import javax.transaction.TransactionManager;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.authz.Role;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.configuration.definition.PropertySimpleType;
+import org.rhq.core.domain.configuration.group.GroupPluginConfigurationUpdate;
+import org.rhq.core.domain.configuration.group.GroupResourceConfigurationUpdate;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.InventoryStatus;
+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.domain.resource.group.ResourceGroup;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.configuration.ConfigurationManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.util.SessionTestHelper;
+import org.rhq.test.JPAUtils;
+import org.rhq.test.TransactionCallbackWithContext;
+
+public abstract class LargeGroupTestBase extends AbstractEJB3Test {
+ // for plugin configuration
+ protected static final String PC_PROP1_NAME = "LargeGroupTest pc prop1";
+ protected static final String PC_PROP1_VALUE = "LargeGroupTest pc property one";
+ protected static final String PC_PROP2_NAME = "LargeGroupTest pc prop2";
+
+ // for resource configuration
+ protected static final String RC_PROP1_NAME = "LargeGroupTest rc prop1";
+ protected static final String RC_PROP1_VALUE = "LargeGroupTest rc property one";
+ protected static final String RC_PROP2_NAME = "LargeGroupTest rc prop2";
+
+ protected ConfigurationManagerLocal configurationManager;
+ protected ResourceManagerLocal resourceManager;
+ protected ResourceGroupManagerLocal resourceGroupManager;
+ protected SubjectManagerLocal subjectManager;
+
+ protected class LargeGroupEnvironment {
+ public Agent agent;
+ public Resource platformResource; // all if its children will be members of the compatible group
+ public ResourceType platformType;
+ public ResourceType serverType;
+ public ConfigurationDefinition serverPluginConfiguration;
+ public ConfigurationDefinition serverResourceConfiguration;
+ public ResourceGroup compatibleGroup;
+ public Subject normalSubject; // user with a role that has access to the group
+ public Role normalRole; // role with permissions on the group
+ public Subject unauthzSubject; // a subject with no authorization to do anything
+
+ public LargeGroupEnvironment() {
+ }
+
+ /**
+ * Stores references to the existing lge's resource types' metadata but nothing else.
+ * @param lge the object whose platformType and serverType are stored in the new lge object
+ */
+ public LargeGroupEnvironment(LargeGroupEnvironment lge) {
+ if (lge != null) {
+ this.platformType = lge.platformType;
+ this.serverType = lge.serverType;
+ this.serverPluginConfiguration = lge.serverPluginConfiguration;
+ this.serverResourceConfiguration = lge.serverResourceConfiguration;
+ }
+ }
+ }
+
+ /**
+ * Prepares things for the entire test class.
+ */
+ @BeforeClass
+ public void beforeClassBase() {
+ configurationManager = LookupUtil.getConfigurationManager();
+ resourceManager = LookupUtil.getResourceManager();
+ resourceGroupManager = LookupUtil.getResourceGroupManager();
+ subjectManager = LookupUtil.getSubjectManager();
+ }
+
+ @BeforeMethod
+ public void beforeMethodBase() throws Exception {
+ TestServerCommunicationsService agentServiceContainer = prepareForTestAgents();
+ setupMockAgentServices(agentServiceContainer);
+
+ prepareScheduler();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethodBase() throws Exception {
+ try {
+ unprepareForTestAgents();
+ } finally {
+ unprepareScheduler();
+ }
+ }
+
+ protected abstract void setupMockAgentServices(TestServerCommunicationsService agentServiceContainer);
+
+ /**
+ * Creates a compatible group of the given size. This also creates a normal user and a role
+ * and makes sure that user can access the group that was created. The role will be assigned the
+ * given permissions and that role be placed on the new group and the new user.
+ *
+ * @param groupSize the number of members to create and put into the compatible group that is created.
+ * @param permissions permissions to grant the new user via the new role.
+ * @return information about the entities that were created
+ */
+ protected LargeGroupEnvironment createLargeGroupWithNormalUserRoleAccess(final int groupSize,
+ final Permission... permissions) {
+ return createLargeGroupWithNormalUserRoleAccess(null, groupSize, 0, 0, 0, permissions);
+ }
+
+ protected LargeGroupEnvironment createLargeGroupWithNormalUserRoleAccess(LargeGroupEnvironment largeGroupEnv,
+ final int groupSize, final int down, final int unknown, final int disabled, final Permission... permissions) {
+ return createLargeGroupWithNormalUserRoleAccessWithInventoryStatus(largeGroupEnv, groupSize, down, unknown,
+ disabled, 0, permissions);
+ }
+
+ /**
+ * Creates a compatible group of the given size. This also creates a normal user and a role
+ * and makes sure that user can access the group that was created. The role will be assigned the
+ * given permissions and that role be placed on the new group and the new user.
+ *
+ * If lge is not null, that means we already have resource types created. We'll reuse those types.
+ *
+ * @param largeGroupEnv an already-created large group environment object (may be null)
+ * @param groupSize the number of members to create and put into the compatible group that is created.
+ * @param down number of resources that are to be set as DOWN
+ * @param unknown number of resources whose availability status is to be marked as UNKNOWN
+ * @param disabled number of resources that are to be set as DISABLED
+ * @param uncommitted number of resources whose inventory status is not COMMITTED (will be NEW instead)
+ * @param permissions permissions to grant the new user via the new role.
+ * @return information about the entities that were created
+ */
+ protected LargeGroupEnvironment createLargeGroupWithNormalUserRoleAccessWithInventoryStatus(
+ LargeGroupEnvironment largeGroupEnv, final int groupSize, final int down, final int unknown,
+ final int disabled, final int uncommitted, final Permission... permissions) {
+
+ System.out.println("=====Creating a group with [" + groupSize + "] members");
+
+ final LargeGroupEnvironment lge = new LargeGroupEnvironment(largeGroupEnv);
+ JPAUtils.executeInTransaction(new TransactionCallbackWithContext<Object>() {
+ public Object execute(TransactionManager tm, EntityManager em) throws Exception {
+ // create the agent where all resources will be housed
+ lge.agent = SessionTestHelper.createNewAgent(em, "LargeGroupTestAgent");
+
+ // create the platform resource type and server resource type
+ // the server type will have both a plugin configuration definition and resource config def
+ if (lge.platformType == null) {
+ lge.platformType = new ResourceType("LargeGroupTestPlatformType", "testPlugin",
+ ResourceCategory.PLATFORM, null);
+ em.persist(lge.platformType);
+ } else {
+ lge.platformType = em.find(ResourceType.class, lge.platformType.getId());
+ }
+
+ if (lge.serverType == null) {
+ lge.serverType = new ResourceType("LargeGroupTestServerType", "testPlugin",
+ ResourceCategory.SERVER, lge.platformType);
+ lge.serverPluginConfiguration = new ConfigurationDefinition("LargeGroupTestPCDef", "pc desc");
+ lge.serverPluginConfiguration.put(new PropertyDefinitionSimple(PC_PROP1_NAME, "pc prop1desc",
+ false, PropertySimpleType.STRING));
+ lge.serverPluginConfiguration.put(new PropertyDefinitionSimple(PC_PROP2_NAME, "pc prop2desc",
+ false, PropertySimpleType.STRING));
+ lge.serverType.setPluginConfigurationDefinition(lge.serverPluginConfiguration);
+
+ lge.serverResourceConfiguration = new ConfigurationDefinition("LargeGroupTestRCDef", "rc desc");
+ lge.serverResourceConfiguration.put(new PropertyDefinitionSimple(RC_PROP1_NAME, "rc prop1desc",
+ false, PropertySimpleType.STRING));
+ lge.serverResourceConfiguration.put(new PropertyDefinitionSimple(RC_PROP2_NAME, "rc prop2desc",
+ false, PropertySimpleType.STRING));
+ lge.serverType.setResourceConfigurationDefinition(lge.serverResourceConfiguration);
+
+ em.persist(lge.serverType);
+ em.flush();
+ } else {
+ lge.serverType = em.find(ResourceType.class, lge.serverType.getId());
+ }
+
+ // create our platform - all of our server resources will have this as their parent
+ lge.platformResource = SessionTestHelper.createNewResource(em, "LargeGroupTestPlatform",
+ lge.platformType);
+ lge.platformResource.setAgent(lge.agent);
+
+ // create our subject and role
+ lge.normalSubject = new Subject("LargeGroupTestSubject" + System.currentTimeMillis(), true, false);
+ lge.normalRole = SessionTestHelper.createNewRoleForSubject(em, lge.normalSubject, "LargeGroupTestRole",
+ permissions);
+
+ // create our unauthorized subject
+ lge.unauthzSubject = SessionTestHelper.createNewSubject(em, "LargeGroupTestSubjectUnauth");
+
+ // create our compatible group
+ lge.compatibleGroup = SessionTestHelper.createNewCompatibleGroupForRole(em, lge.normalRole,
+ "LargeGroupTestCompatGroup", lge.serverType);
+
+ // create our many server resources
+ int downCount = down;
+ int unknownCount = unknown;
+ int disabledCount = disabled;
+ int uncommittedCount = uncommitted;
+ System.out.print("=====> Creating member Resources (this might take some time)...");
+ for (int i = 1; i <= groupSize; i++) {
+ AvailabilityType avail;
+ InventoryStatus inventoryStatus = InventoryStatus.COMMITTED;
+ if (downCount > 0) {
+ avail = AvailabilityType.DOWN;
+ downCount--;
+ } else if (unknownCount > 0) {
+ avail = AvailabilityType.UNKNOWN;
+ unknownCount--;
+ } else if (disabledCount > 0) {
+ avail = AvailabilityType.DISABLED;
+ disabledCount--;
+ } else if (uncommittedCount > 0) {
+ avail = AvailabilityType.UNKNOWN;
+ inventoryStatus = InventoryStatus.NEW;
+ uncommittedCount--;
+ } else {
+ avail = AvailabilityType.UP;
+ }
+
+ Resource res = SessionTestHelper.createNewResourceForGroup(em, lge.compatibleGroup,
+ "LargeGroupTestServer", lge.serverType, avail, (i % 100) == 0);
+ res.setAgent(lge.agent);
+ res.setInventoryStatus(inventoryStatus);
+ lge.platformResource.addChildResource(res);
+
+ // give it an initial plugin configuration
+ Configuration pc = new Configuration();
+ pc.put(new PropertySimple(PC_PROP1_NAME, PC_PROP1_VALUE));
+ pc.put(new PropertySimple(PC_PROP2_NAME, res.getId()));
+ em.persist(pc);
+ res.setPluginConfiguration(pc);
+
+ if ((i % 100) == 0) {
+ System.out.print(i);
+ } else if ((i % 10) == 0) {
+ System.out.print('.');
+ }
+ }
+ System.out.println(" Done.");
+
+ em.flush();
+ em.clear();
+ return null;
+ }
+ });
+
+ System.out.println("=====Created group [" + lge.compatibleGroup.getName() + "] with ["
+ + lge.platformResource.getChildResources().size() + "] members");
+
+ return lge;
+ }
+
+ protected void tearDownLargeGroupWithNormalUserRoleAccess(final LargeGroupEnvironment lge) throws Exception {
+ tearDownLargeGroupWithNormalUserRoleAccess(lge, false);
+ }
+
+ /**
+ * Purges all the entities that were created by the
+ * {@link #createLargeGroupWithNormalUserRoleAccess(int, org.rhq.core.domain.authz.Permission...)} method.
+ * This includes the user, role, agent and all resources, along with the group itself.
+ *
+ * @param lge contains information that was created which needs to be deleted
+ * @param keepTypes if true, do not delete the resource types
+ */
+ protected void tearDownLargeGroupWithNormalUserRoleAccess(final LargeGroupEnvironment lge, boolean keepTypes)
+ throws Exception {
+ System.out.println("=====Cleaning up test data from " + this.getClass().getSimpleName());
+
+ // purge the group itself
+ resourceGroupManager.deleteResourceGroup(getOverlord(), lge.compatibleGroup.getId());
+
+ // purge all resources by performing in-band and out-of-band work in quick succession.
+ // this takes a long time but trying to get this right using native queries is hard to get right so just do it this way.
+ // only need to delete the platform which will delete all children servers AND the agent itself
+ System.out.print("=====> Removing member Resources (this might take some time)...");
+ final List<Integer> deletedIds = resourceManager.uninventoryResource(getOverlord(),
+ lge.platformResource.getId());
+ for (int i = 1, deletedIdsSize = deletedIds.size(); i <= deletedIdsSize; i++) {
+ Integer deletedResourceId = deletedIds.get(i - 1);
+ resourceManager.uninventoryResourceAsyncWork(getOverlord(), deletedResourceId);
+ if ((i % 100) == 0) {
+ System.out.print(i);
+ } else if ((i % 10) == 0) {
+ System.out.print('.');
+ }
+ }
+ System.out.println(" Done.");
+
+ // purge the users and role
+ executeInTransaction(new TransactionCallbackReturnable<Object>() {
+ public Object execute() throws Exception {
+ lge.normalRole = em.getReference(Role.class, lge.normalRole.getId());
+ lge.normalSubject = em.getReference(Subject.class, lge.normalSubject.getId());
+ lge.unauthzSubject = em.getReference(Subject.class, lge.unauthzSubject.getId());
+ em.remove(lge.normalRole);
+ em.remove(lge.normalSubject);
+ em.remove(lge.unauthzSubject);
+ return null;
+ }
+ });
+
+ if (!keepTypes) {
+ // purge the resource types
+ executeInTransaction(new TransactionCallbackReturnable<Object>() {
+ public Object execute() throws Exception {
+ ResourceType pType = em.getReference(ResourceType.class, lge.platformResource.getResourceType()
+ .getId());
+ ResourceType sType = em.getReference(ResourceType.class, lge.compatibleGroup.getResourceType()
+ .getId());
+ em.remove(sType);
+ em.remove(pType);
+ return null;
+ }
+ });
+ }
+
+ System.out.println("=====Cleaned up test data from " + this.getClass().getSimpleName());
+ }
+
+ /**
+ * Given the id of a compatible group, this will return the status of the update.
+ *
+ * @param groupId compatible group ID
+ * @return status, or null if not known
+ */
+ protected ConfigurationUpdateStatus getGroupPluginConfigurationStatus(final int groupId) {
+ return JPAUtils.executeInTransaction(new TransactionCallbackWithContext<ConfigurationUpdateStatus>() {
+ public ConfigurationUpdateStatus execute(TransactionManager tm, EntityManager em) throws Exception {
+ try {
+ Query query = em.createNamedQuery(GroupPluginConfigurationUpdate.QUERY_FIND_LATEST_BY_GROUP_ID);
+ query.setParameter("groupId", groupId);
+ GroupPluginConfigurationUpdate latestConfigGroupUpdate = (GroupPluginConfigurationUpdate) query
+ .getSingleResult();
+ return latestConfigGroupUpdate.getStatus();
+ } catch (NoResultException nre) {
+ // The group resource config history is empty, so there's obviously no update in progress.
+ return null;
+ }
+ }
+ });
+ }
+
+ /**
+ * Given the id of a compatible group, this will return the status of the update.
+ *
+ * @param groupId compatible group ID
+ * @return status, or null if not known
+ */
+ protected ConfigurationUpdateStatus getGroupResourceConfigurationStatus(final int groupId) {
+ return JPAUtils.executeInTransaction(new TransactionCallbackWithContext<ConfigurationUpdateStatus>() {
+ public ConfigurationUpdateStatus execute(TransactionManager tm, EntityManager em) throws Exception {
+ try {
+ Query query = em.createNamedQuery(GroupResourceConfigurationUpdate.QUERY_FIND_LATEST_BY_GROUP_ID);
+ query.setParameter("groupId", groupId);
+ GroupResourceConfigurationUpdate latestConfigGroupUpdate = (GroupResourceConfigurationUpdate) query
+ .getSingleResult();
+ return latestConfigGroupUpdate.getStatus();
+ } catch (NoResultException nre) {
+ // The group resource config history is empty, so there's obviously no update in progress.
+ return null;
+ }
+ }
+ });
+ }
+
+ /**
+ * Obtain the overlord user.
+ * @return overlord
+ */
+ protected Subject getOverlord() {
+ return subjectManager.getOverlord();
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/OldAbstractEJB3Test.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/OldAbstractEJB3Test.java
new file mode 100644
index 0000000..a8337b7
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/OldAbstractEJB3Test.java
@@ -0,0 +1,445 @@
+///*
+// * 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.enterprise.server.test;
+
+import org.testng.AssertJUnit;
+
+
+//import static org.rhq.test.JPAUtils.lookupEntityManager;
+//import static org.rhq.test.JPAUtils.lookupTransactionManager;
+//
+//import java.sql.Connection;
+//import java.sql.SQLException;
+//import java.util.Hashtable;
+//import java.util.Properties;
+//
+//import javax.management.MBeanServer;
+//import javax.management.MBeanServerFactory;
+//import javax.naming.InitialContext;
+//import javax.naming.NamingException;
+//import javax.persistence.EntityManager;
+//import javax.transaction.TransactionManager;
+//
+//import org.hibernate.SessionFactory;
+//import org.hibernate.stat.Statistics;
+//import org.testng.AssertJUnit;
+//import org.testng.annotations.AfterMethod;
+//import org.testng.annotations.AfterSuite;
+//import org.testng.annotations.BeforeMethod;
+//import org.testng.annotations.BeforeSuite;
+//
+//import org.jboss.ejb3.embedded.EJB3StandaloneBootstrap;
+//import org.jboss.ejb3.embedded.EJB3StandaloneDeployer;
+//import org.jboss.mx.util.MBeanServerLocator;
+//
+//import org.rhq.core.db.DatabaseTypeFactory;
+//import org.rhq.core.db.PostgresqlDatabaseType;
+//import org.rhq.core.domain.auth.Subject;
+//import org.rhq.core.domain.server.PersistenceUtility;
+//import org.rhq.enterprise.server.RHQConstants;
+//import org.rhq.enterprise.server.auth.SessionManager;
+//import org.rhq.enterprise.server.content.ContentSourceManagerBean;
+//import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceMBean;
+//import org.rhq.enterprise.server.core.plugin.PluginDeploymentScanner;
+//import org.rhq.enterprise.server.core.plugin.PluginDeploymentScannerMBean;
+//import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+//import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceMBean;
+//import org.rhq.enterprise.server.scheduler.SchedulerService;
+//import org.rhq.enterprise.server.scheduler.SchedulerServiceMBean;
+//import org.rhq.enterprise.server.util.LookupUtil;
+//
+////
+/////**
+//// * This is the abstract test base for server jar tests.
+//// *
+//// * @author Greg Hinkle
+//// */
+public abstract class OldAbstractEJB3Test extends AssertJUnit {
+ //
+ // private static EJB3StandaloneDeployer deployer;
+ // private static Statistics stats;
+ // @SuppressWarnings("unused")
+ // private static long start; // see endTest() if you want to output this
+ // private SchedulerService schedulerService;
+ // private ServerPluginService serverPluginService;
+ // private MBeanServer dummyJBossMBeanServer;
+ // private PluginDeploymentScannerMBean pluginScannerService;
+ //
+ //
+ // //@BeforeSuite(groups = {"integration.ejb3","PERF"}) // TODO investigate again
+ // @BeforeSuite(alwaysRun = true)
+ // public static void startupEmbeddedJboss() throws Exception {
+ // // The embeddedDeployment property needs to be set for running tests
+ // // with the embedded container. It is set in the surefire configuration
+ // // in pom.xml but setting here makes it easier to run tests directly
+ // // from your IDE.
+ // //
+ // // jsanda
+ // System.setProperty("embeddedDeployment", "true");
+ //
+ // // Setting content location to the tmp dir
+ // System.setProperty(ContentSourceManagerBean.FILESYSTEM_PROPERTY, System.getProperty("java.io.tmpdir"));
+ //
+ // System.out.println("Starting JBoss EJB3 Embedded Container...");
+ // String deployDir = System.getProperty("deploymentDirectory", "target/classes");
+ // System.out.println("Loading EJB3 deployments from directory: " + deployDir);
+ // try {
+ // EJB3StandaloneBootstrap.boot(null);
+ // // EJB3StandaloneBootstrap.scanClasspath();
+ //
+ // System.err.println("...... embedded container booted....");
+ //
+ // deployer = EJB3StandaloneBootstrap.createDeployer();
+ //
+ // deployer.setClassLoader(AbstractEJB3Test.class.getClassLoader());
+ // System.err.println("...... embedded container classloader set....");
+ //
+ // deployer.getArchivesByResource().add("META-INF/persistence.xml");
+ // System.err.println("...... embedded container persistence xml deployed....");
+ //
+ // deployer.getArchivesByResource().add("META-INF/ejb-jar.xml");
+ // System.err.println("...... embedded container ejb-jar xml deployed....");
+ //
+ // EJB3StandaloneBootstrap.deployXmlResource("jboss-jms-beans.xml");
+ // System.err.println("...... embedded container jboss-jms-beans xml deployed....");
+ //
+ // EJB3StandaloneBootstrap.deployXmlResource("rhq-mdb-beans.xml");
+ // System.err.println("...... embedded container rhq-mdb-beans xml deployed....");
+ //
+ // /*
+ // * File core = new File(deployDir, "on-core-domain-ejb.ejb3"); if (!core.exists())
+ // * System.err.println("Deployment directory does not exist: " + core.getAbsolutePath());
+ // * deployer.getArchives().add(core.toURI().toURL());
+ // *
+ // * File server = new File(deployDir, "on-enterprise-server-ejb.ejb3"); if (!server.exists())
+ // * System.err.println("Deployment directory does not exist: " + server.getAbsolutePath());
+ // * deployer.getArchives().add(server.toURI().toURL());
+ // *
+ // */
+ //
+ // //deployer.setKernel(EJB3StandaloneBootstrap.getKernel());
+ // deployer.create();
+ // System.err.println("...... deployer created....");
+ //
+ // deployer.start();
+ // System.err.println("...... deployer started....");
+ //
+ // System.err.println("...... start statistics");
+ // SessionFactory sessionFactory = PersistenceUtility.getHibernateSession(getEntityManager())
+ // .getSessionFactory();
+ // stats = sessionFactory.getStatistics();
+ // stats.setStatisticsEnabled(true);
+ //
+ // System.err.println("...... embedded container initialized and ready for testing....");
+ //
+ // } catch (Throwable t) {
+ // // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
+ // // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
+ // t.printStackTrace();
+ // throw new RuntimeException(t);
+ // }
+ // }
+ //
+ // //@Configuration(groups = "integration.ejb3", afterSuite = true)
+ // @AfterSuite(alwaysRun = true)
+ // public static void shutdownEmbeddedJboss() {
+ // System.out.println("Stopping JBoss EJB3 Embedded Container...");
+ //
+ // System.err.println("!!! Any errors occurring after this point !!!");
+ // System.err.println("!!! occurred during embedded server shutdown !!!");
+ // System.err.println("!!! and are probably not a real problem. !!!");
+ // if (deployer != null) {
+ // try {
+ // deployer.stop();
+ // deployer.destroy();
+ // deployer = null;
+ // } catch (Throwable t) {
+ // System.err.println("Failed to stop embedded deployer");
+ // t.printStackTrace(System.err);
+ // }
+ // }
+ // EJB3StandaloneBootstrap.shutdown();
+ // }
+ //
+ // @BeforeMethod
+ // public static void startTest() {
+ // if (DatabaseTypeFactory.getDefaultDatabaseType() == null) {
+ // try {
+ // Connection conn = getConnection();
+ // DatabaseTypeFactory.setDefaultDatabaseType(DatabaseTypeFactory.getDatabaseType(conn));
+ // } catch (Exception e) {
+ // System.err.println("!!! WARNING !!! cannot set default database type, some tests may fail");
+ // e.printStackTrace();
+ // }
+ // }
+ //
+ // if (stats != null)
+ // start = stats.getQueryExecutionCount();
+ // else
+ // start = 0;
+ // }
+ //
+ // public static Connection getConnection() throws SQLException {
+ // return LookupUtil.getDataSource().getConnection();
+ // }
+ //
+ // @AfterMethod
+ // public static void endTest() {
+ // //System.out.println("Connections used: " + (stats.getQueryExecutionCount() - start));
+ // }
+ //
+ // public TransactionManager getTransactionManager() {
+ // return lookupTransactionManager();
+ // }
+ //
+ // public static EntityManager getEntityManager() {
+ // return lookupEntityManager();
+ // }
+ //
+ // public static InitialContext getInitialContext() {
+ // Hashtable<String, String> env = new Hashtable<String, String>();
+ // env.put("java.naming.factory.initial", "org.jnp.interfaces.LocalOnlyContextFactory");
+ // env.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
+ // try {
+ // return new InitialContext(env);
+ // } catch (NamingException e) {
+ // e.printStackTrace();
+ // throw new RuntimeException("Failed to load initial context", e);
+ // }
+ // }
+ //
+ // public boolean isPostgres() throws Exception {
+ // return DatabaseTypeFactory.getDatabaseType(getInitialContext(), RHQConstants.DATASOURCE_JNDI_NAME) instanceof PostgresqlDatabaseType;
+ // }
+ //
+ // /**
+ // * This creates a session for the given user and associates that session with the subject. You can test the security
+ // * annotations by creating sessions for different users with different permissions.
+ // *
+ // * @param subject a JON subject
+ // * @return the session activated subject, a copy of the subject passed in.
+ // */
+ // public Subject createSession(Subject subject) {
+ // return SessionManager.getInstance().put(subject);
+ // }
+ //
+ // /**
+ // * Returns an MBeanServer that simulates the JBossAS MBeanServer.
+ // *
+ // * @return MBeanServer instance
+ // */
+ // public MBeanServer getJBossMBeanServer() {
+ // if (dummyJBossMBeanServer == null) {
+ // dummyJBossMBeanServer = MBeanServerFactory.createMBeanServer("jboss");
+ // MBeanServerLocator.setJBoss(dummyJBossMBeanServer);
+ // }
+ //
+ // return dummyJBossMBeanServer;
+ // }
+ //
+ // public void releaseJBossMBeanServer() {
+ // if (dummyJBossMBeanServer != null) {
+ // MBeanServerFactory.releaseMBeanServer(dummyJBossMBeanServer);
+ // dummyJBossMBeanServer = null;
+ // }
+ // }
+ //
+ // /**
+ // * If you need to test round trips from server to agent and back, you first must install the server communications
+ // * service that houses all the agent clients. Call this method and add your test agent services to the public fields
+ // * in the returned object.
+ // *
+ // * @return the object that will house your test agent service impls and the agent clients.
+ // *
+ // * @throws RuntimeException
+ // */
+ // public TestServerCommunicationsService prepareForTestAgents() {
+ // try {
+ // MBeanServer mbs = getJBossMBeanServer();
+ // if (mbs.isRegistered(ServerCommunicationsServiceMBean.OBJECT_NAME)) {
+ // mbs.unregisterMBean(ServerCommunicationsServiceMBean.OBJECT_NAME);
+ // }
+ // TestServerCommunicationsService testAgentContainer = new TestServerCommunicationsService();
+ // mbs.registerMBean(testAgentContainer, ServerCommunicationsServiceMBean.OBJECT_NAME);
+ // return testAgentContainer;
+ // } catch (Exception e) {
+ // throw new RuntimeException(e);
+ // }
+ // }
+ //
+ // /**
+ // * Call this after your tests have finished. You only need to call this if your test previously called
+ // * {@link #prepareForTestAgents()}.
+ // */
+ // public void unprepareForTestAgents() {
+ // unprepareForTestAgents(false);
+ // }
+ //
+ // public void unprepareForTestAgents(boolean beanOnly) {
+ // try {
+ // if (beanOnly) {
+ // MBeanServer mbs = getJBossMBeanServer();
+ // if (mbs.isRegistered(ServerCommunicationsServiceMBean.OBJECT_NAME)) {
+ // mbs.unregisterMBean(ServerCommunicationsServiceMBean.OBJECT_NAME);
+ // }
+ // } else {
+ // releaseJBossMBeanServer();
+ // }
+ // } catch (Exception e) {
+ // throw new RuntimeException(e);
+ // }
+ // }
+ //
+ // /**
+ // * If you need to test server plugins, you must first prepare the server plugin service.
+ // * After this returns, the caller must explicitly start the PC by using the appropriate API
+ // * on the given mbean; this method will only start the service, it will NOT start the master PC.
+ // *
+ // * @param testServiceMBean the object that will house your test server plugins
+ // *
+ // * @throws RuntimeException
+ // */
+ // public void prepareCustomServerPluginService(ServerPluginService testServiceMBean) {
+ // try {
+ // MBeanServer mbs = getJBossMBeanServer();
+ // testServiceMBean.start();
+ // mbs.registerMBean(testServiceMBean, ServerPluginServiceMBean.OBJECT_NAME);
+ // serverPluginService = testServiceMBean;
+ // return;
+ // } catch (Exception e) {
+ // throw new RuntimeException(e);
+ // }
+ // }
+ //
+ // public void unprepareServerPluginService() throws Exception {
+ // unprepareServerPluginService(false);
+ // }
+ //
+ // public void unprepareServerPluginService(boolean beanOnly) throws Exception {
+ // if (serverPluginService != null) {
+ // serverPluginService.stopMasterPluginContainer();
+ // serverPluginService.stop();
+ // if (beanOnly) {
+ // MBeanServer mbs = getJBossMBeanServer();
+ // if (mbs.isRegistered(ServerPluginService.OBJECT_NAME)) {
+ // getJBossMBeanServer().unregisterMBean(ServerPluginService.OBJECT_NAME);
+ // }
+ // if (mbs.isRegistered(ServerPluginServiceMBean.OBJECT_NAME)) {
+ // getJBossMBeanServer().unregisterMBean(ServerPluginServiceMBean.OBJECT_NAME);
+ // }
+ //
+ // } else {
+ // releaseJBossMBeanServer();
+ // }
+ // serverPluginService = null;
+ // }
+ // }
+ //
+ // public SchedulerService getSchedulerService() {
+ // return schedulerService;
+ // }
+ //
+ // public void prepareScheduler() {
+ // try {
+ // if (schedulerService != null) {
+ // return;
+ // }
+ //
+ // Properties quartzProps = new Properties();
+ // quartzProps.load(this.getClass().getClassLoader().getResourceAsStream("test-scheduler.properties"));
+ //
+ // schedulerService = new SchedulerService();
+ // schedulerService.setQuartzProperties(quartzProps);
+ // schedulerService.start();
+ // getJBossMBeanServer().registerMBean(schedulerService, SchedulerServiceMBean.SCHEDULER_MBEAN_NAME);
+ // schedulerService.startQuartzScheduler();
+ // return;
+ // } catch (Exception e) {
+ // e.printStackTrace();
+ // throw new RuntimeException(e);
+ // }
+ // }
+ //
+ // public void unprepareScheduler() throws Exception {
+ // unprepareScheduler(false);
+ // }
+ //
+ // public void unprepareScheduler(boolean beanOnly) throws Exception {
+ // if (schedulerService != null) {
+ // schedulerService.stop();
+ // if (beanOnly) {
+ // MBeanServer mbs = getJBossMBeanServer();
+ // if (mbs.isRegistered(SchedulerServiceMBean.SCHEDULER_MBEAN_NAME)) {
+ // getJBossMBeanServer().unregisterMBean(SchedulerServiceMBean.SCHEDULER_MBEAN_NAME);
+ // }
+ // } else {
+ // releaseJBossMBeanServer();
+ // }
+ //
+ // schedulerService = null;
+ // }
+ // }
+ //
+ // public PluginDeploymentScannerMBean getPluginScannerService() {
+ // return pluginScannerService;
+ // }
+ //
+ // protected void preparePluginScannerService() {
+ // preparePluginScannerService(null);
+ // }
+ //
+ // public void preparePluginScannerService(PluginDeploymentScannerMBean scannerService) {
+ // try {
+ // if (scannerService == null) {
+ // scannerService = new PluginDeploymentScanner();
+ // }
+ // MBeanServer mbs = getJBossMBeanServer();
+ // mbs.registerMBean(scannerService, PluginDeploymentScannerMBean.OBJECT_NAME);
+ // pluginScannerService = scannerService;
+ // return;
+ // } catch (Exception e) {
+ // e.printStackTrace();
+ // throw new RuntimeException(e);
+ // }
+ // }
+ //
+ // public void unpreparePluginScannerService() throws Exception {
+ // unpreparePluginScannerService(false);
+ // }
+ //
+ // public void unpreparePluginScannerService(boolean beanOnly) throws Exception {
+ // if (pluginScannerService != null) {
+ // pluginScannerService.stop();
+ // if (beanOnly) {
+ // MBeanServer mbs = getJBossMBeanServer();
+ // if (mbs.isRegistered(PluginDeploymentScannerMBean.OBJECT_NAME)) {
+ // getJBossMBeanServer().unregisterMBean(PluginDeploymentScannerMBean.OBJECT_NAME);
+ // }
+ // } else {
+ // releaseJBossMBeanServer();
+ // }
+ //
+ // pluginScannerService = null;
+ // }
+ // }
+ //
+ // protected void executeInTransaction(TransactionCallback callback) {
+ // executeInTransaction(callback);
+ // }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StandardServerPluginService.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StandardServerPluginService.java
new file mode 100644
index 0000000..5f5692f
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StandardServerPluginService.java
@@ -0,0 +1,103 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.test;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+import org.rhq.enterprise.server.plugin.pc.alert.AlertServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.bundle.BundleServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.content.PackageTypeServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.generic.GenericServerPluginContainer;
+
+/**
+ * An MBean to use as a ServerPluginService for tests that actually don't care
+ * about the server plugin services but need the server to have the server plugin
+ * infrastructure started up.
+ *
+ * @author Lukas Krejci
+ */
+public class StandardServerPluginService extends ServerPluginService implements StandardServerPluginServiceMBean {
+
+ private static final Log LOG = LogFactory.getLog(StandardServerPluginService.class);
+
+ public static class TestMasterServerPluginContainer extends MasterServerPluginContainer {
+ private List<AbstractTypeServerPluginContainer> serverPluginContainers = new ArrayList<AbstractTypeServerPluginContainer>();
+
+ public TestMasterServerPluginContainer(
+ List<Class<? extends AbstractTypeServerPluginContainer>> pluginContainerClasses) {
+
+ for (Class<? extends AbstractTypeServerPluginContainer> cls : pluginContainerClasses) {
+ try {
+ Constructor<? extends AbstractTypeServerPluginContainer> ctor = cls
+ .getConstructor(MasterServerPluginContainer.class);
+ AbstractTypeServerPluginContainer container = ctor.newInstance(this);
+ serverPluginContainers.add(container);
+ } catch (Exception e) {
+ LOG.error("Failed to instantiate server plugin container class: " + cls.getName(), e);
+ }
+ }
+ }
+
+ @Override
+ protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
+ return serverPluginContainers;
+ }
+ }
+
+ // public so tests can directly set these
+ public TestMasterServerPluginContainer master;
+ public MasterServerPluginContainerConfiguration masterConfig;
+
+ /**
+ * This list contains all the standard server plugin container classes by default.
+ * Modify it before the master plugin container is started, if you don't want
+ * some of these deployed or if you want to supply a custom one tailored for your test.
+ */
+ public List<Class<? extends AbstractTypeServerPluginContainer>> pluginContainerClasses;
+
+ public StandardServerPluginService() {
+ File dir = new File(System.getProperty("java.io.tmpdir"), "test-server-plugins");
+ this.masterConfig = new MasterServerPluginContainerConfiguration(dir, dir, dir, null);
+ pluginContainerClasses = new ArrayList<Class<? extends AbstractTypeServerPluginContainer>>();
+ pluginContainerClasses.add(AlertServerPluginContainer.class);
+ pluginContainerClasses.add(BundleServerPluginContainer.class);
+ pluginContainerClasses.add(ContentServerPluginContainer.class);
+ pluginContainerClasses.add(GenericServerPluginContainer.class);
+ pluginContainerClasses.add(PackageTypeServerPluginContainer.class);
+ }
+
+ @Override
+ protected MasterServerPluginContainer createMasterPluginContainer() {
+ this.master = new TestMasterServerPluginContainer(pluginContainerClasses);
+ this.master.initialize(this.masterConfig);
+ return this.master;
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StandardServerPluginServiceMBean.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StandardServerPluginServiceMBean.java
new file mode 100644
index 0000000..eff1ae6
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StandardServerPluginServiceMBean.java
@@ -0,0 +1,31 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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.test;
+
+import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceMBean;
+
+/**
+ * A generic MBean interface for tests that need a ServerPluginService setup.
+ *
+ * @author Lukas Krejci
+ */
+public interface StandardServerPluginServiceMBean extends ServerPluginServiceMBean {
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java
new file mode 100644
index 0000000..010c64b
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java
@@ -0,0 +1,378 @@
+/*
+ * 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.enterprise.server.test;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+import org.rhq.common.drift.Headers;
+import org.rhq.core.clientapi.agent.PluginContainerException;
+import org.rhq.core.clientapi.agent.bundle.BundleAgentService;
+import org.rhq.core.clientapi.agent.bundle.BundlePurgeRequest;
+import org.rhq.core.clientapi.agent.bundle.BundlePurgeResponse;
+import org.rhq.core.clientapi.agent.bundle.BundleScheduleRequest;
+import org.rhq.core.clientapi.agent.bundle.BundleScheduleResponse;
+import org.rhq.core.clientapi.agent.configuration.ConfigurationAgentService;
+import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
+import org.rhq.core.clientapi.agent.content.ContentAgentService;
+import org.rhq.core.clientapi.agent.discovery.DiscoveryAgentService;
+import org.rhq.core.clientapi.agent.discovery.InvalidPluginConfigurationClientException;
+import org.rhq.core.clientapi.agent.drift.DriftAgentService;
+import org.rhq.core.clientapi.agent.inventory.CreateResourceRequest;
+import org.rhq.core.clientapi.agent.inventory.CreateResourceResponse;
+import org.rhq.core.clientapi.agent.inventory.DeleteResourceRequest;
+import org.rhq.core.clientapi.agent.inventory.DeleteResourceResponse;
+import org.rhq.core.clientapi.agent.inventory.ResourceFactoryAgentService;
+import org.rhq.core.clientapi.agent.measurement.MeasurementAgentService;
+import org.rhq.core.clientapi.agent.operation.CancelResults;
+import org.rhq.core.clientapi.agent.operation.OperationAgentService;
+import org.rhq.core.clientapi.agent.support.SupportAgentService;
+import org.rhq.core.clientapi.server.configuration.ConfigurationUpdateResponse;
+import org.rhq.core.clientapi.server.content.ContentDiscoveryReport;
+import org.rhq.core.clientapi.server.content.DeletePackagesRequest;
+import org.rhq.core.clientapi.server.content.DeployPackagesRequest;
+import org.rhq.core.clientapi.server.content.RetrievePackageBitsRequest;
+import org.rhq.core.clientapi.server.discovery.InventoryReport;
+import org.rhq.core.communications.command.annotation.Asynchronous;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.content.transfer.DeployPackageStep;
+import org.rhq.core.domain.content.transfer.ResourcePackageDetails;
+import org.rhq.core.domain.discovery.AvailabilityReport;
+import org.rhq.core.domain.discovery.MergeResourceResponse;
+import org.rhq.core.domain.discovery.ResourceSyncInfo;
+import org.rhq.core.domain.drift.DriftDefinition;
+import org.rhq.core.domain.drift.DriftFile;
+import org.rhq.core.domain.drift.DriftSnapshot;
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.measurement.MeasurementData;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.domain.measurement.ResourceMeasurementScheduleRequest;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.agentclient.AgentClient;
+
+public class TestAgentClient implements AgentClient, BundleAgentService, DriftAgentService, ContentAgentService,
+ ResourceFactoryAgentService, ConfigurationAgentService, DiscoveryAgentService, MeasurementAgentService,
+ OperationAgentService, SupportAgentService {
+ private final Agent agent;
+ private final TestServerCommunicationsService commService;
+
+ public TestAgentClient(Agent agent, TestServerCommunicationsService commService) {
+ this.agent = agent;
+ this.commService = commService;
+ }
+
+ @Override
+ public Agent getAgent() {
+ return this.agent;
+ }
+
+ @Override
+ public BundleAgentService getBundleAgentService() {
+ return (commService.bundleService != null) ? commService.bundleService : this;
+ }
+
+ @Override
+ public ContentAgentService getContentAgentService() {
+ return (commService.contentService != null) ? commService.contentService : this;
+ }
+
+ @Override
+ public ResourceFactoryAgentService getResourceFactoryAgentService() {
+ return (commService.resourceFactoryService != null) ? commService.resourceFactoryService : this;
+ }
+
+ @Override
+ public ConfigurationAgentService getConfigurationAgentService() {
+ return (commService.configurationService != null) ? commService.configurationService : this;
+ }
+
+ @Override
+ public DiscoveryAgentService getDiscoveryAgentService() {
+ return (commService.discoveryService != null) ? commService.discoveryService : this;
+ }
+
+ @Override
+ public MeasurementAgentService getMeasurementAgentService() {
+ return (commService.measurementService != null) ? commService.measurementService : this;
+ }
+
+ @Override
+ public OperationAgentService getOperationAgentService() {
+ return (commService.operationService != null) ? commService.operationService : this;
+ }
+
+ @Override
+ public SupportAgentService getSupportAgentService() {
+ return (commService.supportService != null) ? commService.supportService : this;
+ }
+
+ @Override
+ public void startSending() {
+ return; // no-op
+ }
+
+ @Override
+ public void stopSending() {
+ return; // no-op
+ }
+
+ @Override
+ public boolean ping(long timeoutMillis) {
+ return true;
+ }
+
+ // provide no-ops for all agent services
+
+ @Override
+ public Set<MeasurementData> getRealTimeMeasurementValue(int resourceId, Set<MeasurementScheduleRequest> requests) {
+ return null;
+ }
+
+ @Override
+ public void scheduleCollection(Set<ResourceMeasurementScheduleRequest> resourceSchedules) {
+ }
+
+ @Override
+ public void unscheduleCollection(Set<Integer> resourceIds) {
+ }
+
+ @Override
+ public void updateCollection(Set<ResourceMeasurementScheduleRequest> resourceSchedules) {
+ }
+
+ @Override
+ public Map<String, Object> getMeasurementScheduleInfoForResource(int resourceId) {
+ return null;
+ }
+
+ @Override
+ public ConfigurationUpdateResponse executeUpdateResourceConfigurationImmediately(ConfigurationUpdateRequest request)
+ throws PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public Configuration loadResourceConfiguration(int resourceId) throws PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public Configuration merge(Configuration configuration, int resourceId, boolean fromStructured)
+ throws PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public void updateResourceConfiguration(ConfigurationUpdateRequest request) {
+ }
+
+ @Override
+ public CancelResults cancelOperation(String jobId) {
+ return null;
+ }
+
+ @Override
+ public void invokeOperation(String jobId, int resourceId, String operationName, Configuration parameters)
+ throws PluginContainerException {
+ }
+
+ @Override
+ public void deletePackages(DeletePackagesRequest request) {
+ }
+
+ @Override
+ public void deployPackages(DeployPackagesRequest request) {
+ }
+
+ @Override
+ public ContentDiscoveryReport executeResourcePackageDiscoveryImmediately(int resourceId, String packageTypeName)
+ throws PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public Set<ResourcePackageDetails> getLastDiscoveredResourcePackages(int resourceId) {
+ return null;
+ }
+
+ @Override
+ public void retrievePackageBits(RetrievePackageBitsRequest request) {
+ }
+
+ @Override
+ public List<DeployPackageStep> translateInstallationSteps(int resourceId, ResourcePackageDetails packageDetails)
+ throws PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public void disableServiceScans(int serverResourceId) {
+ }
+
+ @Override
+ public void enableServiceScans(int serverResourceId, Configuration config) {
+ }
+
+ @Override
+ public AvailabilityReport executeAvailabilityScanImmediately(boolean changedOnlyReport) {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public InventoryReport executeServerScanImmediately() throws PluginContainerException {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public InventoryReport executeServiceScanImmediately() throws PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public void executeServiceScanDeferred() {
+ return;
+ }
+
+ @Override
+ public Availability getCurrentAvailability(Resource resource) {
+ return null;
+ }
+
+ @Override
+ public Resource getPlatform() {
+ return null;
+ }
+
+ @Override
+ public MergeResourceResponse manuallyAddResource(ResourceType resourceType, int parentResourceId,
+ Configuration pluginConfiguration, int creatorSubjectId) throws InvalidPluginConfigurationClientException,
+ PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public void uninventoryResource(int resourceId) {
+ }
+
+ @Override
+ public void updatePluginConfiguration(int resourceId, Configuration newPluginConfiguration)
+ throws InvalidPluginConfigurationClientException, PluginContainerException {
+ }
+
+ @Asynchronous(guaranteedDelivery = true)
+ @Override
+ public void synchronizeInventory(ResourceSyncInfo syncInfo) {
+ return;
+ }
+
+ @Override
+ public void createResource(CreateResourceRequest request) throws PluginContainerException {
+ }
+
+ @Override
+ public void deleteResource(DeleteResourceRequest request) throws PluginContainerException {
+ }
+
+ @Override
+ public CreateResourceResponse executeCreateResourceImmediately(CreateResourceRequest request)
+ throws PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public DeleteResourceResponse executeDeleteResourceImmediately(DeleteResourceRequest request)
+ throws PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public InputStream getSnapshotReport(int resourceId, String name, String description) throws Exception {
+ return null;
+ }
+
+ @Override
+ public Configuration validate(Configuration configuration, int resourceId, boolean isStructured)
+ throws PluginContainerException {
+ return null;
+ }
+
+ @Override
+ public BundleScheduleResponse schedule(BundleScheduleRequest request) {
+ return new BundleScheduleResponse();
+ }
+
+ @Override
+ public BundlePurgeResponse purge(BundlePurgeRequest request) {
+ return new BundlePurgeResponse();
+ }
+
+ @Override
+ public DriftAgentService getDriftAgentService() {
+ return (commService.driftService != null) ? commService.driftService : this;
+ }
+
+ @Override
+ public boolean requestDriftFiles(int resourceId, Headers headers, List<? extends DriftFile> driftFiles) {
+ return false;
+ }
+
+ @Override
+ public void scheduleDriftDetection(int resourceId, DriftDefinition driftDefinition) {
+ }
+
+ @Override
+ public void detectDrift(int resourceId, DriftDefinition driftDefinition) {
+ }
+
+ @Override
+ public void unscheduleDriftDetection(int resourceId, DriftDefinition driftDefinition) {
+ }
+
+ @Override
+ public void updateDriftDetection(int resourceId, DriftDefinition driftDefinition) {
+ }
+
+ @Override
+ public void updateDriftDetection(int resourceId, DriftDefinition driftDef, DriftSnapshot driftSnapshot) {
+ }
+
+ @Override
+ public void ackChangeSet(int resourceId, String driftDefName) {
+ }
+
+ @Override
+ public void ackChangeSetContent(int resourceId, String driftDefName, String token) {
+ }
+
+ @Override
+ public void pinSnapshot(int resourceId, String configName, DriftSnapshot snapshot) {
+ }
+
+ @Override
+ public void requestFullAvailabilityReport() {
+ return;
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerCommunicationsService.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerCommunicationsService.java
new file mode 100644
index 0000000..0a1c625
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerCommunicationsService.java
@@ -0,0 +1,248 @@
+/*
+ * 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.enterprise.server.test;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.jboss.remoting.InvokerLocator;
+
+import org.rhq.core.clientapi.agent.bundle.BundleAgentService;
+import org.rhq.core.clientapi.agent.configuration.ConfigurationAgentService;
+import org.rhq.core.clientapi.agent.content.ContentAgentService;
+import org.rhq.core.clientapi.agent.discovery.DiscoveryAgentService;
+import org.rhq.core.clientapi.agent.drift.DriftAgentService;
+import org.rhq.core.clientapi.agent.inventory.ResourceFactoryAgentService;
+import org.rhq.core.clientapi.agent.measurement.MeasurementAgentService;
+import org.rhq.core.clientapi.agent.operation.OperationAgentService;
+import org.rhq.core.clientapi.agent.support.SupportAgentService;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.enterprise.communications.ServiceContainer;
+import org.rhq.enterprise.communications.command.server.CommandProcessorMetrics.Calltime;
+import org.rhq.enterprise.server.agentclient.AgentClient;
+import org.rhq.enterprise.server.core.comm.ServerConfiguration;
+
+/**
+ * Our test server comm service MBean, which mimics the same interface as the real service but provides some dummy agent
+ * clients. Tests should have access to this service instance and should set one or more of the public fields that
+ * define what the test services should be.
+ */
+public class TestServerCommunicationsService implements TestServerCommunicationsServiceMBean {
+ public BundleAgentService bundleService;
+ public ContentAgentService contentService;
+ public DriftAgentService driftService;
+ public ResourceFactoryAgentService resourceFactoryService;
+ public ConfigurationAgentService configurationService;
+ public DiscoveryAgentService discoveryService;
+ public MeasurementAgentService measurementService;
+ public OperationAgentService operationService;
+ public SupportAgentService supportService;
+
+ protected Map<Agent, AgentClient> agentClients = new HashMap<Agent, AgentClient>();
+
+ public TestServerCommunicationsService() {
+ }
+
+ public AgentClient getKnownAgentClient(Agent agent) {
+ AgentClient testClient = new TestAgentClient(agent, this);
+ agentClients.put(agent, testClient);
+ return testClient;
+ }
+
+ public void destroyKnownAgentClient(Agent agent) {
+ agentClients.remove(agent);
+ }
+
+ public List<InvokerLocator> getAllKnownAgents() {
+ return null;
+ }
+
+ public void addStartedAgent(Agent agent) {
+ }
+
+ public void removeDownedAgent(String endpoint) {
+ }
+
+ public boolean pingEndpoint(String endpoint, long timeoutMillis) {
+ return true;
+ }
+
+ public Integer getGlobalConcurrencyLimit() {
+ return 1;
+ }
+
+ public void setGlobalConcurrencyLimit(Integer maxConcurrency) {
+ }
+
+ public Integer getInventoryReportConcurrencyLimit() {
+ return 1;
+ }
+
+ public void setInventoryReportConcurrencyLimit(Integer maxConcurrency) {
+ }
+
+ public Integer getAvailabilityReportConcurrencyLimit() {
+ return 1;
+ }
+
+ public void setAvailabilityReportConcurrencyLimit(Integer maxConcurrency) {
+ }
+
+ public Integer getInventorySyncConcurrencyLimit() {
+ return 1;
+ }
+
+ public void setInventorySyncConcurrencyLimit(Integer maxConcurrency) {
+ }
+
+ public Integer getContentReportConcurrencyLimit() {
+ return 1;
+ }
+
+ public void setContentReportConcurrencyLimit(Integer maxConcurrency) {
+ }
+
+ public Integer getContentDownloadConcurrencyLimit() {
+ return 1;
+ }
+
+ public void setContentDownloadConcurrencyLimit(Integer maxConcurrency) {
+ }
+
+ public Integer getMeasurementReportConcurrencyLimit() {
+ return 1;
+ }
+
+ public void setMeasurementReportConcurrencyLimit(Integer maxConcurrency) {
+ }
+
+ public Integer getMeasurementScheduleRequestConcurrencyLimit() {
+ return 1;
+ }
+
+ public void setMeasurementScheduleRequestConcurrencyLimit(Integer maxConcurrency) {
+ }
+
+ public Boolean getMaintenanceModeAtStartup() {
+ return Boolean.FALSE;
+ }
+
+ public Boolean isMaintenanceModeAtStartup() {
+ return Boolean.FALSE;
+ }
+
+ public void setMaintenanceModeAtStartup(Boolean flag) {
+ }
+
+ public void clear() {
+ }
+
+ public long getNumberDroppedCommandsReceived() {
+ return 0;
+ }
+
+ public long getNumberNotProcessedCommandsReceived() {
+ return 0;
+ }
+
+ public long getNumberFailedCommandsReceived() {
+ return 0;
+ }
+
+ public long getNumberSuccessfulCommandsReceived() {
+ return 0;
+ }
+
+ public long getNumberTotalCommandsReceived() {
+ return 0;
+ }
+
+ public long getAverageExecutionTimeReceived() {
+ return 0;
+ }
+
+ public Map<String, Calltime> getCallTimeDataReceived() {
+ return null;
+ }
+
+ public ServerConfiguration getConfiguration() {
+ return null;
+ }
+
+ public String getConfigurationFile() {
+ return null;
+ }
+
+ public Properties getConfigurationOverrides() {
+ return null;
+ }
+
+ public String getPreferencesNodeName() {
+ return null;
+ }
+
+ public ServiceContainer getServiceContainer() {
+ return new MockServiceContainer();
+ }
+
+ public ServiceContainer safeGetServiceContainer() {
+ return new MockServiceContainer();
+ }
+
+ public String getStartedServerEndpoint() {
+ return "http://TestServerCommunicationsService";
+ }
+
+ public ServerConfiguration reloadConfiguration() throws Exception {
+ return null;
+ }
+
+ public void setConfigurationFile(String location) {
+ }
+
+ public String getConfigurationOverridesFile() {
+ return null;
+ }
+
+ public void setConfigurationOverridesFile(String f) {
+ }
+
+ public void setPreferencesNodeName(String node) {
+ }
+
+ public void startCommunicationServices() throws Exception {
+ }
+
+ public void stop() throws Exception {
+ }
+
+ public boolean isStarted() {
+ return true;
+ }
+
+ private class MockServiceContainer extends ServiceContainer {
+ @Override
+ public Long addRemoteInputStream(InputStream in) throws Exception {
+ return new Long(1);
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerCommunicationsServiceMBean.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerCommunicationsServiceMBean.java
new file mode 100644
index 0000000..f172bf1
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerCommunicationsServiceMBean.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.enterprise.server.test;
+
+import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceMBean;
+
+/**
+ * Our test server comm service mimics the real one.
+ *
+ * @author John Mazzitelli
+ */
+public interface TestServerCommunicationsServiceMBean extends ServerCommunicationsServiceMBean {
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
new file mode 100644
index 0000000..c28256b
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
@@ -0,0 +1,113 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 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.test;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.rhq.core.domain.plugin.PluginKey;
+import org.rhq.core.domain.plugin.ServerPlugin;
+import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginManager;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+import org.rhq.enterprise.server.plugin.pc.drift.DriftServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.drift.DriftServerPluginManager;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
+
+public class TestServerPluginService extends ServerPluginService implements TestServerPluginServiceMBean {
+
+ public TestMasterServerPluginContainer master;
+ public MasterServerPluginContainerConfiguration masterConfig;
+
+ public TestServerPluginService() {
+ // build the config at constructor time so tests have it even before the PC is initialized
+ File dir = new File(System.getProperty("java.io.tmpdir"), "test-server-plugins");
+ this.masterConfig = new MasterServerPluginContainerConfiguration(dir, dir, dir, null);
+ }
+
+ @Override
+ public MasterServerPluginContainer createMasterPluginContainer() {
+ this.master = new TestMasterServerPluginContainer();
+ this.master.initialize(this.masterConfig);
+ return this.master;
+ }
+
+ class TestMasterServerPluginContainer extends MasterServerPluginContainer {
+ @Override
+ protected ClassLoader createRootServerPluginClassLoader() {
+ return getClass().getClassLoader();
+ }
+
+ @Override
+ protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ protected List<PluginKey> getDisabledPluginKeys() {
+ // in the real world, the db is checked for enable flag, here we say all plugins are enabled
+ return new ArrayList<PluginKey>();
+ }
+
+ @Override
+ protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
+ ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(1);
+ DriftServerPluginContainer driftPC = new TestDriftServerPluginContainer(this);
+ pcs.add(driftPC);
+
+ return pcs;
+ }
+ }
+
+ class TestDriftServerPluginContainer extends DriftServerPluginContainer {
+ public TestDriftServerPluginContainer(MasterServerPluginContainer master) {
+ super(master);
+ }
+
+ @Override
+ protected ServerPluginManager createPluginManager() {
+ return new TestDriftServerPluginManager(this);
+ }
+ }
+
+ class TestDriftServerPluginManager extends DriftServerPluginManager {
+ public TestDriftServerPluginManager(DriftServerPluginContainer pc) {
+ super(pc);
+ }
+
+ @Override
+ public Collection<ServerPluginEnvironment> getPluginEnvironments() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ protected ServerPlugin getPlugin(ServerPluginEnvironment env) {
+ return null;
+ }
+ }
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerPluginServiceMBean.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerPluginServiceMBean.java
new file mode 100644
index 0000000..a0310a5
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestServerPluginServiceMBean.java
@@ -0,0 +1,25 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 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.test;
+
+import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceMBean;
+
+public interface TestServerPluginServiceMBean extends ServerPluginServiceMBean {
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TransactionCallback.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TransactionCallback.java
new file mode 100644
index 0000000..cec66cb
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TransactionCallback.java
@@ -0,0 +1,7 @@
+package org.rhq.enterprise.server.test;
+
+public interface TransactionCallback {
+
+ void execute() throws Exception;
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TransactionCallbackReturnable.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TransactionCallbackReturnable.java
new file mode 100644
index 0000000..cd0389e
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TransactionCallbackReturnable.java
@@ -0,0 +1,7 @@
+package org.rhq.enterprise.server.test;
+
+public interface TransactionCallbackReturnable<T extends Object> {
+
+ T execute() throws Exception;
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/ldap/FakeLdapContext.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/ldap/FakeLdapContext.java
new file mode 100644
index 0000000..dad31ce
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/ldap/FakeLdapContext.java
@@ -0,0 +1,2950 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 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.test.ldap;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NameClassPair;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.Control;
+import javax.naming.ldap.ExtendedRequest;
+import javax.naming.ldap.ExtendedResponse;
+import javax.naming.ldap.LdapContext;
+
+import org.rhq.enterprise.server.resource.group.LDAPStringUtil;
+
+/**
+ * A fake implementation of {@link LdapContext} which can be used for LDAP
+ * unit testing.
+ *
+ * @author loleary
+ *
+ */
+public class FakeLdapContext implements LdapContext {
+
+ FakeLdapContext.LdapSearchTestData ldapTestData = new LdapSearchTestData();
+
+ @Override
+ public NamingEnumeration<SearchResult> search(String name, String filter, SearchControls cons)
+ throws NamingException {
+ Hashtable<String, String> attributes = new Hashtable<String, String>();
+
+ if (name != null && name.length() > 0) {
+ attributes.put("baseName", name);
+ }
+
+ /*
+ * simple parse of filter
+ * We treat everything like an &
+ * We do not handle wildcards
+ */
+ if (filter != null) {
+ int idxLP = -1; // Left Parenthesis
+ int idxEq = -1; // Equal sign
+ int idxRP = -1; // Right Parenthesis
+ while (idxLP < filter.length() && idxRP < filter.length()) {
+ idxLP = filter.indexOf('(', idxLP + 1);
+ if (idxLP > -1 && idxLP + 1 < filter.length()) {
+ if (filter.charAt(idxLP + 1) == '&') {
+ idxLP++;
+ continue;
+ }
+ idxEq = filter.indexOf('=', idxLP + 1);
+ }
+ if (idxEq > -1 && idxEq + 1 < filter.length())
+ idxRP = filter.indexOf(')', idxEq + 1);
+ if (idxLP > -1 && idxEq > idxLP && idxRP > idxEq) {
+ String attrName = filter.substring(idxLP + 1, idxEq);
+ String attrValue = filter.substring(idxEq + 1, idxRP);
+ attributes.put(attrName, attrValue);
+ } else {
+ idxRP = filter.length();
+ }
+ }
+ }
+
+ try {
+ return new FakeNamingEnumeration<SearchResult>(ldapTestData.getSearchResults(attributes));
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ public FakeLdapContext() throws NamingException {
+ super();
+ //System.out.println("------------------------------------------------");
+ //System.out.println(FakeLdapContext.class.getCanonicalName() + " initialized");
+ //System.out.println("------------------------------------------------");
+ }
+
+ @Override
+ public void bind(Name arg0, Object arg1, Attributes arg2) throws NamingException {
+ }
+
+ @Override
+ public void bind(String arg0, Object arg1, Attributes arg2) throws NamingException {
+ }
+
+ @Override
+ public DirContext createSubcontext(Name arg0, Attributes arg1) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public DirContext createSubcontext(String arg0, Attributes arg1) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Attributes getAttributes(Name arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Attributes getAttributes(String arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Attributes getAttributes(Name arg0, String[] arg1) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Attributes getAttributes(String arg0, String[] arg1) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public DirContext getSchema(Name arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public DirContext getSchema(String arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public DirContext getSchemaClassDefinition(Name arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public DirContext getSchemaClassDefinition(String arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public void modifyAttributes(Name arg0, ModificationItem[] arg1) throws NamingException {
+ }
+
+ @Override
+ public void modifyAttributes(String arg0, ModificationItem[] arg1) throws NamingException {
+ }
+
+ @Override
+ public void modifyAttributes(Name arg0, int arg1, Attributes arg2) throws NamingException {
+ }
+
+ @Override
+ public void modifyAttributes(String arg0, int arg1, Attributes arg2) throws NamingException {
+ }
+
+ @Override
+ public void rebind(Name arg0, Object arg1, Attributes arg2) throws NamingException {
+ }
+
+ @Override
+ public void rebind(String arg0, Object arg1, Attributes arg2) throws NamingException {
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(Name arg0, Attributes arg1) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(String arg0, Attributes arg1) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(Name arg0, Attributes arg1, String[] arg2) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(String arg0, Attributes arg1, String[] arg2) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(Name arg0, String arg1, SearchControls arg2) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(Name arg0, String arg1, Object[] arg2, SearchControls arg3)
+ throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<SearchResult> search(String arg0, String arg1, Object[] arg2, SearchControls arg3)
+ throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Object addToEnvironment(String arg0, Object arg1) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public void bind(Name arg0, Object arg1) throws NamingException {
+ }
+
+ @Override
+ public void bind(String arg0, Object arg1) throws NamingException {
+ }
+
+ @Override
+ public void close() throws NamingException {
+
+ }
+
+ @Override
+ public Name composeName(Name arg0, Name arg1) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public String composeName(String arg0, String arg1) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Context createSubcontext(Name arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Context createSubcontext(String arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public void destroySubcontext(Name arg0) throws NamingException {
+ }
+
+ @Override
+ public void destroySubcontext(String arg0) throws NamingException {
+ }
+
+ @Override
+ public Hashtable<?, ?> getEnvironment() throws NamingException {
+ return null;
+ }
+
+ @Override
+ public String getNameInNamespace() throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NameParser getNameParser(Name arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NameParser getNameParser(String arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<NameClassPair> list(Name arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<NameClassPair> list(String arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<Binding> listBindings(Name arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public NamingEnumeration<Binding> listBindings(String arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Object lookup(Name arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Object lookup(String arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Object lookupLink(Name arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Object lookupLink(String arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public void rebind(Name arg0, Object arg1) throws NamingException {
+ }
+
+ @Override
+ public void rebind(String arg0, Object arg1) throws NamingException {
+ }
+
+ @Override
+ public Object removeFromEnvironment(String arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public void rename(Name arg0, Name arg1) throws NamingException {
+ }
+
+ @Override
+ public void rename(String arg0, String arg1) throws NamingException {
+ }
+
+ @Override
+ public void unbind(Name arg0) throws NamingException {
+ }
+
+ @Override
+ public void unbind(String arg0) throws NamingException {
+ }
+
+ @Override
+ public ExtendedResponse extendedOperation(ExtendedRequest arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Control[] getConnectControls() throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Control[] getRequestControls() throws NamingException {
+ return null;
+ }
+
+ @Override
+ public Control[] getResponseControls() throws NamingException {
+ return null;
+ }
+
+ @Override
+ public LdapContext newInstance(Control[] arg0) throws NamingException {
+ return null;
+ }
+
+ @Override
+ public void reconnect(Control[] arg0) throws NamingException {
+ }
+
+ @Override
+ public void setRequestControls(Control[] arg0) throws NamingException {
+ }
+
+ /**
+ * Test data that is returned as LDAP search results based on simple queries.
+ *
+ * @author loleary
+ *
+ */
+ public class LdapSearchTestData extends ArrayList<SearchResult> {
+
+ private static final long serialVersionUID = -1751409714032152844L;
+
+ public LdapSearchTestData() {
+ super();
+ Attribute attr = null;
+ Attributes attrs = null;
+ SearchResult sr = null;
+
+ // dn: dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("dcObject");
+ attr.add("organization");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("dc");
+ attr.add("test-rhq");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("Test directory for RHQ from Red Hat, Inc. Directory should contain entries that can be used to test LDAP integration between RHQ Server and a compatible LDAP server implementation. ");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("o");
+ attr.add("Test RHQ directory");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("dc=test,dc=rhq,dc=redhat,dc=com", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: ou=groups,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalUnit");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("groups");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("All groups which can be used for testing RHQ role/group mappings.");
+ attrs.put(attr);
+
+ sr = new SearchResult("groups", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalUnit");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("people");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("All users which can be used for testing RHQ user authentication and authorizations.");
+ attrs.put(attr);
+
+ sr = new SearchResult("people", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=RHQ Admin Group,ou=groups,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("groupOfNames");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("RHQ administrators group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("member");
+ attr.add("cn=Robert Smith,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Cannon\\, Brett,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Charles H\\\\Samlin,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Craig \\#1 Sellers,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Beverly \\+1 Balanger,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Bethany \\<Stuart\\> Wallace,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Zachory S\\; Balanger,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Allen \\\"The Hammer\\\" Callen,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Sam Not \\= Smitherson,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=\\ Billy The Kiddough\\ ,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=System/Integration API,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Lee -Fast- Croutche,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Samantha *Won't Quit* Jeopardy,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Brad (The Eagle) Strafford,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Michal M\u011Bchura,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ sr = new SearchResult("RHQ Admin Group", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=JBoss Admin Group,ou=groups,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("groupOfNames");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("Group that administers and manages JBoss servers and applications");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("member");
+ attr.add("cn=John Smith,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Dr. Greg Hause\\, MD,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Cindy\\\\Cynthia Groober,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Biff \\# Rogers,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Steven \\+2 Reed,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Lisa \\<The Great\\> Toller,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Homer J Simpsonite\\; III,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Jessica \\\"Crouching Tiger\\\" Mathers,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Hope \\= Rein,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=\\ Sue Ferguson\\ ,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Phil/Susan Carlson,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Sally -Ainte- Mathers,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Lee *Fast* Croutche,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Kimberly (Six Toe) Krawford,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=We\u00F1dy Sequerl,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ sr = new SearchResult("JBoss Admin Group", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=JBoss Monitor Group,ou=groups,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("groupOfNames");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("Group that monitors JBoss servers and applications");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("member");
+ attr.add("cn=Sheri Smith,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Walsh\\, Brad,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Jim\\\\James Kirk,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Sandra \\# Phillips,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=William Tell Overture \\+1,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Craig \\<Bison\\> Allen,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Walter T Fredrick\\; The Second,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Stanley \\\"Short\\\" Mein,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Noah \\= Sadler,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=\\ Stuart Smiley\\ ,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=System/Integration API 2,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Samantha -Won't Quit- Jeopardy,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Sally *Ainte* Mathers,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Jeff (Top Hat) Wilbright,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attr.add("cn=Phillip Br\u00E3dy,ou=users,dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ sr = new SearchResult("JBoss Monitor Group", null, null, attrs, true);
+ this.add(sr);
+
+ // dn "cn=Robert Smith,ou=users,dc=test,dc=rhq,dc=redhat,dc=com"
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("rjosmith");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Smith");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("robert.smith(a)rhq.redhat.com");
+ attr.add("bob.smith(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-111-2222");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Robert Smith");
+ attr.add("Robert J Smith");
+ attr.add("Bob Smith");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("telephonenumber");
+ attr.add("555-555-1212");
+ attr.add("212");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("swell guy");
+ attr.add("Simple user in the RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("carlicense");
+ attr.add("HISCAR 123");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Robert Smith,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=John Smith,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("John Smith");
+ attr.add("John J Smith");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Smith");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("carlicense");
+ attr.add("HISCAR 124");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-111-2223");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("j.smith(a)rhq.redhat.com");
+ attr.add("jsmith(a)rhq.redhat.com");
+ attr.add("john.smith(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("jsmith");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("Simple user in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=John Smith,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Sheri Smith,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Sheri Smith");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Smith");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("carlicense");
+ attr.add("HERCAR 125");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-111-2225");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("s.smith(a)rhq.redhat.com");
+ attr.add("ssmith(a)rhq.redhat.com");
+ attr.add("sheri.smith(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("ssmith");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("Simple user in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Sheri Smith,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Cannon\, Brett,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Cannon, Brett");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Cannon");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1212");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("bcannon(a)rhq.redhat.com");
+ attr.add("brett.cannon(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("bcannon");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with comma (,) in 'cn' in the RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Cannon\\, Brett,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Dr. Greg Hause\, MD,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Dr. Greg Hause, MD");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Hause");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-2155");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("ghause(a)rhq.redhat.com");
+ attr.add("dr.feel.good(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("ghause");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with comma (,) in 'cn' in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Dr. Greg Hause\\, MD,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Walsh\, Brad,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Walsh, Brad");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Walsh");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1215");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("bwalsh(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("bwalsh");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with comma (,) in 'cn' in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Walsh\\, Brad,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Charles H\\Samlin,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Charles H\\Samlin");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("H\\Samlin");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1213");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("csamlin(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("csamlin");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with backslash (\\) in 'cn' in the RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Charles H\\\\Samlin,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Cindy\\Cynthia Groober,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Cindy\\Cynthia Groober");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Groober");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1214");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("cgroober(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("cgroober");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with backslash (\\) in 'cn' in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Cindy\\\\Cynthia Groober,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Jim\\James Kirk,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Jim\\James Kirk");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Kirk");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1215");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("jkirk(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("jkirk");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with backslash (\\) in 'cn' in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Jim\\\\James Kirk,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Craig \#1 Sellers,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Craig #1 Sellers");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Sellers");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1216");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("csellers(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("csellers");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with hash-sign (#) in 'cn' in the RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Craig \\#1 Sellers,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Biff \# Rogers,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Biff # Rogers");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Rogers");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1217");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("brogers(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("brogers");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with hash-sign (#) in 'cn' in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Biff \\# Rogers,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Sandra \# Phillips,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Sandra \\# Phillips");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Phillips");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1218");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("sphillips(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("sphillips");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with hash-sign (#) in 'cn' in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Sandra \\# Phillips,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Beverly \+1 Balanger,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Beverly +1 Balanger");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Balanger");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1219");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("bbalanger(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("bbalanger");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with plus-sign (+) in 'cn' in the RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Beverly \\+1 Balanger,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Steven \+2 Reed,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Steven +2 Reed");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Reed");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1220");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("sreed(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("sreed");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with plus-sign (+) in 'cn' in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Steven \\+2 Reed,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=William Tell Overture \+1,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("William Tell Overture +1");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Overture");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1221");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("woverture(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("woverture");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with plus-sign (+) in 'cn' in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=William Tell Overture \\+1,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Bethany \<Stuart\> Wallace,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Bethany <Stuart> Wallace");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Wallace");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1222");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("bwallace(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("bwallace");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with less-than and greater-than sign (<>) in 'cn' in the RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Bethany \\<Stuart\\> Wallace,ou=users", "javax.naming.directory.DirContext",
+ null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Lisa \<The Great\> Toller,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Lisa <The Great> Toller");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Toller");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1223");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("ltoller(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("ltoller");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with less-than and greater-than sign (<>) in 'cn' in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Lisa \\<The Great\\> Toller,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Craig \<Bison\> Allen,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Craig <Bison> Allen");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Allen");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1224");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("callen(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("callen");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with less-than and greater-than sign (<>) in 'cn' in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Craig \\<Bison\\> Allen,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Zachory S\; Balanger,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Zachory S; Balanger");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Balanger");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1225");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("zbalanger(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("zbalanger");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with semi-colon (;) in 'cn' in the RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Zachory S\\; Balanger,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Homer J Simpsonite\; III,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Homer J Simpsonite; III");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Simpsonite");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1226");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("hsimpsonite(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("hsimpsonite");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with semi-colon (;) in 'cn' in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Homer J Simpsonite\\; III,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Walter T Fredrick\; The Second,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Walter T Fredrick; The Second");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Fredrick");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1227");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("wfredrick(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("wfredrick");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with semi-colon (;) in 'cn' in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Walter T Fredrick\\; The Second,ou=users", "javax.naming.directory.DirContext",
+ null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Allen \"The Hammer\" Callen,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Allen \"The Hammer\" Callen");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Callen");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1228");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("acallen(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("acallen");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with quote (\") in 'cn' in the RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Allen \\\"The Hammer\\\" Callen,ou=users", "javax.naming.directory.DirContext",
+ null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Jessica \"Crouching Tiger\" Mathers,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Jessica \"Crouching Tiger\" Mathers");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Simpsonite");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1229");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("jmathers(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("jmathers");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with quote (\") in 'cn' in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Jessica \\\"Crouching Tiger\\\" Mathers,ou=users",
+ "javax.naming.directory.DirContext", null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Stanley \"Short\" Mein,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Stanley \"Short\" Mein");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Mein");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1230");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("smein(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("smein");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with quote (\") in 'cn' in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Stanley \\\"Short\\\" Mein,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Sam Not \= Smitherson,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Sam Not = Smitherson");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Smitherson");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1231");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("ssmitherson(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("ssmitherson");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with equal-sign (=) in 'cn' in the RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Sam Not \\= Smitherson,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Hope \= Rein,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Hope = Rein");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Rein");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1232");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("hrein(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("hrein");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with equal-sign (=) in 'cn' in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Hope \\= Rein,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Noah \= Sadler,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Noah = Sadler");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Sadler");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1233");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("nsadler(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("nsadler");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with equal-sign (=) in 'cn' in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Noah \\= Sadler,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=\ Billy The Kiddough\ ,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add(" Billy The Kiddough ");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Kiddough");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1234");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("bkiddough(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("bkiddough");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with leading and trailing space ( ) in 'cn' in the RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=\\ Billy The Kiddough\\ ,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=\ Sue Ferguson\ ,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add(" Sue Ferguson ");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Ferguson");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1235");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("sferguson(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("sferguson");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with leading and trailing space ( ) in 'cn' in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=\\ Sue Ferguson\\ ,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=\ Stuart Smiley\ ,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add(" Stuart Smiley ");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Smiley");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1236");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("ssmiley(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("ssmiley");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with leading and trailing space ( ) in 'cn' in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=\\ Stuart Smiley\\ ,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=System/Integration API,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("System/Integration API");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("API");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("sysapi(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("sysapi");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with slash (/) in 'cn' in the RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=System/Integration API,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Phil/Susan Carlson,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Phil/Susan Carlson");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Carlson");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1238");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("pscarlson(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("pscarlson");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with slash (/) in 'cn' in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Phil/Susan Carlson,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=System/Integration API 2,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("System/Integration API 2");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("API");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("sysapi2(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("sysapi2");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with slash (/) in 'cn' in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=System/Integration API 2,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Lee -Fast- Croutche,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Lee -Fast- Croutche");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Croutche");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1243");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("lecroutche(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("lecroutche");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with hyphen (-) in 'cn', not to be confused with user with similar name in JBoss Admin Group, in the RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Lee -Fast- Croutche,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Sally -Ainte- Mathers,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Sally -Ainte- Mathers");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Mathers");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1244");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("samathers(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("samathers");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with hyphen (-) in 'cn', not to be confused with user with similar name in JBoss Monitor Group, in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Sally -Ainte- Mathers,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Samantha -Won't Quit- Jeopardy,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Samantha -Won't Quit- Jeopardy");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Jeopardy");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("gn");
+ attr.add("Samantha");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1245");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("sajeopardy(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("sajeopardy");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with hyphen (-) in 'cn', not to be confused with user with similar name in RHQ Admin Group, in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Samantha -Won't Quit- Jeopardy,ou=users", "javax.naming.directory.DirContext",
+ null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Samantha *Won't Quit* Jeopardy,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Samantha *Won't Quit* Jeopardy");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Jeopardy");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("gn");
+ attr.add("Samantha");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1246");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("sjeopardy(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("sjeopardy");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with asterisk (*) in 'cn', not to be confused with user with similar name in JBoss Monitor Group, in the RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Samantha *Won't Quit* Jeopardy,ou=users", "javax.naming.directory.DirContext",
+ null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Lee *Fast* Croutche,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Lee *Fast* Croutche");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Croutche");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1247");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("lcroutche(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("lcroutche");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with asterisk (*) in 'cn', not to be confused with user with similar name in RHQ Admin Group, in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Lee *Fast* Croutche,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Sally *Ainte* Mathers,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Sally *Ainte* Mathers");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Mathers");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1248");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("smathers(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("smathers");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with asterisk (*) in 'cn', not to be confused with user with similar name in JBoss Admin Group, in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Sally *Ainte* Mathers,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Brad (The Eagle) Strafford,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Brad (The Eagle) Strafford");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Strafford");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1249");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("bstrafford(a)rhq.redhat.com");
+ attr.add("the.eagle(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("bstrafford");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with parenthesis () in 'cn' in the RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Brad (The Eagle) Strafford,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Kimberly (Six Toe) Krawford,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Kimberly (Six Toe) Krawford");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Krawford");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1250");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("kkrawford(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("kkrawford");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with parenthesis () in 'cn' in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Kimberly (Six Toe) Krawford,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Jeff (Top Hat) Wilbright,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Jeff (Top Hat) Wilbright");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Wilbright");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-555-1251");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("jwilbright(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("jwilbright");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with parenthesis () in 'cn' in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Jeff (Top Hat) Wilbright,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Michal Měchura,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Michal Měchura");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("M\u011Bchura");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("gn");
+ attr.add("Michal");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-777-1212");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("mmechura(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("mmechura");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("RHQ Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with non-ASCII character (\u011B) in 'cn' in the RHQ Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Michal M\u011Bchura,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Weñdy Sequerl,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("We\u00F1dy Sequerl");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Sequerl");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-777-1213");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("wsequerl(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("wsequerl");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Admin Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with non-ASCII character (\u00F1) in 'cn' in the JBoss Admin Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=We\u00F1dy Sequerl,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ // dn: cn=Phillip Brãdy,ou=users,dc=test,dc=rhq,dc=redhat,dc=com
+ attrs = new BasicAttributes();
+
+ attr = new BasicAttribute("baseName");
+ attr.add("dc=test,dc=rhq,dc=redhat,dc=com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("objectClass");
+ attr.add("organizationalPerson");
+ attr.add("person");
+ attr.add("inetOrgPerson");
+ attr.add("top");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("cn");
+ attr.add("Phillip Br\u00E3dy");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("sn");
+ attr.add("Br\u00E3dy");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("homephone");
+ attr.add("555-777-1214");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("mail");
+ attr.add("pbrady(a)rhq.redhat.com");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("uid");
+ attr.add("pbrady");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("userpassword");
+ attr.add("cmVkaGF0");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("ou");
+ attr.add("JBoss Monitor Group");
+ attrs.put(attr);
+
+ attr = new BasicAttribute("description");
+ attr.add("User with non-ASCII character (\u00E3) in 'cn' in the JBoss Monitor Group");
+ attrs.put(attr);
+
+ sr = new SearchResult("cn=Phillip Br\u00E3dy,ou=users", null, null, attrs, true);
+ this.add(sr);
+
+ }
+
+ /**
+ * Unescapes an LDAP search filter value. This is done by converting
+ * each occurance of \xx (where xx is a hex value) to its character
+ * reprentation. If xx is not a valid hex value, the \ is stripped from
+ * the result.
+ *
+ * @param value a value from an LDAP search filter
+ * @return unescaped value
+ * @throws Exception
+ */
+ private String unescapeFilterValue(String value) {
+ boolean strip = false;
+ int i = 0, len = value.length();
+ char c;
+ StringBuffer sb = new StringBuffer(len);
+ while (i < len) {
+ c = value.charAt(i++);
+ if (c == '\\') {
+ if (i + 2 < len) {
+ try {
+ c = (char) Integer.parseInt(value.substring(i, i + 2), 16);
+ } catch (NumberFormatException nfe) {
+ strip = true;
+ }
+ if (!strip)
+ i += 2;
+ }
+ } // fall through: \ escapes itself, quotes any character but u
+ if (!strip)
+ sb.append(c);
+ strip = false;
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Query the test data for an LDAP entry using a simple query. The
+ * simple query is defined by a {@link Hashtable} which represents the
+ * required attributes and their values. Each LDAP entry that satisifies
+ * all the attributes and value contained in <code>attrSet</code> are
+ * returned.
+ *
+ * @param attrSet The attributes and values that an LDAP entry must have
+ * to satisfy the query
+ * @return A {@link List} of 0 or more {@link SearchResult} LDAP entries
+ * which satisified the query
+ * @throws NamingException
+ */
+ public List<SearchResult> getSearchResults(Hashtable<String, String> attrSet) throws NamingException {
+ List<SearchResult> list = new ArrayList<SearchResult>();
+ int matchCount, keyCount;
+ boolean match;
+
+ for (SearchResult sr : this) {
+ matchCount = 0;
+ keyCount = 0;
+ Attributes attrs = sr.getAttributes();
+ Enumeration<String> keye = attrSet.keys();
+ while (keye.hasMoreElements()) {
+ match = false;
+ String searchAttrName = (String) keye.nextElement();
+ Attribute attrib = attrs.get(searchAttrName);
+ if (attrib != null) {
+ for (Enumeration<?> vals = attrib.getAll(); vals.hasMoreElements();) {
+ String value = (String) vals.nextElement();
+ String utf8Value = new String(unescapeFilterValue(LDAPStringUtil.encodeForFilter(value)));
+ match = utf8Value.equalsIgnoreCase(unescapeFilterValue(attrSet.get(searchAttrName)));
+ if (match) {
+ break;
+ }
+ }
+ }
+ if (match)
+ matchCount++;
+ keyCount++;
+ }
+ if (matchCount > 0 && matchCount == keyCount) {
+ list.add(sr);
+ }
+ }
+
+ return list;
+ }
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/ldap/FakeLdapCtxFactory.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/ldap/FakeLdapCtxFactory.java
new file mode 100644
index 0000000..d149dad
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/ldap/FakeLdapCtxFactory.java
@@ -0,0 +1,61 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 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.test.ldap;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.ldap.LdapContext;
+import javax.naming.spi.InitialContextFactory;
+import javax.naming.spi.ObjectFactory;
+
+import org.apache.commons.lang.NotImplementedException;
+
+/**
+ * An implementation of {@link InitialContextFactory} that can be used for
+ * testing LDAP context operations. This implementation simply returns an
+ * instance of {@link FakeLdapContext}.
+ *
+ * @author loleary
+ *
+ */
+public class FakeLdapCtxFactory implements ObjectFactory, InitialContextFactory {
+
+ /**
+ * Returns a fake {@link LdapContext} object useful for unit testing
+ *
+ * @return A fake <code>Context</code>
+ */
+ @Override
+ public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
+ return new FakeLdapContext();
+ }
+
+ /**
+ * Not implemented
+ */
+ @Override
+ public Object getObjectInstance(Object arg0, Name arg1, Context arg2, Hashtable<?, ?> arg3) throws Exception {
+ throw new NotImplementedException();
+ }
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/ldap/FakeNamingEnumeration.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/ldap/FakeNamingEnumeration.java
new file mode 100644
index 0000000..dfa72d9
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/ldap/FakeNamingEnumeration.java
@@ -0,0 +1,76 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 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.test.ldap;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.SearchResult;
+
+/**
+ * @author loleary
+ * @param <T>
+ *
+ */
+public class FakeNamingEnumeration<T> implements NamingEnumeration<T> {
+ private List<SearchResult> srList = null;
+ private int idx = 0;
+
+ FakeNamingEnumeration(List<SearchResult> srList) {
+ if (srList != null)
+ this.srList = new ArrayList<SearchResult>(srList);
+ else
+ this.srList = new ArrayList<SearchResult>(0);
+ }
+
+ @Override
+ public boolean hasMoreElements() {
+ return srList != null && idx < srList.size() || false;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T nextElement() {
+ if (srList == null || idx >= srList.size()) {
+ throw new NoSuchElementException();
+ }
+
+ return (T) srList.get(idx++);
+ }
+
+ @Override
+ public void close() throws NamingException {
+ srList = null;
+ }
+
+ @Override
+ public boolean hasMore() throws NamingException {
+ return hasMoreElements();
+ }
+
+ @Override
+ public T next() throws NamingException {
+ return nextElement();
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/CriteriaQueryTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/CriteriaQueryTest.java
new file mode 100644
index 0000000..cdccd6c
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/CriteriaQueryTest.java
@@ -0,0 +1,125 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.util;
+
+import static java.util.Arrays.asList;
+import static org.testng.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.criteria.Criteria;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+
+public class CriteriaQueryTest {
+
+ private static class FakeEntity {
+ private int id;
+
+ public FakeEntity(int id) {
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+ }
+
+ private static class FakeEntityCriteria extends Criteria {
+ @Override
+ public Class<?> getPersistentClass() {
+ return FakeEntity.class;
+ }
+ }
+
+ private static class FakeCriteriaQueryExecutor implements CriteriaQueryExecutor<FakeEntity, FakeEntityCriteria> {
+
+ private List<PageList<FakeEntity>> pages = new ArrayList<PageList<FakeEntity>>();
+
+ private int totalSize;
+
+ private PageControl pc;
+
+ public FakeCriteriaQueryExecutor(int totalSize, PageControl pc) {
+ this.totalSize = totalSize;
+ this.pc = pc;
+ }
+
+ public void addPage(List<FakeEntity> entities) {
+ pages.add(new PageList<FakeEntity>(entities, totalSize, pc));
+ }
+
+ @Override
+ public PageList<FakeEntity> execute(FakeEntityCriteria criteria) {
+ return pages.get(criteria.getPageNumber());
+ }
+ }
+
+ @Test
+ public void executeQueryThatReturnsASinglePageOfResults() {
+ List<FakeEntity> expected = asList(new FakeEntity(1), new FakeEntity(2));
+
+ FakeCriteriaQueryExecutor queryExecutor = new FakeCriteriaQueryExecutor(2, PageControl.getUnlimitedInstance());
+ queryExecutor.addPage(expected);
+
+ FakeEntityCriteria criteria = new FakeEntityCriteria();
+
+ CriteriaQuery<FakeEntity, FakeEntityCriteria> query =
+ new CriteriaQuery<FakeEntity, FakeEntityCriteria>(criteria, queryExecutor);
+
+ List<FakeEntity> actual = new ArrayList<FakeEntity>();
+ for (FakeEntity entity : query) {
+ actual.add(entity);
+ }
+
+ assertEquals(actual, expected, "Failed to iterate over query results with a single page");
+ }
+
+ @Test
+ public void executeQueryThatReturnsMultiplePagesOfResults() {
+ PageControl pc = new PageControl(0, 2);
+
+ List<FakeEntity> expected = asList(new FakeEntity(1), new FakeEntity(2), new FakeEntity(3), new FakeEntity(4));
+
+ FakeCriteriaQueryExecutor queryExecutor = new FakeCriteriaQueryExecutor(4, pc);
+ queryExecutor.addPage(expected.subList(0, 2));
+ queryExecutor.addPage(expected.subList(2, 4));
+
+ FakeEntityCriteria criteria = new FakeEntityCriteria();
+ criteria.setPageControl(pc);
+
+ CriteriaQuery<FakeEntity, FakeEntityCriteria> query =
+ new CriteriaQuery<FakeEntity, FakeEntityCriteria>(criteria, queryExecutor);
+
+ List<FakeEntity> actual = new ArrayList<FakeEntity>();
+ for (FakeEntity entity : query) {
+ actual.add(entity);
+ }
+
+ assertEquals(actual, expected);
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/DbSetupUtility.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/DbSetupUtility.java
new file mode 100644
index 0000000..5affecb
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/DbSetupUtility.java
@@ -0,0 +1,259 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2012 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.util;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.net.URL;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Map;
+import java.util.Properties;
+
+import liquibase.Liquibase;
+import liquibase.database.Database;
+import liquibase.database.DatabaseFactory;
+import liquibase.exception.LiquibaseException;
+import liquibase.integration.commandline.CommandLineUtils;
+import liquibase.resource.ClassLoaderResourceAccessor;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.helper.ProjectHelper2;
+import org.rhq.core.db.setup.DBSetup;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+
+/**
+ * Provides utility methods for doing dbresets, dbsetups, and dbupgrades.
+ *
+ * @author Ian Springer
+ */
+public class DbSetupUtility {
+
+ public static final String JON300_SCHEMA_VERSION = "2.116";
+
+ private static final String BASE_RESOURCE_PATH = DbSetupUtility.class.getPackage().getName().replace('.', '/');
+
+ private static TestDatasourceConfiguration testDsConfig;
+
+ private static TestDatasourceConfiguration getTestDatasourceConfiguration() {
+ if (testDsConfig == null) {
+ Properties testDsProperties = new Properties();
+ InputStream resourceAsStream = DbSetupUtility.class.getResourceAsStream("test-ds.properties");
+ try {
+ testDsProperties.load(resourceAsStream);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to load test-ds.properties from classloader.", e);
+ }
+ testDsConfig = new TestDatasourceConfiguration(testDsProperties);
+ System.out.println("Using test datasource with config " + testDsConfig + "...");
+ }
+ return testDsConfig;
+ }
+
+ public static void dbreset() throws Exception {
+ TestDatasourceConfiguration testDs = getTestDatasourceConfiguration();
+ System.out.println("Resetting DB at " + testDs.connectionUrl + "...");
+
+ // NOTE: We do not use DBReset.performDBReset() here, since DBReset deletes the schema, which requires there to
+ // be no active connections to the DB. Liquibase.dropAll(), on the other hand, just deletes all the
+ // objects in the DB, which has no such requirement.
+ String dbDriver = DatabaseFactory.getInstance().findDefaultDriver(testDs.connectionUrl);
+ Database database = CommandLineUtils.createDatabaseObject(DbSetupUtility.class.getClassLoader(),
+ testDs.connectionUrl, testDs.userName, testDs.password, dbDriver, null, null, null);
+ //Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(
+ // new JdbcConnection(AbstractEJB3Test.getConnection()));
+ Liquibase liquibase = new Liquibase(null, new ClassLoaderResourceAccessor(), database);
+ liquibase.dropAll();
+ dropRhqCalltimeDataKeyTable(database);
+ }
+
+ public static void dbsetup() throws Exception {
+ dbsetup(null);
+ }
+
+ public static void dbsetup(String jonVersion) throws Exception {
+ String schemaFileResourcePath;
+ String dataFileResourcePath;
+ if (jonVersion != null) {
+ System.out.println("Installing new RHQ DB with schema from JON version [" + jonVersion + "]...");
+ schemaFileResourcePath =
+ BASE_RESOURCE_PATH + "/" + "db-schema-combined-" + jonVersion + ".xml";
+ dataFileResourcePath =
+ BASE_RESOURCE_PATH + "/" + "db-data-combined-" + jonVersion + ".xml";
+ } else {
+ System.out.println("Installing new RHQ DB with latest schema version...");
+ schemaFileResourcePath = "db-schema-combined.xml";
+ dataFileResourcePath = "db-data-combined.xml";
+ }
+
+ TestDatasourceConfiguration testDs = getTestDatasourceConfiguration();
+
+ DBSetup dbsetup = new DBSetup(testDs.connectionUrl, testDs.userName, testDs.password);
+ dbsetup.setup(schemaFileResourcePath);
+ dbsetup.setup(dataFileResourcePath);
+ }
+
+ public static void dbupgrade(String targetSchemaVersion) throws Exception {
+ System.out.println("Upgrading RHQ DB to schema version [" + targetSchemaVersion + "]...");
+ File logfile = File.createTempFile("rhq.test", "dbupgrade.log");
+
+ TestDatasourceConfiguration testDs = getTestDatasourceConfiguration();
+ try {
+ // Get the URL for the dbupgrade Ant script, which is located in the dbutils jar.
+ URL dbupgradeXmlFileUrl = DbSetupUtility.class.getClassLoader().getResource("db-upgrade.xml");
+
+ Properties antProps = new Properties();
+ antProps.setProperty("jdbc.url", testDs.connectionUrl);
+ antProps.setProperty("jdbc.user", testDs.userName);
+ antProps.setProperty("jdbc.password", testDs.password);
+ antProps.setProperty("target.schema.version", targetSchemaVersion);
+
+ startAnt(dbupgradeXmlFileUrl, "db-ant-tasks.properties", antProps, logfile);
+ } catch (Exception e) {
+ throw new RuntimeException("Cannot upgrade the RHQ DB at [" + testDs.connectionUrl + "] to schema version ["
+ + targetSchemaVersion + "].", e);
+ }
+
+ return;
+ }
+
+ private static void dropRhqCalltimeDataKeyTable(Database database) throws LiquibaseException {
+ // For some reason Liquibase always fails to drop the rhq_calltime_data_key table, logging the following:
+ //
+ // WARNING 2/22/12 4:56 PM:liquibase: Foreign key rhq_calltime_data_value_key_id_fkey references table
+ // rhq_calltime_data_key, which is in a different schema. Retaining FK in
+ // diff, but table will not be diffed.
+ //
+ // The workaround is to manually drop the table via JDBC once Liquibase has cleared out everything else.
+
+ System.out.println("Dropping rhq_calltime_data_key table...");
+ // NOTE: The below attempt to delete the table individually via Liquibase doesn't even work...
+ /*SqlVisitor sqlVisitor = new AbstractSqlVisitor() {
+ public String modifySql(String sql, Database database) {
+ log.info("Liquibase executing SQL [" + sql + "]...");
+ return sql;
+ }
+
+ public String getName() {
+ return null;
+ }
+ };
+
+ database.execute(new SqlStatement[]{new DropTableStatement(null, "rhq_calltime_data_key", false)},
+ Arrays.asList(sqlVisitor));*/
+
+ try {
+ PreparedStatement statement = AbstractEJB3Test.getConnection().prepareStatement("DROP TABLE rhq_calltime_data_key");
+ statement.execute();
+ } catch (SQLException e) {
+ // ignore
+ }
+ }
+
+ /**
+ * Launches Ant and runs the default target in the given build file.
+ *
+ * @param buildFile the build file that Ant will run
+ * @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 (in addition to the app server's log file)
+ * @throws RuntimeException
+ */
+ private static void startAnt(URL buildFile, String customTaskDefs, Properties properties, File logFile) {
+ PrintWriter logFileOutput = null;
+
+ try {
+ logFileOutput = new PrintWriter(new FileOutputStream(logFile));
+
+ ClassLoader classLoader = DbSetupUtility.class.getClassLoader();
+
+ Properties taskDefs = new Properties();
+ InputStream taskDefsStream = classLoader.getResourceAsStream(customTaskDefs);
+ try {
+ taskDefs.load(taskDefsStream);
+ } finally {
+ taskDefsStream.close();
+ }
+
+ Project project = new Project();
+ project.setCoreLoader(classLoader);
+ project.init();
+
+ for (Map.Entry<Object, Object> property : properties.entrySet()) {
+ project.setProperty(property.getKey().toString(), property.getValue().toString());
+ }
+
+ // notice we add our listener after we set the properties - we do not want the password to be in the log file
+ // our dbupgrade script will echo the property settings, so we can still get the other values
+ project.addBuildListener(new LoggerAntBuildListener(logFileOutput));
+
+ for (Map.Entry<Object, Object> taskDef : taskDefs.entrySet()) {
+ project.addTaskDefinition(taskDef.getKey().toString(), Class.forName(taskDef.getValue().toString(),
+ true, classLoader));
+ }
+
+ new ProjectHelper2().parse(project, buildFile);
+ project.executeTarget(project.getDefaultTarget());
+ } catch (Exception e) {
+ throw new RuntimeException("Cannot run Ant on script [" + buildFile + "] - cause: " + e, e);
+ } finally {
+ if (logFileOutput != null) {
+ logFileOutput.close();
+ }
+ }
+ }
+
+ private static class TestDatasourceConfiguration {
+ abstract class Property {
+ public static final String DB_CONNECTION_URL = "rhq.test.ds.connection-url";
+ public static final String DB_SERVER_NAME = "rhq.test.ds.server-name";
+ public static final String DB_NAME = "rhq.test.ds.db-name";
+ public static final String DB_USER_NAME = "rhq.test.ds.user-name";
+ public static final String DB_PASSWORD = "rhq.test.ds.password";
+ }
+
+ String connectionUrl;
+ String serverName;
+ String dbName;
+ String userName;
+ String password;
+
+ private TestDatasourceConfiguration(Properties props) {
+ connectionUrl = props.getProperty(Property.DB_CONNECTION_URL);
+ serverName = props.getProperty(Property.DB_SERVER_NAME);
+ dbName = props.getProperty(Property.DB_NAME);
+ userName = props.getProperty(Property.DB_USER_NAME);
+ password = props.getProperty(Property.DB_PASSWORD);
+ }
+
+ @Override
+ public String toString() {
+ // NOTE: For the sake of security, we don't include the password here.
+ return "{" +
+ "connectionUrl='" + connectionUrl + '\'' +
+ ", serverName='" + serverName + '\'' +
+ ", dbName='" + dbName + '\'' +
+ ", userName='" + userName + '\'' +
+ '}';
+ }
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/JaxbTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/JaxbTest.java
new file mode 100644
index 0000000..e5172f6
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/JaxbTest.java
@@ -0,0 +1,38 @@
+package org.rhq.enterprise.server.util;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.shared.ResourceBuilder;
+import org.rhq.core.domain.util.PageList;
+
+public class JaxbTest {
+
+ @Test
+ public void writeFragments() throws Exception {
+ Resource resource = new ResourceBuilder()
+ .createRandomServer()
+ .with(2).randomChildServers()
+ .build();
+
+ PageList<Resource> resources = new PageList<Resource>();
+ resources.add(resource);
+ resources.addAll(resource.getChildResources());
+
+ JAXBContext context = JAXBContext.newInstance(Resource.class, PageList.class);
+ Marshaller marshaller = context.createMarshaller();
+ marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+
+ System.out.println("<collection>\n");
+ for (Resource r : resources) {
+ marshaller.marshal(r, System.out);
+ }
+ System.out.println("</collection>\n");
+
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/LoggerAntBuildListener.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/LoggerAntBuildListener.java
new file mode 100644
index 0000000..4afe7d4
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/LoggerAntBuildListener.java
@@ -0,0 +1,105 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2012 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.util;
+
+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 PrintWriter output;
+
+ public LoggerAntBuildListener(PrintWriter logFile) {
+ output = logFile;
+
+ // just output our first line with the date this was started
+ output.println(new Date().toString());
+ }
+
+ public void buildFinished(BuildEvent event) {
+ logEvent(event, "FINISHED!");
+ }
+
+ public void buildStarted(BuildEvent event) {
+ logEvent(event, "STARTED!");
+ }
+
+ 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) {
+ 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();
+
+ return;
+ }
+
+}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/ResourceTreeHelper.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/ResourceTreeHelper.java
new file mode 100644
index 0000000..0e7170f
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/ResourceTreeHelper.java
@@ -0,0 +1,282 @@
+/*
+ * 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.enterprise.server.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import javax.persistence.EntityExistsException;
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+
+/**
+ * Will create a tree of resources based off of a short-hand, string representation of the tree Pre-condition: resource
+ * names are globally unique (because the parser is too simple to handle uniqueness wrt your parent resource) Notes: all
+ * whitespace is ignored For example: A=1,2; 1=a,b; a=i,ii; b=iii,iv; B=3 | | \|/ v +-- A +-- 1 | +-- a | | +-- i | |
+ * +-- ii | | | +-- b | +-- iii | +-- iv +-- 2 +-- B +-- 3 For now, all resources have the exact same resourceType, but
+ * it would be fairly easy to create rules where different ranges of characters (e.g., [A-Z], [a-z], etc) could be used
+ * to represent different resource types or, at the very least, different categories. A more flexible solution could be
+ * to enable a separate specification mechanism for resource types and categories. For example, we might use a compound,
+ * parenthetical annotation for category-type specification. So if we assume that, p = platform s = server v = service
+ * Then our annotated resource would look like A(p1) This would set A's resource type to the newly created resource type
+ * with the name of "fake platform 1", and set A's resource category to ResourceCategory.PLATFORM Thus, the new
+ * short-hand would look like: A(p1)=1,2; 1(s1)=a,b; a(v1)=i,ii; b(v2)=iii,iv; B(p2)=3; 2(s2); 3(s3) However, as you can
+ * see, this requires a slightly more verbose specification because the type information is parenthetically attached to
+ * the LHS of the relationship, requiring leaf nodes in the resource hierarchy to be specified solely to attach this
+ * information to it.
+ */
+public class ResourceTreeHelper {
+ private static int fakeTypeId = 1;
+ private static final String FAKE_TYPE_NAME = "fakeType";
+ private static final String FAKE_PLUGIN_NAME = "fakePlugin";
+
+ /*
+ * This will create the resource tree, but won't persist it
+ */
+ public static List<Resource> createTree(String flatStructure) {
+ return createTree(null, flatStructure);
+ }
+
+ /*
+ * This will create the resource tree, and related resource types
+ */
+ public static synchronized List<Resource> createTree(EntityManager entityManager, String flatStructure) {
+ // remove any and all whitespace from the string
+ flatStructure = flatStructure.replaceAll("\\s", "");
+
+ // if necessary, create the fakeType which ALL resources will be attached too
+ ResourceType fakeType;
+ if (null != entityManager) {
+ Query namedQuery = entityManager.createNamedQuery(ResourceType.QUERY_FIND_BY_NAME_AND_PLUGIN);
+ namedQuery.setParameter("name", FAKE_TYPE_NAME);
+ namedQuery.setParameter("plugin", FAKE_PLUGIN_NAME);
+ try {
+ fakeType = (ResourceType) namedQuery.getSingleResult();
+ } catch (NoResultException e) {
+ fakeType = null;
+ }
+ if (fakeType == null) {
+ fakeType = new ResourceType(FAKE_TYPE_NAME, FAKE_PLUGIN_NAME, ResourceCategory.PLATFORM, null);
+ persist(entityManager, fakeType);
+ fakeTypeId = fakeType.getId();
+ }
+ } else {
+ fakeType = new ResourceType(FAKE_TYPE_NAME, FAKE_PLUGIN_NAME, ResourceCategory.PLATFORM, null);
+ }
+
+ // create the map that will hold all of the resources - root, leaf, or inner node
+ Map<String, Resource> resources = new HashMap<String, Resource>();
+
+ // relationships in the form of X=y,z are semi-colon delimited
+ String[] relationships = flatStructure.split(";");
+ for (int i = 0; i < relationships.length; i++) {
+ String relationship = relationships[i];
+ int splitIndex = relationship.indexOf("=");
+ String parent = relationship.substring(0, splitIndex);
+ String[] children = relationship.substring(splitIndex + 1).split(",");
+
+ Resource parentResource = null;
+
+ // only add the parent if it doesn't already exist
+ if (resources.containsKey(parent)) {
+ parentResource = resources.get(parent);
+ } else {
+ parentResource = new Resource(parent, parent, fakeType);
+ parentResource.setUuid("" + new Random().nextInt());
+ resources.put(parent, parentResource);
+ }
+
+ for (String child : children) {
+ Resource childResource = null;
+
+ // only add the child if it doesn't already exist
+ // this happens when children were specified before their parents
+ if (resources.containsKey(child)) {
+ childResource = resources.get(child);
+ } else {
+ childResource = new Resource(child, child, fakeType);
+ childResource.setUuid("" + new Random().nextInt());
+ resources.put(child, childResource);
+ }
+
+ childResource.setParentResource(parentResource);
+ parentResource.addChildResource(childResource);
+ }
+ }
+
+ // this object returns only root resources, which can be traversed to find the children
+ List<Resource> roots = new ArrayList<Resource>();
+ for (Resource potentialRoot : resources.values()) {
+ potentialRoot.setInventoryStatus(InventoryStatus.COMMITTED);
+ persist(entityManager, potentialRoot);
+
+ // roots are those with no parent resource
+ if (potentialRoot.getParentResource() == null) {
+ roots.add(potentialRoot);
+ }
+ }
+
+ // only flush when we are in persisting mode
+ if (entityManager != null)
+ entityManager.flush();
+
+ return roots;
+ }
+
+ public static void deleteForest(EntityManager entityManager, List<Resource> roots) {
+
+ for (Resource root : roots) {
+ Resource doomedRoot = entityManager.find(Resource.class, root.getId());
+
+ if (null != doomedRoot) {
+ ResourceType doomedResourceType = doomedRoot.getResourceType();
+
+ deleteTree(entityManager, doomedRoot);
+
+ if (null != doomedResourceType) {
+ doomedResourceType = entityManager.find(ResourceType.class, doomedResourceType.getId());
+ if (doomedResourceType.getResources().isEmpty()) {
+ entityManager.remove(doomedResourceType);
+ }
+ }
+ }
+ }
+ }
+
+ private static void deleteTree(EntityManager entityManager, Resource root) {
+ for (Resource child : root.getChildResources()) {
+ deleteTree(entityManager, child);
+ }
+ deleteResource(entityManager, entityManager.find(Resource.class, root.getId()));
+ }
+
+ public static void deleteResource(EntityManager entityManager, Resource doomedResource) {
+ if (null == doomedResource) {
+ return;
+ }
+
+ for (Availability avail : doomedResource.getAvailability()) {
+ entityManager.remove(avail);
+ }
+ entityManager.remove(doomedResource);
+ }
+
+ public static Resource findNode(List<Resource> roots, String name) {
+ Resource node = null;
+ for (Resource root : roots) {
+ node = findNode(root, name);
+ if (node != null) {
+ break;
+ }
+ }
+
+ return node;
+ }
+
+ // public static Resource findNode(Resource rootResource, String name) {
+ // return findNodeHelper(rootResource, name);
+ // }
+
+ public static Resource findNode(Resource resource, String name) {
+ if (name.equals(resource.getName())) {
+ return resource;
+ }
+
+ Resource result = null;
+ for (Resource child : resource.getChildResources()) {
+ result = findNode(child, name);
+ if (result != null) {
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ public static List<Resource> getSubtree(Resource resource) {
+ List<Resource> subtree = new ArrayList<Resource>();
+
+ List<Resource> toBeSearched = new LinkedList<Resource>();
+ toBeSearched.add(resource);
+ while (toBeSearched.size() > 0) {
+ Resource next = toBeSearched.remove(0);
+ subtree.add(next);
+ toBeSearched.addAll(next.getChildResources());
+ }
+
+ return subtree;
+ }
+
+ public static List<Resource> findSubtree(Resource resource, String name) {
+ return getSubtree(findNode(resource, name));
+ }
+
+ private static void persist(EntityManager entityManager, Object object) {
+ if (entityManager != null) {
+ try {
+ entityManager.persist(object);
+ } catch (EntityExistsException e) {
+ // ignore
+ }
+ }
+ }
+
+ public static void printForest(List<Resource> resources) {
+ for (Resource root : resources) {
+ printTree(root);
+ }
+ }
+
+ public static void printTree(Resource resource) {
+ printTreeHelper(resource, 0, "");
+ }
+
+ private static void printTreeHelper(Resource resource, int level, String namePrefix) {
+ for (int i = 0; i < level; i++) {
+ System.out.print(" ");
+ }
+
+ System.out.println("<resource " + //
+ "id=\"" + resource.getId() + "\" " + //
+ "name=\"" + resource.getName() + "\" " + //
+ "path=\"" + namePrefix + resource.getName() + "\" />");
+
+ for (Resource child : resource.getChildResources()) {
+ printTreeHelper(child, level + 1, namePrefix + resource.getName() + ".");
+ }
+ }
+
+ public static void main(String[] args) {
+ List<Resource> resourceRoots = createTree("A=1,2; 1=a,b; a=i,ii; b=iii,iv; B=3");
+ for (Resource root : resourceRoots) {
+ printTree(root);
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/SessionTestHelper.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/SessionTestHelper.java
new file mode 100644
index 0000000..4b51224
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/util/SessionTestHelper.java
@@ -0,0 +1,286 @@
+/*
+ * 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.enterprise.server.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.persistence.EntityManager;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.authz.Permission.Target;
+import org.rhq.core.domain.authz.Role;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.configuration.definition.PropertySimpleType;
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.ResourceAvailability;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.InventoryStatus;
+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.domain.resource.group.ResourceGroup;
+import org.rhq.enterprise.server.auth.SessionManager;
+
+public class SessionTestHelper {
+
+ private static AtomicInteger idGenerator = new AtomicInteger(0);
+
+ /*
+ * supporting methods to help carry out primary tests
+ */
+ public static boolean samePermissions(Set<Permission> one, Set<Permission> two) {
+ return one.containsAll(two) && two.containsAll(one);
+ }
+
+ public static Set<Permission> getAllGlobalPerms() {
+ Permission[] allPermissions = Permission.values();
+ Set<Permission> globalPermissions = EnumSet.noneOf(Permission.class);
+ for (Permission permission : allPermissions) {
+ if (permission.getTarget() == Target.GLOBAL) {
+ globalPermissions.add(permission);
+ }
+ }
+
+ return globalPermissions;
+ }
+
+ public static Set<Permission> getAllResourcePerms() {
+ Permission[] allPermissions = Permission.values();
+ Set<Permission> globalPermissions = EnumSet.noneOf(Permission.class);
+ for (Permission permission : allPermissions) {
+ if (permission.getTarget() == Target.RESOURCE) {
+ globalPermissions.add(permission);
+ }
+ }
+
+ return globalPermissions;
+ }
+
+ public static Subject createNewSubject(EntityManager em, String subjectName) {
+ subjectName = preprocess(subjectName);
+
+ Subject newSubject = new Subject();
+ newSubject.setName(subjectName);
+ newSubject.setFactive(true);
+ newSubject.setFsystem(false);
+
+ em.persist(newSubject);
+ em.flush();
+
+ // We want to return the attached object but sessionmanager.put will return a detached copy of newSubject.
+ // Copy over the sessionId and pass back the attached Subject.
+ Subject sessionSubject = SessionManager.getInstance().put(newSubject, 1000 * 60 * 10); // 10 mins timeout
+ newSubject.setSessionId(sessionSubject.getSessionId());
+ return newSubject;
+ }
+
+ public static void simulateLogin(Subject subject) {
+ Subject sessionSubject = SessionManager.getInstance().put(subject, 1000 * 60 * 10); // 10 mins timeout
+ subject.setSessionId(sessionSubject.getSessionId());
+ return;
+ }
+
+ public static void simulateLogout(Subject subject) {
+ Integer sessionId = subject.getSessionId();
+ if (sessionId != null) {
+ SessionManager.getInstance().invalidate(sessionId);
+ }
+ return;
+ }
+
+ public static Role createNewRoleForSubject(EntityManager em, Subject subject, String roleName) {
+ return createNewRoleForSubject(em, subject, roleName, new Permission[0]);
+ }
+
+ public static Role createNewRoleForSubject(EntityManager em, Subject subject, String roleName,
+ Permission... permissions) {
+ roleName = preprocess(roleName);
+
+ Role newRole = new Role(roleName);
+ newRole.setFsystem(false);
+
+ for (Permission perm : permissions) {
+ newRole.addPermission(perm);
+ }
+
+ subject.getRoles().add(newRole);
+ newRole.getSubjects().add(subject);
+
+ em.persist(subject);
+ em.persist(newRole);
+ em.flush();
+
+ return newRole;
+ }
+
+ public static ResourceType createNewResourceType(EntityManager em) {
+ ResourceType type = new ResourceType(preprocess("testType"), "testPlugin", ResourceCategory.PLATFORM, null);
+ ConfigurationDefinition resourceConfigDef = new ConfigurationDefinition("Fake def",
+ "Resource config def for fake test resource");
+ resourceConfigDef.put(new PropertyDefinitionSimple("fake property", "fake", false, PropertySimpleType.BOOLEAN));
+ type.setResourceConfigurationDefinition(resourceConfigDef);
+ em.persist(type);
+ em.flush();
+
+ return type;
+ }
+
+ public static ResourceGroup createNewCompatibleGroupForRole(EntityManager em, Role role, String groupName) {
+ return createNewCompatibleGroupForRole(em, role, groupName, null);
+ }
+
+ public static ResourceGroup createNewCompatibleGroupForRole(EntityManager em, Role role, String groupName,
+ ResourceType type) {
+ if (type == null) {
+ type = createNewResourceType(em);
+ }
+ return createNewGroupForRoleHelper(em, role, groupName, type, false);
+ }
+
+ public static ResourceGroup createNewMixedGroupForRole(EntityManager em, Role role, String groupName,
+ boolean recursive) {
+ return createNewGroupForRoleHelper(em, role, groupName, null, recursive);
+ }
+
+ private static ResourceGroup createNewGroupForRoleHelper(EntityManager em, Role role, String groupName,
+ ResourceType type, boolean recursive) {
+ ResourceGroup newGroup = null;
+
+ groupName = preprocess(groupName);
+
+ if (type == null) {
+ newGroup = new ResourceGroup(groupName);
+ newGroup.setRecursive(recursive);
+ } else {
+ newGroup = new ResourceGroup(groupName, type);
+ }
+
+ if (role != null) {
+ role.getResourceGroups().add(newGroup);
+ newGroup.addRole(role);
+
+ em.persist(role);
+ }
+
+ em.persist(newGroup);
+ em.flush();
+
+ return newGroup;
+ }
+
+ public static Resource createNewResourceForGroup(EntityManager em, ResourceGroup group, String resourceName) {
+ ResourceType type = group.getResourceType();
+ return createNewResourceForGroup(em, group, resourceName, type, true);
+ }
+
+ public static Resource createNewResourceForGroup(EntityManager em, ResourceGroup group, String resourceName,
+ ResourceType type, boolean doFlush) {
+ return createNewResourceForGroup(em, group, resourceName, type, AvailabilityType.UP, doFlush);
+ }
+
+ public static Resource createNewResourceForGroup(EntityManager em, ResourceGroup group, String resourceName,
+ ResourceType type, AvailabilityType avail, boolean doFlush) {
+
+ if (type == null) {
+ type = createNewResourceType(em);
+ }
+
+ resourceName = preprocess(resourceName);
+ Resource resource = new Resource(resourceName, resourceName, type);
+ resource.setUuid("" + new Random().nextInt());
+ resource.setInventoryStatus(InventoryStatus.COMMITTED);
+ resource.initCurrentAvailability(); // the only way I can see to intialize the avail list
+ resource.setCurrentAvailability(new ResourceAvailability(resource, avail));
+ resource.getAvailability().clear();
+ resource.getAvailability().add(new Availability(resource, 0L, avail));
+
+ group.addExplicitResource(resource);
+ resource.getExplicitGroups().add(group);
+
+ /*
+ * Single resource implies the implicit resource list should mirror the explicit one
+ */
+ group.addImplicitResource(resource);
+ resource.getImplicitGroups().add(group);
+
+ em.persist(resource);
+ if (doFlush) {
+ em.flush();
+ }
+
+ return resource;
+ }
+
+ public static Agent createNewAgent(EntityManager em, String agentName) {
+ agentName = preprocess(agentName);
+ String address = preprocess("localhost");
+ int port = 16163;
+ String endPoint = "socket://" + address + ":" + port + "/?rhq.communications.connector.rhqtype=agent";
+
+ Agent agent = new Agent(agentName, address, port, endPoint, agentName);
+
+ em.persist(agent);
+ em.flush();
+
+ return agent;
+ }
+
+ public static Resource createNewResource(EntityManager em, String resourceName) {
+ return createNewResource(em, resourceName, null);
+ }
+
+ public static Resource createNewResource(EntityManager em, String resourceName, ResourceType type) {
+ if (type == null) {
+ type = new ResourceType(preprocess("testType"), "testPlugin", ResourceCategory.PLATFORM, null);
+ em.persist(type);
+ }
+
+ resourceName = preprocess(resourceName);
+ Resource resource = new Resource(resourceName, resourceName, type);
+ resource.setUuid("" + new Random().nextInt());
+ resource.setInventoryStatus(InventoryStatus.COMMITTED);
+ resource.setCurrentAvailability(new ResourceAvailability(resource, AvailabilityType.UP));
+
+ em.persist(resource);
+ em.flush();
+
+ return resource;
+ }
+
+ public static Collection<Integer> getResourceList(Resource... resources) {
+ Collection<Integer> resourceIdList = new ArrayList<Integer>(resources.length + 1);
+ for (Resource resource : resources) {
+ resourceIdList.add(resource.getId());
+ }
+
+ return resourceIdList;
+ }
+
+ private static String preprocess(String name) {
+ return name += (System.currentTimeMillis() + "-" + idGenerator.getAndIncrement());
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/application.xml b/modules/enterprise/server/itests-2/src/test/resources/application.xml
new file mode 100644
index 0000000..06b81e6
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/application.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" version="6">
+ <description>RHQ enterprise server EAR</description>
+ <display-name>RHQ</display-name>
+ <module>
+ <ejb>rhq-core-domain-ejb3.jar</ejb>
+ </module>
+ <module>
+ <ejb>rhq-enterprise-server-ejb3.jar</ejb>
+ </module>
+</application>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/arquillian.xml b/modules/enterprise/server/itests-2/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..66f737a
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/arquillian.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<arquillian
+ xmlns="http://jboss.org/schema/arquillian"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://jboss.org/schema/arquillian
+ http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
+
+ <!-- Change from using the default JMX protocol due to https://issues.jboss.org/browse/AS7-1696 -->
+ <defaultProtocol type="Servlet 3.0" />
+
+ <container
+ qualifier="RHQAS7"
+ default="true">
+
+ <configuration>
+ <property name="jbossHome">${jboss.unzip.location}</property>
+ </configuration>
+ </container>
+</arquillian>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/binary-blob-sample.jar b/modules/enterprise/server/itests-2/src/test/resources/binary-blob-sample.jar
new file mode 100644
index 0000000..0a629ec
Binary files /dev/null and b/modules/enterprise/server/itests-2/src/test/resources/binary-blob-sample.jar differ
diff --git a/modules/enterprise/server/itests-2/src/test/resources/default.persistence.properties b/modules/enterprise/server/itests-2/src/test/resources/default.persistence.properties
new file mode 100644
index 0000000..8e4f317
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/default.persistence.properties
@@ -0,0 +1,22 @@
+hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JBossTransactionManagerLookup
+#hibernate.connection.release_mode=after_statement
+#hibernate.transaction.flush_before_completion=false
+#hibernate.transaction.auto_close_session=false
+#hibernate.query.factory_class=org.hibernate.hql.ast.ASTQueryTranslatorFactory
+#hibernate.hbm2ddl.auto=create-drop
+#hibernate.hbm2ddl.auto=create
+hibernate.cache.provider_class=org.hibernate.cache.HashtableCacheProvider
+# Clustered cache with TreeCache
+#hibernate.cache.provider_class=org.jboss.ejb3.entity.TreeCacheProviderHook
+#hibernate.treecache.mbean.object_name=jboss.cache:service=EJB3EntityTreeCache
+#hibernate.dialect=org.hibernate.dialect.HSQLDialect
+hibernate.jndi.java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
+hibernate.jndi.java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
+hibernate.bytecode.use_reflection_optimizer=false
+# I don't think this is honored, but EJB3Deployer uses it
+hibernate.bytecode.provider=javassist
+hibernate.jdbc.use_streams_for_binary=true
+hibernate.show_sql=false
+hibernate.format_sql=true
+hibernate.default_batch_fetch_size=16
+hibernate.jdbc.batch_size=20
diff --git a/modules/enterprise/server/itests-2/src/test/resources/ejb-jar.xml b/modules/enterprise/server/itests-2/src/test/resources/ejb-jar.xml
new file mode 100644
index 0000000..b3deb45
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/ejb-jar.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
+ version="3.1">
+
+ <description>RHQ</description>
+ <display-name>RHQ</display-name>
+
+ <interceptors>
+ <interceptor>
+ <interceptor-class>org.rhq.enterprise.server.authz.RequiredPermissionsInterceptor</interceptor-class>
+ </interceptor>
+ <interceptor>
+ <interceptor-class>org.rhq.enterprise.server.common.TransactionInterruptInterceptor</interceptor-class>
+ </interceptor>
+ <interceptor>
+ <interceptor-class>org.rhq.enterprise.server.common.PerformanceMonitorInterceptor</interceptor-class>
+ </interceptor>
+ </interceptors>
+
+ <assembly-descriptor>
+
+ <!-- all our EJB3 SLSBs can define custom @RequiredPermissions annotations for authorization checks-->
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+ <interceptor-class>org.rhq.enterprise.server.authz.RequiredPermissionsInterceptor</interceptor-class>
+ </interceptor-binding>
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+ <interceptor-class>org.rhq.enterprise.server.common.TransactionInterruptInterceptor</interceptor-class>
+ </interceptor-binding>
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+ <interceptor-class>org.rhq.enterprise.server.common.PerformanceMonitorInterceptor</interceptor-class>
+ </interceptor-binding>
+
+ </assembly-descriptor>
+
+</ejb-jar>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/ejb3-interceptors-aop.xml b/modules/enterprise/server/itests-2/src/test/resources/ejb3-interceptors-aop.xml
new file mode 100644
index 0000000..f30aa70
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/ejb3-interceptors-aop.xml
@@ -0,0 +1,360 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE aop PUBLIC
+ "-//JBoss//DTD JBOSS AOP 1.0//EN"
+ "http://www.jboss.org/aop/dtd/jboss-aop_1_0.dtd">
+
+<aop>
+ <interceptor class="org.jboss.aspects.remoting.InvokeRemoteInterceptor" scope="PER_VM"/>
+ <interceptor class="org.jboss.aspects.security.SecurityClientInterceptor" scope="PER_VM"/>
+ <interceptor class="org.jboss.aspects.tx.ClientTxPropagationInterceptor" scope="PER_VM"/>
+ <interceptor class="org.jboss.ejb3.remoting.IsLocalInterceptor" scope="PER_VM"/>
+ <interceptor class="org.jboss.aspects.remoting.ClusterChooserInterceptor" scope="PER_VM"/>
+
+ <interceptor class="org.jboss.aspects.tx.TxPropagationInterceptor" scope="PER_VM"/>
+
+ <stack name="ServiceClientInterceptors">
+ <interceptor-ref name="org.jboss.ejb3.remoting.IsLocalInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.security.SecurityClientInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.tx.ClientTxPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.remoting.InvokeRemoteInterceptor"/>
+ </stack>
+
+ <stack name="AsynchronousStatelessSessionClientInterceptors">
+ <interceptor-ref name="org.jboss.ejb3.remoting.IsLocalInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.security.SecurityClientInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.tx.ClientTxPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.remoting.InvokeRemoteInterceptor"/>
+ </stack>
+
+ <stack name="AsynchronousStatefulSessionClientInterceptors">
+ <interceptor-ref name="org.jboss.ejb3.remoting.IsLocalInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.security.SecurityClientInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.tx.ClientTxPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.remoting.InvokeRemoteInterceptor"/>
+ </stack>
+
+ <stack name="StatelessSessionClientInterceptors">
+ <interceptor-ref name="org.jboss.ejb3.remoting.IsLocalInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.security.SecurityClientInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.tx.ClientTxPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.remoting.InvokeRemoteInterceptor"/>
+ </stack>
+
+ <stack name="StatefulSessionClientInterceptors">
+ <interceptor-ref name="org.jboss.ejb3.remoting.IsLocalInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.security.SecurityClientInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.tx.ClientTxPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.remoting.InvokeRemoteInterceptor"/>
+ </stack>
+
+ <stack name="ClusteredStatelessSessionClientInterceptors">
+ <interceptor-ref name="org.jboss.ejb3.remoting.IsLocalInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.security.SecurityClientInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.tx.ClientTxPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.remoting.ClusterChooserInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.remoting.InvokeRemoteInterceptor"/>
+ </stack>
+
+ <stack name="ClusteredStatefulSessionClientInterceptors">
+ <interceptor-ref name="org.jboss.ejb3.remoting.IsLocalInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.security.SecurityClientInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.tx.ClientTxPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.remoting.ClusterChooserInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.remoting.InvokeRemoteInterceptor"/>
+ </stack>
+
+ <interceptor class="org.jboss.ejb3.asynchronous.AsynchronousInterceptor" scope="PER_CLASS"/>
+ <interceptor class="org.jboss.ejb3.ENCPropagationInterceptor" scope="PER_VM"/>
+ <interceptor name="Basic Authorization" factory="org.jboss.ejb3.security.RoleBasedAuthorizationInterceptorFactory" scope="PER_CLASS"/>
+ <interceptor name="JACC Authorization" factory="org.jboss.ejb3.security.JaccAuthorizationInterceptorFactory" scope="PER_CLASS"/>
+ <interceptor factory="org.jboss.ejb3.security.AuthenticationInterceptorFactory" scope="PER_CLASS"/>
+ <interceptor factory="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory" scope="PER_CLASS"/>
+ <interceptor class="org.jboss.ejb3.entity.ExtendedPersistenceContextPropagationInterceptor" scope="PER_VM"/>
+ <interceptor class="org.jboss.ejb3.stateless.StatelessInstanceInterceptor" scope="PER_VM"/>
+ <interceptor class="org.jboss.ejb3.stateful.StatefulInstanceInterceptor" scope="PER_VM"/>
+ <interceptor class="org.jboss.ejb3.stateful.SessionSynchronizationInterceptor" scope="PER_VM"/>
+ <interceptor class="org.jboss.ejb3.service.ServiceSingletonInterceptor" scope="PER_VM"/>
+ <interceptor class="org.jboss.ejb3.cache.StatefulReplicationInterceptor" scope="PER_VM"/>
+ <interceptor factory="org.jboss.ejb3.stateful.StatefulRemoveFactory" scope="PER_CLASS_JOINPOINT"/>
+ <interceptor factory="org.jboss.ejb3.tx.TxInterceptorFactory" scope="PER_CLASS_JOINPOINT"/>
+ <interceptor factory="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory" scope="PER_CLASS_JOINPOINT"/>
+ <interceptor factory="org.jboss.ejb3.remoting.ReplicantsManagerInterceptorFactory" scope="PER_CLASS"/>
+ <interceptor class="org.jboss.ejb3.AllowedOperationsInterceptor" scope="PER_VM"/>
+ <interceptor factory="org.jboss.ejb3.mdb.CurrentMessageInjectorInterceptorFactory" scope="PER_CLASS"/>
+ <interceptor class="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor" scope="PER_VM"/>
+
+ <domain name="Stateless Bean">
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.asynchronous.AsynchronousInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.ENCPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.security.AuthenticationInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * @org.jboss.annotation.security.SecurityDomain->*(..))">
+ <interceptor-ref name="Basic Authorization"/>
+ </bind>
+ <bind pointcut="execution(public * @javax.annotation.security.RunAs->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * @org.jboss.annotation.ejb.Clustered->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.remoting.ReplicantsManagerInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.stateless.StatelessInstanceInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.tx.TxPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.tx.TxInterceptorFactory"/>
+ <interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory"/>
+ </bind>
+ <annotation expr="!class((a)org.jboss.annotation.ejb.PoolClass)">
+ @org.jboss.annotation.ejb.PoolClass (value=org.jboss.ejb3.ThreadlocalPool.class, maxSize=30, timeout=10000)
+ </annotation>
+ </domain>
+
+ <domain name="JACC Stateless Bean">
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.asynchronous.AsynchronousInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.ENCPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.security.AuthenticationInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * @org.jboss.annotation.security.SecurityDomain->*(..))">
+ <interceptor-ref name="JACC Authorization"/>
+ </bind>
+ <bind pointcut="execution(public * @javax.annotation.security.RunAs->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * @org.jboss.annotation.ejb.Clustered->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.remoting.ReplicantsManagerInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.stateless.StatelessInstanceInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.tx.TxPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.tx.TxInterceptorFactory"/>
+ <interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory"/>
+ </bind>
+ <annotation expr="!class((a)org.jboss.annotation.ejb.PoolClass)">
+ @org.jboss.annotation.ejb.PoolClass (value=org.jboss.ejb3.ThreadlocalPool.class, maxSize=30, timeout=10000)
+ </annotation>
+ </domain>
+
+ <domain name="Base Stateful Bean">
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.asynchronous.AsynchronousInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.ENCPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.security.AuthenticationInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * @org.jboss.annotation.security.SecurityDomain->*(..))">
+ <interceptor-ref name="Basic Authorization"/>
+ </bind>
+ <bind pointcut="execution(public * @javax.annotation.security.RunAs->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * @org.jboss.annotation.ejb.Clustered->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.remoting.ReplicantsManagerInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * *->@javax.ejb.Remove(..))">
+ <interceptor-ref name="org.jboss.ejb3.stateful.StatefulRemoveFactory"/>
+ </bind>
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.stateful.StatefulInstanceInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.tx.TxPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.tx.TxInterceptorFactory"/>
+ <interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/>
+ </bind>
+ <bind pointcut="execution(public * $instanceof{javax.ejb.SessionSynchronization}->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.stateful.SessionSynchronizationInterceptor"/>
+ </bind>
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.entity.ExtendedPersistenceContextPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory"/>
+ </bind>
+
+ <bind pointcut="execution(public * @org.jboss.annotation.ejb.Clustered->*(..)) AND !execution(public * *->@javax.ejb.Remove(..))">
+ <interceptor-ref name="org.jboss.ejb3.cache.StatefulReplicationInterceptor"/>
+ </bind>
+ <annotation expr="!class((a)org.jboss.annotation.ejb.PoolClass)">
+ @org.jboss.annotation.ejb.PoolClass (value=org.jboss.ejb3.ThreadlocalPool.class, maxSize=30, timeout=10000)
+ </annotation>
+ </domain>
+
+ <domain name="Stateful Bean" extends="Base Stateful Bean" inheritBindings="true">
+ <!-- NON Clustered cache configuration -->
+ <annotation expr="!class((a)org.jboss.annotation.ejb.cache.Cache) AND !class((a)org.jboss.annotation.ejb.Clustered)">
+ @org.jboss.annotation.ejb.cache.Cache (org.jboss.ejb3.cache.simple.SimpleStatefulCache.class)
+ </annotation>
+ <annotation expr="!class((a)org.jboss.annotation.ejb.cache.simple.PersistenceManager) AND !class((a)org.jboss.annotation.ejb.Clustered)">
+ @org.jboss.annotation.ejb.cache.simple.PersistenceManager (org.jboss.ejb3.cache.simple.StatefulSessionFilePersistenceManager.class)
+ </annotation>
+ <annotation expr="!class((a)org.jboss.annotation.ejb.cache.simple.CacheConfig) AND !class((a)org.jboss.annotation.ejb.Clustered)">
+ @org.jboss.annotation.ejb.cache.simple.CacheConfig (maxSize=100000, idleTimeoutSeconds=300)
+ </annotation>
+
+ <!-- Clustered cache configuration -->
+ <annotation expr="!class((a)org.jboss.annotation.ejb.cache.Cache) AND class((a)org.jboss.annotation.ejb.Clustered)">
+ @org.jboss.annotation.ejb.cache.Cache (org.jboss.ejb3.cache.tree.StatefulTreeCache.class)
+ </annotation>
+ <annotation expr="!class((a)org.jboss.annotation.ejb.cache.tree.CacheConfig) AND class((a)org.jboss.annotation.ejb.Clustered)">
+ @org.jboss.annotation.ejb.cache.tree.CacheConfig (name="jboss.cache:service=EJB3SFSBClusteredCache", maxSize=100000, idleTimeoutSeconds=300)
+ </annotation>
+ </domain>
+
+ <domain name="JACC Stateful Bean">
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.asynchronous.AsynchronousInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.ENCPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.security.AuthenticationInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * @org.jboss.annotation.security.SecurityDomain->*(..))">
+ <interceptor-ref name="JACC Authorization"/>
+ </bind>
+ <bind pointcut="execution(public * @javax.annotation.security.RunAs->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * @org.jboss.annotation.ejb.Clustered->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.remoting.ReplicantsManagerInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * *->@javax.ejb.Remove(..))">
+ <interceptor-ref name="org.jboss.ejb3.stateful.StatefulRemoveFactory"/>
+ </bind>
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.stateful.StatefulInstanceInterceptor"/>
+ <interceptor-ref name="org.jboss.aspects.tx.TxPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.tx.TxInterceptorFactory"/>
+ <interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/>
+ </bind>
+ <bind pointcut="execution(public * $instanceof{javax.ejb.SessionSynchronization}->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.stateful.SessionSynchronizationInterceptor"/>
+ </bind>
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.entity.ExtendedPersistenceContextPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory"/>
+ </bind>
+
+ <bind pointcut="execution(public * @org.jboss.annotation.ejb.Clustered->*(..)) AND !execution(public * *->@javax.ejb.Remove(..))">
+ <interceptor-ref name="org.jboss.ejb3.cache.StatefulReplicationInterceptor"/>
+ </bind>
+ <annotation expr="!class((a)org.jboss.annotation.ejb.PoolClass)">
+ @org.jboss.annotation.ejb.PoolClass (value=org.jboss.ejb3.ThreadlocalPool.class, maxSize=30, timeout=10000)
+ </annotation>
+
+ <!-- NON Clustered cache configuration -->
+ <annotation expr="!class((a)org.jboss.annotation.ejb.cache.Cache) AND !class((a)org.jboss.annotation.ejb.Clustered)">
+ @org.jboss.annotation.ejb.cache.Cache (org.jboss.ejb3.cache.simple.SimpleStatefulCache.class)
+ </annotation>
+ <annotation expr="!class((a)org.jboss.annotation.ejb.cache.simple.PersistenceManager) AND !class((a)org.jboss.annotation.ejb.Clustered)">
+ @org.jboss.annotation.ejb.cache.simple.PersistenceManager (org.jboss.ejb3.cache.simple.StatefulSessionFilePersistenceManager.class)
+ </annotation>
+ <annotation expr="!class((a)org.jboss.annotation.ejb.cache.simple.CacheConfig) AND !class((a)org.jboss.annotation.ejb.Clustered)">
+ @org.jboss.annotation.ejb.cache.simple.CacheConfig (maxSize=100000, idleTimeoutSeconds=300)
+ </annotation>
+
+ <!-- Clustered cache configuration -->
+ <annotation expr="!class((a)org.jboss.annotation.ejb.cache.Cache) AND class((a)org.jboss.annotation.ejb.Clustered)">
+ @org.jboss.annotation.ejb.cache.Cache (org.jboss.ejb3.cache.tree.StatefulTreeCache.class)
+ </annotation>
+ <annotation expr="!class((a)org.jboss.annotation.ejb.cache.tree.CacheConfig) AND class((a)org.jboss.annotation.ejb.Clustered)">
+ @org.jboss.annotation.ejb.cache.tree.CacheConfig (name="jboss.cache:service=EJB3SFSBClusteredCache", maxSize=100000, idleTimeoutSeconds=300)
+ </annotation>
+ </domain>
+
+ <domain name="Embedded Stateful Bean" extends="Base Stateful Bean" inheritBindings="true">
+ <!-- NON Clustered cache configuration -->
+ <annotation expr="!class((a)org.jboss.annotation.ejb.cache.Cache)">
+ @org.jboss.annotation.ejb.cache.Cache (org.jboss.ejb3.cache.NoPassivationCache.class)
+ </annotation>
+
+ </domain>
+
+ <domain name="Message Driven Bean">
+ <bind pointcut="execution(public * @javax.annotation.security.RunAs->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.stateless.StatelessInstanceInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.tx.TxInterceptorFactory"/>
+ <interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory"/>
+ </bind>
+ <annotation expr="!class((a)org.jboss.annotation.ejb.PoolClass)">
+ @org.jboss.annotation.ejb.PoolClass (value=org.jboss.ejb3.StrictMaxPool.class, maxSize=30, timeout=10000)
+ </annotation>
+ </domain>
+
+ <domain name="Consumer Bean">
+ <bind pointcut="execution(public * @javax.annotation.security.RunAs->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.stateless.StatelessInstanceInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.tx.TxInterceptorFactory"/>
+ <interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/>
+ </bind>
+ <bind pointcut="execution(public * *->*(..)) AND (has(* *->@org.jboss.annotation.ejb.CurrentMessage(..)) OR hasfield(* *->@org.jboss.annotation.ejb.CurrentMessage))">
+ <interceptor-ref name="org.jboss.ejb3.mdb.CurrentMessageInjectorInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory"/>
+ </bind>
+ <annotation expr="!class((a)org.jboss.annotation.ejb.PoolClass)">
+ @org.jboss.annotation.ejb.PoolClass (value=org.jboss.ejb3.StrictMaxPool.class, maxSize=30, timeout=10000)
+ </annotation>
+ </domain>
+
+ <domain name="Service Bean">
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.asynchronous.AsynchronousInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.ENCPropagationInterceptor"/>
+ </bind>
+ <bind pointcut="!execution(* *->create()) AND !execution(* *->start()) AND !execution(*->new(..))">
+ <interceptor-ref name="org.jboss.ejb3.security.AuthenticationInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * @org.jboss.annotation.security.SecurityDomain->*(..))">
+ <interceptor-ref name="Basic Authorization"/>
+ </bind>
+ <bind pointcut="execution(public * @javax.annotation.security.RunAs->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.aspects.tx.TxPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.tx.TxInterceptorFactory"/>
+ <interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/>
+ </bind>
+ <bind pointcut="execution(public * *->*(..)) AND !execution(* *->create()) AND !execution(* *->start())">
+ <interceptor-ref name="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory"/>
+ </bind>
+ </domain>
+
+ <domain name="JACC Service Bean">
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.asynchronous.AsynchronousInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.ENCPropagationInterceptor"/>
+ </bind>
+ <bind pointcut="!execution(* *->create()) AND !execution(* *->start()) AND !execution(*->new(..))">
+ <interceptor-ref name="org.jboss.ejb3.security.AuthenticationInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * @org.jboss.annotation.security.SecurityDomain->*(..))">
+ <interceptor-ref name="Basic Authorization"/>
+ </bind>
+ <bind pointcut="execution(public * @javax.annotation.security.RunAs->*(..))">
+ <interceptor-ref name="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory"/>
+ </bind>
+ <bind pointcut="execution(public * *->*(..))">
+ <interceptor-ref name="org.jboss.aspects.tx.TxPropagationInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.tx.TxInterceptorFactory"/>
+ <interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/>
+ <interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/>
+ </bind>
+ <bind pointcut="execution(public * *->*(..)) AND !execution(* *->create()) AND !execution(* *->start())">
+ <interceptor-ref name="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory"/>
+ </bind>
+ </domain>
+
+
+</aop>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/jboss-deployment-structure.xml b/modules/enterprise/server/itests-2/src/test/resources/jboss-deployment-structure.xml
new file mode 100644
index 0000000..29e376e
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/jboss-deployment-structure.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">
+
+ <!-- Explicitly indicate that we do not want sub deployments isolated; subdeployments need to see each other's classes -->
+ <ear-subdeployments-isolated>false</ear-subdeployments-isolated>
+
+ <!-- This corresponds to the top level deployment - which in this case in the EAR module -->
+ <deployment>
+ <dependencies>
+ <module name="org.jboss.common-core" export="true" /> <!-- needed to fix https://issues.jboss.org/browse/AS7-5336 -->
+ <module name="org.jboss.jts" export="true" /> <!-- needed for Arjuna CheckedAction related classes and our custom tx interceptor -->
+ <module name="org.apache.commons.logging" export="true" /> <!-- needed as per https://docs.jboss.org/author/display/AS71/How+do+I+migrate+my+applicatio... -->
+ <module name="org.hibernate" export="true" /> <!-- because we need hibernate specific APIs, e.g. for the HibernateDetachUtility -->
+ <module name="org.infinispan" export="true" /> <!-- because we use an Infinispan cache for REST services -->
+ <module name="org.antlr" export="true" /> <!-- rhq ejb jar module wants this - i think for dynagroup syntax? -->
+ <module name="org.dom4j" export="true" /> <!-- rhq ejb jar module declares this with runtime/provided scope -->
+ <module name="javax.mail.api" export="true" /> <!-- for sending email notifications -->
+ <module name="org.picketbox" export="true" /> <!-- for obfuscating passwords -->
+ </dependencies>
+ </deployment>
+
+ <!-- This corresponds to the Server EJB3 JAR -->
+ <sub-deployment name="rhq-enterprise-server-ejb3.jar">
+ <dependencies>
+ <module name="org.jboss.msc" export="true" />
+ <module name="org.jboss.as.controller" export="true" />
+ <module name="org.jboss.as.server" export="true" />
+ </dependencies>
+ </sub-deployment>
+
+</jboss-deployment-structure>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/jboss-jms-beans.xml b/modules/enterprise/server/itests-2/src/test/resources/jboss-jms-beans.xml
new file mode 100644
index 0000000..287cffc
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/jboss-jms-beans.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
+ xmlns="urn:jboss:bean-deployer:2.0">
+ <bean name="jboss.mq:service=JMSProviderLoader,name=JMSProvider" class="org.jboss.jms.jndi.JNDIProviderAdapter">
+ <property name="factoryRef">java:/JmsXA</property>
+ <property name="queueFactoryRef">java:/JmsXA</property>
+ <property name="topicFactoryRef">java:/JmsXA</property>
+ <property name="properties" class="java.util.Properties">
+ <map keyClass="java.lang.String" valueClass="java.lang.String">
+ <entry>
+ <key>java.naming.factory.initial</key>
+ <value>org.jnp.interfaces.LocalOnlyContextFactory</value>
+ </entry>
+ <entry>
+ <key>java.naming.factory.url.pkgs</key>
+ <value>org.jboss.naming:org.jnp.interfaces</value>
+ </entry>
+ </map>
+ </property>
+ </bean>
+
+ <bean name="b1" class="org.jboss.ejb3.embedded.JndiBinder">
+ <property name="jndiProperties"><inject bean="InitialContextProperties"/></property>
+ <property name="target"><inject bean="jboss.mq:service=JMSProviderLoader,name=JMSProvider"/></property>
+ <property name="bindTo">java:/DefaultJMSProvider</property>
+ <property name="serializable">true</property>
+ </bean>
+
+ <bean name="jboss.mq:service=ServerSessionPoolMBean,name=StdJMSPool" class="org.jboss.jms.asf.StdServerSessionPoolFactory">
+ <property name="name">StdJMSPool</property>
+ <property name="xidFactory"><inject bean="XidFactoryMBean"/></property>
+ <property name="transactionManager"><inject bean="TransactionManager"/></property>
+ </bean>
+
+ <bean name="b2" class="org.jboss.ejb3.embedded.JndiBinder">
+ <property name="jndiProperties"><inject bean="InitialContextProperties"/></property>
+ <property name="target"><inject bean="jboss.mq:service=ServerSessionPoolMBean,name=StdJMSPool"/></property>
+ <property name="bindTo">java:/StdJMSPool</property>
+ <property name="serializable">false</property>
+ </bean>
+
+
+ <bean name="jboss.mq:service=PersistenceManager" class="org.jboss.mq.pm.none.PersistenceManager">
+ </bean>
+
+ <bean name="jboss.mq:service=MessageCache" class="org.jboss.mq.kernel.MessageCache">
+ <property name="persistenceManager"><inject bean="jboss.mq:service=PersistenceManager"/></property>
+ <property name="highMemoryMark">50</property>
+ <property name="maxMemoryMark">60</property>
+ </bean>
+
+ <bean name="jms-rar-WorkManager" class="org.jboss.ejb3.embedded.resource.JBossWorkManager">
+ </bean>
+
+ <bean name="jms-rar-DeploymentInfo" class="org.jboss.ejb3.embedded.resource.Ejb3DeploymentInfo">
+ <constructor>
+ <parameter class="java.lang.String">jms-ra.rar</parameter>
+ <parameter class="java.lang.String">javax.jms.MessageListener</parameter>
+ <parameter class="java.lang.String">org.jboss.resource.adapter.jms.inflow.JmsActivationSpec</parameter>
+ </constructor>
+ </bean>
+
+ <bean name="jboss.jca:name='jms-ra.rar',service=RARDeployment" class="org.jboss.ejb3.embedded.resource.RARDeployment">
+ <constructor>
+ <parameter class="org.jboss.deployment.DeploymentInfo">
+ <inject bean="jms-rar-DeploymentInfo"/>
+ </parameter>
+ </constructor>
+ <property name="workManager"><inject bean="jms-rar-WorkManager"/></property>
+ </bean>
+
+ <bean name="jboss.mq:service=StateManager" class="org.jboss.mq.sm.none.NullStateManager">
+ </bean>
+
+ <bean name="BasicQueueParameters" class="org.jboss.mq.server.BasicQueueParameters"/>
+
+ <bean name="jboss.mq:service=ThreadPool" class="org.jboss.util.threadpool.BasicThreadPool">
+ <property name="name">JMSThread</property>
+ <property name="threadGroupName">JBossMQ Server Threads</property>
+ <!-- The max number of threads in the pool -->
+ <property name="maximumPoolSize">10</property>
+ <!-- The max number of tasks before the queue is full -->
+ <property name="maximumQueueSize">1000</property>
+ <!-- The behavior of the pool when a task is added and the queue is full.
+ abort - a RuntimeException is thrown
+ run - the calling thread executes the task
+ wait - the calling thread blocks until the queue has room
+ discard - the task is silently discarded without being run
+ discardOldest - check to see if a task is about to complete and enque
+ the new task if possible, else run the task in the calling thread
+ -->
+ <property name="blockingMode">run</property>
+ </bean>
+
+ <bean name="jboss.mq:service=DestinationManager" class="org.jboss.mq.server.JMSDestinationManager">
+ <constructor>
+ <parameter class="org.jboss.mq.server.BasicQueueParameters">
+ <inject bean="BasicQueueParameters"/>
+ </parameter>
+ </constructor>
+ <property name="persistenceManager"><inject bean="jboss.mq:service=PersistenceManager"/></property>
+ <property name="messageCache"><inject bean="jboss.mq:service=MessageCache"/></property>
+ <property name="stateManager"><inject bean="jboss.mq:service=StateManager"/></property>
+ <property name="threadPool"><inject bean="jboss.mq:service=ThreadPool"/></property>
+ <property name="threadGroup"><inject bean="jboss.mq:service=ThreadPool" property="threadGroup"/></property>
+ <start method="startServer"/>
+ <stop method="stopServer"/>
+ </bean>
+
+ <bean name="jboss.mq.destination:service=Queue,name=DLQ" class="org.jboss.mq.kernel.Queue">
+ <property name="destinationManagerPojo"><inject bean="jboss.mq:service=DestinationManager"/></property>
+ <property name="initialContextProperties"><inject bean="InitialContextProperties"/></property>
+ <property name="destinationName">DLQ</property>
+ </bean>
+
+ <bean name="jboss.mq:service=Invoker" class="org.jboss.mq.server.JMSServerInvoker">
+ <property name="next"><inject bean="jboss.mq:service=DestinationManager"/></property>
+ </bean>
+
+ <bean name="jboss.mq:service=invocationlayer,type=JVM" class="org.jboss.mq.kernel.JVMIL">
+ <property name="jmsInvoker"><inject bean="jboss.mq:service=Invoker"/></property>
+ <!-- notice we actually switched - the non-xa connection factory JNDI Ref is the JNDI name our EJBs use -->
+ <!-- the embedded EJB container doesn't support XA, so the connection factory our JmsXA JNDI lookup will return will be a non-XA factory -->
+ <property name="connectionFactoryJNDIRef">java:/JmsXA</property>
+ <property name="XAConnectionFactoryJNDIRef">java:/ConnectionFactory</property>
+ <property name="pingPeriod">0</property>
+ <property name="initialContextProperties"><inject bean="InitialContextProperties"/></property>
+ </bean>
+
+</deployment>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/jbossas-oracle-ds.xml b/modules/enterprise/server/itests-2/src/test/resources/jbossas-oracle-ds.xml
new file mode 100644
index 0000000..8906dca
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/jbossas-oracle-ds.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<datasources xmlns="http://www.jboss.org/ironjacamar/schema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.jboss.org/ironjacamar/schema http://docs.jboss.org/ironjacamar/schema/datasources_1_0.xsd">
+
+ <xa-datasource jndi-name="java:jboss/datasources/RHQDS" pool-name="RHQDS" enabled="true" use-java-context="true">
+
+ <xa-datasource-property name="URL">${rhq.test.ds.connection-url}</xa-datasource-property>
+ <xa-datasource-property name="ConnectionProperties">SetBigStringTryClob=true</xa-datasource-property>
+ <driver>oracle</driver>
+ <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
+ <xa-pool>
+ <min-pool-size>5</min-pool-size>
+ <max-pool-size>50</max-pool-size>
+ <is-same-rm-override>false</is-same-rm-override>
+ <no-tx-separate-pools />
+ </xa-pool>
+ <security>
+ <security-domain>RHQDSSecurityDomain</security-domain>
+ </security>
+ <validation>
+ <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker" />
+ <stale-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleStaleConnectionChecker" />
+ <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter" />
+ </validation>
+ <timeout>
+ <blocking-timeout-millis>30000</blocking-timeout-millis>
+ <idle-timeout-minutes>15</idle-timeout-minutes>
+ </timeout>
+ <statement>
+ <prepared-statement-cache-size>75</prepared-statement-cache-size>
+ </statement>
+ </xa-datasource>
+
+</datasources>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/jbossas-postgres-ds.xml b/modules/enterprise/server/itests-2/src/test/resources/jbossas-postgres-ds.xml
new file mode 100644
index 0000000..23db62c
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/jbossas-postgres-ds.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<datasources
+ xmlns="http://www.jboss.org/ironjacamar/schema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.jboss.org/ironjacamar/schema
+ http://docs.jboss.org/ironjacamar/schema/datasources_1_0.xsd">
+
+ <xa-datasource
+ jndi-name="java:jboss/datasources/RHQDS"
+ pool-name="RHQDS"
+ enabled="true"
+ use-java-context="true">
+
+ <xa-datasource-property name="DatabaseName">${rhq.test.ds.db-name}</xa-datasource-property>
+ <xa-datasource-property name="PortNumber">${rhq.test.ds.port}</xa-datasource-property>
+ <xa-datasource-property name="ServerName">${rhq.test.ds.server-name}</xa-datasource-property>
+ <driver>postgres</driver>
+ <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
+ <xa-pool>
+ <min-pool-size>5</min-pool-size>
+ <max-pool-size>50</max-pool-size>
+ </xa-pool>
+ <security>
+ <security-domain>RHQDSSecurityDomain</security-domain>
+ </security>
+ <validation>
+ <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker" />
+ <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter" />
+ </validation>
+ <timeout>
+ <blocking-timeout-millis>30000</blocking-timeout-millis>
+ <idle-timeout-minutes>15</idle-timeout-minutes>
+ </timeout>
+ <statement>
+ <prepared-statement-cache-size>75</prepared-statement-cache-size>
+ </statement>
+ </xa-datasource>
+
+</datasources>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/log4j.xml b/modules/enterprise/server/itests-2/src/test/resources/log4j.xml
new file mode 100644
index 0000000..e65d303
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/log4j.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- Log4j Configuration -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<!-- $Id: log4j.xml 39945 2006-01-12 02:44:07Z bill $ -->
+
+<!--
+ | For more configuration information and examples see the Jakarta Log4j
+ | website: http://jakarta.apache.org/log4j
+ -->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
+
+ <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+ <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
+ <param name="Target" value="System.out"/>
+ <param name="Threshold" value="ERROR"/>
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <!-- The default pattern: Date Priority [Category] Messagen -->
+ <!--
+ <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
+ -->
+ <param name="ConversionPattern" value="%-5p %d{dd-MM HH:mm:ss,SSS} [%c] (%F:%M:%L) -%m%n"/>
+ </layout>
+ </appender>
+
+ <appender name="FILE" class="org.apache.log4j.RollingFileAppender">
+ <param name="File" value="target/server-jar-test.log"/>
+ <param name="Threshold" value="WARN"/>
+ <param name="Append" value="false"/>
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <!-- The default pattern: Date Priority [Category] Messagen -->
+ <!--
+ <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
+ -->
+ <param name="ConversionPattern" value="%-5p %d{dd-MM HH:mm:ss,SSS} [%c] (%F:%M:%L) -%m%n"/>
+ </layout>
+ </appender>
+
+ <category name="STDOUT" additivity="false">
+ <priority value="INFO"/>
+ </category>
+
+ <category name="STDERR" additivity="false">
+ <priority value="ERROR"/>
+ </category>
+
+ <category name="org">
+ <priority value="WARN"/>
+ </category>
+
+ <category name="org.rhq">
+ <priority value="DEBUG"/>
+ </category>
+
+ <category name="org.rhq.enterprise.server.scheduler.SchedulerService">
+ <priority value="WARN"/>
+ </category>
+
+ <category name="org.rhq.enterprise.server.configuration.ConfigurationManagerBean">
+ <priority value="WARN"/>
+ </category>
+
+ <!-- Hibernate logs WARNINGS frequent from this class, in test envs. -->
+ <category name="org.hibernate.hql.ast.QueryTranslatorImpl">
+ <priority value="ERROR"/>
+ </category>
+
+ <!-- hides the TIMER SERVICE IS NOT INSTALLED warning - we know embedded EJB3 container doesn't support timers -->
+ <category name="org.jboss.ejb3.timerservice.jboss.JBossTimerServiceFactory">
+ <priority value="ERROR"/>
+ </category>
+
+ <!-- hides the shutdown warnings - for some reason, the container spits out some warnings when shutting down -->
+ <category name="org.jboss.kernel.plugins.dependency.StartStopLifecycleAction">
+ <priority value="ERROR"/>
+ </category>
+
+ <!-- Hibernate SQL logs -->
+ <!--
+ <category name="org.hibernate.SQL">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <root>
+ <appender-ref ref="CONSOLE"/>
+ <appender-ref ref="FILE"/>
+ </root>
+
+</log4j:configuration>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/logging/log4j.properties b/modules/enterprise/server/itests-2/src/test/resources/logging/log4j.properties
new file mode 100644
index 0000000..4e7a50d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/logging/log4j.properties
@@ -0,0 +1,17 @@
+log4j.rootCategory=INFO, FILE
+
+log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.FILE.DatePattern='.'yyyy-MM-dd
+log4j.appender.FILE.File=./target/unit-test.log
+log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
+log4j.appender.FILE.layout.ConversionPattern=%d{ABSOLUTE} %-5p %c %m%n
+#log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
+log4j.appender.FILE.Append=false
+
+# turn the following on...
+#log4j.logger.com.jboss=INFO
+#log4j.logger.org.jbpm=TRACE
+
+# and the following off...
+# without turning this down you get a spurious "couldn't set xml parser property" warning.
+#log4j.logger.org.jbpm.jpdl.xml.JpdlParser=ERROR
diff --git a/modules/enterprise/server/itests-2/src/test/resources/login-config.xml b/modules/enterprise/server/itests-2/src/test/resources/login-config.xml
new file mode 100644
index 0000000..645294d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/login-config.xml
@@ -0,0 +1,72 @@
+<?xml version='1.0'?>
+
+<!DOCTYPE policy PUBLIC
+ "-//JBoss//DTD JBOSS Security Config 3.0//EN"
+ "http://www.jboss.org/j2ee/dtd/security_config.dtd">
+
+<!-- The XML based JAAS login configuration read by the
+org.jboss.security.auth.login.XMLLoginConfig mbean. Add
+an application-policy element for each security domain.
+
+The outline of the application-policy is:
+<application-policy name="security-domain-name">
+ <authentication>
+ <login-module code="login.module1.class.name" flag="control_flag">
+ <module-option name = "option1-name">option1-value</module-option>
+ <module-option name = "option2-name">option2-value</module-option>
+ ...
+ </login-module>
+
+ <login-module code="login.module2.class.name" flag="control_flag">
+ ...
+ </login-module>
+ ...
+ </authentication>
+</application-policy>
+
+$Revision: 42748 $
+-->
+
+<policy>
+ <!-- Used by clients within the application server VM such as
+ mbeans and servlets that access EJBs.
+ -->
+ <application-policy name="client-login">
+ <authentication>
+ <login-module code="org.jboss.security.ClientLoginModule"
+ flag="required">
+ <!-- Any existing security context will be restored on logout -->
+ <module-option name="restore-login-identity">true</module-option>
+ </login-module>
+ </authentication>
+ </application-policy>
+
+ <application-policy name = "jbossmq">
+ <authentication>
+ <login-module code = "org.jboss.mq.sm.file.DynamicLoginModule" flag = "required">
+ <module-option name = "unauthenticatedIdentity">guest</module-option>
+ <module-option name = "sm.objectname">jboss.mq:service=StateManager</module-option>
+ </login-module>
+ </authentication>
+ </application-policy>
+
+ <application-policy name="other">
+ <!-- A simple server login module, which can be used when the number
+ of users is relatively small. It uses two properties files:
+ users.properties, which holds users (key) and their password (value).
+ roles.properties, which holds users (key) and a comma-separated list of
+ their roles (value).
+ The unauthenticatedIdentity property defines the name of the principal
+ that will be used when a null username and password are presented as is
+ the case for an unuathenticated web client or MDB. If you want to
+ allow such users to be authenticated add the property, e.g.,
+ unauthenticatedIdentity="nobody"
+ -->
+ <authentication>
+ <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
+ flag="required"/>
+ </authentication>
+ </application-policy>
+
+</policy>
+
diff --git a/modules/enterprise/server/itests-2/src/test/resources/obsolete/embedded-jboss-beans.xml b/modules/enterprise/server/itests-2/src/test/resources/obsolete/embedded-jboss-beans.xml
new file mode 100644
index 0000000..85e2fb3
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/obsolete/embedded-jboss-beans.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
+ xmlns="urn:jboss:bean-deployer:2.0">
+
+ <!-- This installs a custom initial context factory builder into the JVM
+ that will ensure that all the default InitialContexts are going to check
+ for the permission to access the RHQ internals. -->
+ <bean class="org.rhq.jndi.mbean.AccessCheckingInitialContextFactoryBuilderInstaller"
+ name="AccessCheckingInitialContextFactoryBuilderInstaller">
+ </bean>
+
+
+ <bean name="Naming" class="org.jnp.server.SingletonNamingServer"/>
+
+ <bean name="InitialContextProperties" class="java.util.Hashtable">
+ <constructor>
+ <parameter class="java.util.Map">
+ <map keyClass="java.lang.String" valueClass="java.lang.String">
+ <entry>
+ <key>java.naming.factory.initial</key>
+ <value>org.jnp.interfaces.LocalOnlyContextFactory</value>
+ </entry>
+ <entry>
+ <key>java.naming.factory.url.pkgs</key>
+ <value>org.jboss.naming:org.jnp.interfaces</value>
+ </entry>
+ </map>
+ </parameter>
+ </constructor>
+ </bean>
+
+ <bean name="java:comp/Initializer" class="org.jboss.ejb3.embedded.JavaCompInitializer">
+ <property name="jndiProperties">
+ <inject bean="InitialContextProperties"/>
+ </property>
+ </bean>
+
+ <bean name="XidFactory" class="org.jboss.tm.XidFactoryImpl"/>
+
+ <bean name="XidFactoryMBean" class="org.jboss.ejb3.embedded.XidFactoryMBean">
+ <constructor>
+ <parameter class="org.jboss.tm.XidFactoryBase">
+ <inject bean="XidFactory"/>
+ </parameter>
+ </constructor>
+ </bean>
+
+ <bean name="TransactionManagerInitializer" class="org.jboss.tm.TransactionManagerInitializer">
+ <property name="xidFactory">
+ <inject bean="XidFactory"/>
+ </property>
+ <property name="initialContextProperties">
+ <inject bean="InitialContextProperties"/>
+ </property>
+ </bean>
+
+ <bean name="UserTransaction" class="org.jboss.ejb3.embedded.UserTransactionImpl">
+ <demand>TransactionManagerInitializer</demand>
+ </bean>
+
+ <bean name="UserTransactionBinding" class="org.jboss.ejb3.embedded.JndiBinder">
+ <property name="jndiProperties">
+ <inject bean="InitialContextProperties"/>
+ </property>
+ <property name="target">
+ <inject bean="UserTransaction"/>
+ </property>
+ <property name="bindTo">UserTransaction</property>
+ <property name="serializable">false</property>
+ </bean>
+
+
+ <bean name="TransactionManager" class="java.lang.Object">
+ <constructor factoryMethod="getTransactionManager">
+ <factory bean="TransactionManagerInitializer"/>
+ </constructor>
+ </bean>
+ <bean name="CachedConnectionManager" class="org.jboss.resource.connectionmanager.CachedConnectionManagerReference">
+ <property name="transactionManager">
+ <inject bean="TransactionManager"/>
+ </property>
+ </bean>
+
+ <bean name="RHQDSBootstrap" class="org.jboss.resource.adapter.jdbc.local.LocalTxDataSource">
+ <property name="driverClass">${rhq.test.ds.driver-class}</property>
+ <property name="connectionURL">${rhq.test.ds.connection-url}</property>
+ <property name="userName">${rhq.test.ds.user-name}</property>
+ <property name="password">${rhq.test.ds.password}</property>
+ <property name="jndiName">java:/RHQDS</property>
+ <property name="minSize">0</property>
+ <property name="maxSize">20</property>
+ <property name="blockingTimeout">3000</property>
+ <property name="idleTimeout">100000</property>
+ <property name="transactionManager">
+ <inject bean="TransactionManager"/>
+ </property>
+ <property name="cachedConnectionManager">
+ <inject bean="CachedConnectionManager"/>
+ </property>
+ <property name="initialContextProperties">
+ <inject bean="InitialContextProperties"/>
+ </property>
+ </bean>
+
+ <bean name="RHQDS" class="java.lang.Object">
+ <constructor factoryMethod="getDatasource">
+ <factory bean="RHQDSBootstrap"/>
+ </constructor>
+ </bean>
+
+ <!-- needed for Quartz' no-TX data source (even though this is a local-tx, seems like Quartz is still working) -->
+ <bean name="NoTxRHQDSBootstrap" class="org.jboss.resource.adapter.jdbc.local.LocalTxDataSource">
+ <property name="driverClass">${rhq.test.ds.driver-class}</property>
+ <property name="connectionURL">${rhq.test.ds.connection-url}</property>
+ <property name="userName">${rhq.test.ds.user-name}</property>
+ <property name="password">${rhq.test.ds.password}</property>
+ <property name="jndiName">java:/NoTxRHQDS</property>
+ <property name="minSize">0</property>
+ <property name="maxSize">10</property>
+ <property name="blockingTimeout">1000</property>
+ <property name="idleTimeout">100000</property>
+ <property name="transactionManager">
+ <inject bean="TransactionManager"/>
+ </property>
+ <property name="cachedConnectionManager">
+ <inject bean="CachedConnectionManager"/>
+ </property>
+ <property name="initialContextProperties">
+ <inject bean="InitialContextProperties"/>
+ </property>
+ </bean>
+
+ <bean name="NoTxRHQDS" class="java.lang.Object">
+ <constructor factoryMethod="getDatasource">
+ <factory bean="NoTxRHQDSBootstrap"/>
+ </constructor>
+ </bean>
+
+ <bean name="DefaultDSBootstrap" class="org.jboss.resource.adapter.jdbc.local.LocalTxDataSource">
+ <property name="driverClass">org.hsqldb.jdbcDriver</property>
+ <property name="connectionURL">jdbc:hsqldb:.</property>
+ <!-- <property name="connectionURL">jdbc:hsqldb:./hypersonic/localDB</property> -->
+ <property name="userName">sa</property>
+ <property name="jndiName">java:/DefaultDS</property>
+ <property name="minSize">0</property>
+ <property name="maxSize">10</property>
+ <property name="blockingTimeout">1000</property>
+ <property name="idleTimeout">100000</property>
+ <property name="transactionManager">
+ <inject bean="TransactionManager"/>
+ </property>
+ <property name="cachedConnectionManager">
+ <inject bean="CachedConnectionManager"/>
+ </property>
+ <property name="initialContextProperties">
+ <inject bean="InitialContextProperties"/>
+ </property>
+ </bean>
+
+ <bean name="DefaultDS" class="java.lang.Object">
+ <constructor factoryMethod="getDatasource">
+ <factory bean="DefaultDSBootstrap"/>
+ </constructor>
+ </bean>
+
+</deployment>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/obsolete/testng.bak.xml b/modules/enterprise/server/itests-2/src/test/resources/obsolete/testng.bak.xml
new file mode 100644
index 0000000..1452edb
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/obsolete/testng.bak.xml
@@ -0,0 +1,12 @@
+<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
+
+<suite name="EJB3 Testsuite" >
+ <test name="EJB3 tests" >
+ <groups>
+ <run>
+ <include name="integration.ejb3"/>
+ </run>
+ </groups>
+
+ </test>
+</suite>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.xml
new file mode 100644
index 0000000..475cd0a
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.xml
@@ -0,0 +1,84 @@
+<dataset>
+ <rhq_resource_type id="1"
+ name="AlertManagerBeanTest_Platform"
+ plugin="AlertManagerBeanTest_Plugin"
+ category="PLATFORM"
+ creation_data_type="CONFIGURATION"
+ create_delete_policy="BOTH"
+ singleton="false"
+ supports_manual_add="false"
+ deleted="false"/>
+
+ <rhq_resource id="1"
+ resource_key="1"
+ name="test1"
+ resource_type_id="1"
+ uuid="-10000000000000000000000000000000000"
+ inventory_status="COMMITTED"
+ connected="false"/>
+
+ <rhq_alert_definition id="1"
+ name="alerttest"
+ enabled="true"
+ priority="HIGH"
+ resource_id="1"
+ dampening_category="0"
+ dampening_value="0"
+ dampening_period="0"
+ required="1"
+ recovery_id="0"
+ ctime="12345"
+ mtime="12345"/>
+ <rhq_alert_definition id="2"
+ name="delete_by_type_def"
+ enabled="true"
+ priority="HIGH"
+ resource_type_id="1"
+ dampening_category="0"
+ dampening_value="0"
+ dampening_period="0"
+ required="1"
+ recovery_id="0"
+ ctime="12345"
+ mtime="12345"/>
+
+ <rhq_alert_condition id="1"
+ alert_definition_id="1"
+ type="AVAILABILITY"
+ comparator="=="/>
+ <rhq_alert_condition id="2"
+ alert_definition_id="2"
+ type="AVAILABILITY"
+ comparator="=="/>
+
+ <rhq_alert id="1"
+ alert_definition_id="1"
+ ctime="12345"
+ recovery_id="0"/>
+ <rhq_alert id="2"
+ alert_definition_id="2"
+ ctime="12345"
+ recovery_id="0"/>
+
+ <rhq_alert_condition_log id="1"
+ ctime="12345"
+ condition_id="1"
+ value="dummy value"
+ alert_id="1"/>
+ <rhq_alert_condition_log id="2"
+ ctime="12345"
+ condition_id="2"
+ value="dummy value"
+ alert_id="2"/>
+
+ <rhq_alert_notif_log id="1"
+ alert_id="1"
+ sender="dummy"
+ result_state="SUCCESS"
+ message="message"/>
+ <rhq_alert_notif_log id="2"
+ alert_id="2"
+ sender="dummy"
+ result_state="SUCCESS"
+ message="message"/>
+</dataset>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/configuration/metadata/configuration_metadata_manager_bean_test_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/configuration/metadata/configuration_metadata_manager_bean_test_v1.xml
new file mode 100644
index 0000000..bd04beb
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/configuration/metadata/configuration_metadata_manager_bean_test_v1.xml
@@ -0,0 +1,95 @@
+<plugin name="ConfigurationMetadataManagerBeanTest"
+ package="org.rhq.enterprise.server.confiuguration.metadata"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="MyServer1">
+ <plugin-configuration>
+ <c:simple-property name="myExistingProperty"
+ type="integer"
+ units="megabytes"
+ default="256"
+ required="true"
+ description="My Existing Property"/>
+
+ <c:simple-property name="v1OnlyProperty"
+ description="This property exists only in version 1 of the plugin"/>
+ </plugin-configuration>
+ </server>
+
+ <server name="ServerWithAddedOptions">
+ <plugin-configuration>
+ <c:simple-property name="mySimple"/>
+ </plugin-configuration>
+ </server>
+
+ <server name="GroupTests">
+ <plugin-configuration>
+ <c:group name="existingGroup">
+ <c:simple-property name="existingGroupProperty"/>
+ </c:group>
+ </plugin-configuration>
+ </server>
+
+ <server name="UpdatedPropertyList">
+ <plugin-configuration>
+ <c:list-property name="myList"
+ displayName="My Test List"
+ readOnly="false"
+ description="Update Property List Test"
+ required="true"
+ min="1"
+ max="5">
+ <c:simple-property name="myListMember"
+ type="double"
+ default="3.14"
+ description="PI"/>
+ </c:list-property>
+ </plugin-configuration>
+ </server>
+
+ <server name="UnchangedMap">
+ <plugin-configuration>
+ <c:map-property name="myMap">
+ <c:simple-property name="property1ToKeep"/>
+ <c:simple-property name="property2ToKeep"/>
+ </c:map-property>
+ </plugin-configuration>
+ </server>
+
+ <server name="UpdatedMapWithAddRemoveProperty">
+ <plugin-configuration>
+ <c:map-property name="myMap">
+ <c:simple-property name="property1ToKeep"/>
+ <c:simple-property name="property1ToRemove"/>
+ <c:simple-property name="property2ToKeep"/>
+ <c:simple-property name="property2ToRemove"/>
+ </c:map-property>
+ </plugin-configuration>
+ </server>
+
+ <server name="UpdatedMapWithUpdatedProperty">
+ <plugin-configuration>
+ <c:map-property name="myMap">
+ <c:simple-property name="propertyToUpdate"
+ default="ten"
+ required="false"/>
+ </c:map-property>
+ </plugin-configuration>
+ </server>
+
+ <server name="OptionSourceTest">
+ <plugin-configuration>
+ <c:simple-property name="prop1">
+ <c:property-options>
+ <c:option value="value1"/>
+ </c:property-options>
+ <c:option-source target="resource" expression="resourceType=DomainDeployment,plugin=as7"
+ filter="*.jdbc" linkToTarget="false"/>
+ </c:simple-property>
+ <c:simple-property name="prop2"/>
+ </plugin-configuration>
+ </server>
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/configuration/metadata/configuration_metadata_manager_bean_test_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/configuration/metadata/configuration_metadata_manager_bean_test_v2.xml
new file mode 100644
index 0000000..0d23ac7
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/configuration/metadata/configuration_metadata_manager_bean_test_v2.xml
@@ -0,0 +1,120 @@
+<plugin name="ConfigurationMetadataManagerBeanTest"
+ package="org.rhq.enterprise.server.confiuguration.metadata"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="MyServer1">
+ <plugin-configuration>
+ <c:simple-property name="myExistingProperty"
+ type="integer"
+ units="megabytes"
+ default="256"
+ required="true"
+ description="My Existing Property"/>
+
+ <c:simple-property name="newUngroupedProperty"
+ description="A new, ungrouped property"
+ activationPolicy="immediate"
+ default="new property"
+ required="true"
+ displayName="My New Ungrouped Property"
+ readOnly="true"
+ type="longString"
+ summary="false"/>
+ </plugin-configuration>
+ </server>
+
+ <server name="ServerWithAddedOptions">
+ <plugin-configuration>
+ <c:simple-property name="mySimple">
+ <c:property-options>
+ <c:option name="x" value="1"/>
+ <c:option name="y" value="2"/>
+ </c:property-options>
+ </c:simple-property>
+ </plugin-configuration>
+ </server>
+
+ <server name="GroupTests">
+ <plugin-configuration>
+ <c:group name="existingGroup">
+ <c:simple-property name="existingGroupProperty"/>
+ </c:group>
+
+ <c:group name="newGroup">
+ <c:simple-property name="newGroupProperty"
+ description="A new, grouped property"
+ activationPolicy="immediate"
+ default="new grouped property"
+ displayName="New Group Property"
+ readOnly="true"/>
+ </c:group>
+ </plugin-configuration>
+ </server>
+
+ <server name="UpdatedPropertyList">
+ <plugin-configuration>
+ <c:list-property name="myList"
+ displayName="My Test List"
+ readOnly="false"
+ description="Update Property List Test"
+ required="true"
+ min="1"
+ max="5">
+ <c:map-property name="myMap">
+ <c:simple-property name="myListMember"
+ type="double"
+ default="3.14"
+ description="PI"/>
+ </c:map-property>
+ </c:list-property>
+ </plugin-configuration>
+ </server>
+
+ <server name="UnchangedMap">
+ <plugin-configuration>
+ <c:map-property name="myMap">
+ <c:simple-property name="property1ToKeep"/>
+ <c:simple-property name="property2ToKeep"/>
+ </c:map-property>
+ </plugin-configuration>
+ </server>
+
+ <server name="UpdatedMapWithAddRemoveProperty">
+ <plugin-configuration>
+ <c:map-property name="myMap">
+ <c:simple-property name="property1ToKeep"/>
+ <c:simple-property name="propertyToAdd"/>
+ <c:simple-property name="property2ToKeep"/>
+ </c:map-property>
+ </plugin-configuration>
+ </server>
+
+ <server name="UpdatedMapWithUpdatedProperty">
+ <plugin-configuration>
+ <c:map-property name="myMap">
+ <c:simple-property name="propertyToUpdate"
+ type="integer"
+ default="10"
+ required="true"/>
+ </c:map-property>
+ </plugin-configuration>
+ </server>
+ <server name="OptionSourceTest">
+ <plugin-configuration>
+ <c:simple-property name="prop1">
+ <c:option-source target="resource" expression="resourceType=DomainDeployment,plugin=as7"
+ linkToTarget="false"/>
+ </c:simple-property>
+ <c:simple-property name="prop2">
+ <c:property-options>
+ <c:option value="value2"/>
+ </c:property-options>
+ <c:option-source target="resource" expression="*"/>
+ </c:simple-property>
+ </plugin-configuration>
+ </server>
+
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.xml
new file mode 100644
index 0000000..4891276
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.xml
@@ -0,0 +1,98 @@
+<dataset>
+ <rhq_agent id="1"
+ name="TestAgent-dbbt"
+ address="0.0.0.0"
+ port="16163"
+ remote_endpoint="http://here"
+ agenttoken="tok"
+ backfilled="0"
+ ctime="123456"
+ mtime="123456"/>
+
+ <rhq_config_def/>
+ <rhq_config_prop_def/>
+ <rhq_config_pd_osrc/>
+ <rhq_conf_prop_def_enum/>
+ <rhq_config_prop_constr/>
+
+ <rhq_config/>
+ <rhq_config_property/>
+ <rhq_config_template/>
+
+ <rhq_resource_type id="1"
+ name="test platform"
+ category="PLATFORM"
+ creation_data_type="CONFIGURATION"
+ create_delete_policy="BOTH"
+ supports_manual_add="1"
+ singleton="0"
+ plugin="test"
+ deleted="0"/>
+ <rhq_resource_type id="2"
+ name="test server"
+ category="SERVER"
+ creation_data_type="CONFIGURATION"
+ create_delete_policy="BOTH"
+ supports_manual_add="1"
+ singleton="0"
+ plugin="test"
+ deleted="0"/>
+ <rhq_resource_type id="3"
+ name="test service 1"
+ category="SERVICE"
+ creation_data_type="CONFIGURATION"
+ create_delete_policy="BOTH"
+ supports_manual_add="1"
+ singleton="0"
+ plugin="test"
+ deleted="0"/>
+ <rhq_resource_type id="4"
+ name="test service 2"
+ category="SERVICE"
+ creation_data_type="CONFIGURATION"
+ create_delete_policy="BOTH"
+ supports_manual_add="1"
+ singleton="1"
+ plugin="test"
+ deleted="0"/>
+
+ <rhq_resource_type_parents resource_type_id="2"
+ parent_resource_type_id="1"/>
+ <rhq_resource_type_parents resource_type_id="3"
+ parent_resource_type_id="2"/>
+ <rhq_resource_type_parents resource_type_id="4"
+ parent_resource_type_id="2"/>
+
+ <rhq_process_scan/>
+ <rhq_event_def/>
+ <rhq_measurement_def/>
+ <rhq_operation_def/>
+ <rhq_package_type/>
+ <rhq_bundle_type/>
+ <rhq_resource/>
+ <rhq_resource_subcat/>
+ <rhq_resource_group/>
+ <rhq_prd_ver/>
+ <rhq_alert_definition/>
+ <rhq_alert_condition/>
+ <rhq_alert/>
+ <rhq_alert_condition_log/>
+ <rhq_alert_notif_log/>
+ <rhq_availability/>
+ <rhq_measurement_sched/>
+ <rhq_content_source/>
+ <rhq_package/>
+ <rhq_bundle/>
+ <rhq_drift_def_template/>
+
+ <rhq_plugin id="1"
+ deployment="AGENT"
+ name="test"
+ display_name="test"
+ enabled="1"
+ status="INSTALLED"
+ path="/plugins/test.jar"
+ md5="1234567"
+ ctime="12345"
+ mtime="123456"/>
+</dataset>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-1.txt b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-1.txt
new file mode 100644
index 0000000..fec744d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-1.txt
@@ -0,0 +1,5 @@
+test-1
+/test
+C
+dir 1
+aaaaa 0 filename.ext A
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-1.zip b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-1.zip
new file mode 100644
index 0000000..6dd62f5
Binary files /dev/null and b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-1.zip differ
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-2.txt b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-2.txt
new file mode 100644
index 0000000..af59629
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-2.txt
@@ -0,0 +1,5 @@
+test-1
+/test
+D
+dir 1
+bbbbb aaaaa filename.ext C
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-2.zip b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-2.zip
new file mode 100644
index 0000000..95e7a76
Binary files /dev/null and b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/drift/changeset-2.zip differ
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/inventory/InventoryManagerBeanTest.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/inventory/InventoryManagerBeanTest.xml
new file mode 100644
index 0000000..1c177c7
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/inventory/InventoryManagerBeanTest.xml
@@ -0,0 +1,121 @@
+<dataset>
+ <rhq_config_def/>
+ <rhq_config_prop_def/>
+ <rhq_config_pd_osrc/>
+ <rhq_conf_prop_def_enum/>
+ <rhq_config_prop_constr/>
+
+ <rhq_config/>
+ <rhq_config_property/>
+ <rhq_config_template/>
+
+ <rhq_resource_type id="1"
+ name="TestServer1"
+ category="SERVER"
+ creation_data_type="CONFIGURATION"
+ create_delete_policy="BOTH"
+ supports_manual_add="1"
+ singleton="0"
+ plugin="TestPlugin1"
+ deleted="0"/>
+ <rhq_resource_type id="2"
+ name="TestService1"
+ category="SERVICE"
+ creation_data_type="CONFIGURATION"
+ create_delete_policy="BOTH"
+ supports_manual_add="1"
+ singleton="0"
+ plugin="TestPlugin1"
+ deleted="0"/>
+ <rhq_resource_type id="3"
+ name="TestService2"
+ category="SERVICE"
+ creation_data_type="CONFIGURATION"
+ create_delete_policy="BOTH"
+ supports_manual_add="1"
+ singleton="0"
+ plugin="TestPlugin1"
+ deleted="0"/>
+ <rhq_resource_type id="4"
+ name="TestServer2"
+ category="SERVER"
+ creation_data_type="CONFIGURATION"
+ create_delete_policy="BOTH"
+ supports_manual_add="1"
+ singleton="0"
+ plugin="TestPlugin1"
+ deleted="0"/>
+ <rhq_resource_type id="5"
+ name="TestService3"
+ category="SERVICE"
+ creation_data_type="CONFIGURATION"
+ create_delete_policy="BOTH"
+ supports_manual_add="1"
+ singleton="0"
+ plugin="TestPlugin1"
+ deleted="0"/>
+ <rhq_resource_type id="6"
+ name="TestServer3"
+ category="SERVER"
+ creation_data_type="CONFIGURATION"
+ create_delete_policy="BOTH"
+ supports_manual_add="1"
+ singleton="0"
+ plugin="TestPlugin1"
+ deleted="0"/>
+
+
+ <rhq_resource_type_parents resource_type_id="2"
+ parent_resource_type_id="1"/>
+ <rhq_resource_type_parents resource_type_id="3"
+ parent_resource_type_id="1"/>
+ <rhq_resource_type_parents resource_type_id="5"
+ parent_resource_type_id="2"/>
+
+
+ <rhq_process_scan/>
+ <rhq_event_def/>
+ <rhq_measurement_def/>
+ <rhq_operation_def/>
+ <rhq_package_type/>
+ <rhq_bundle_type/>
+
+ <rhq_resource id="1"
+ resource_type_id="1"
+ name="TestServer1"
+ uuid="test-server-1"
+ resource_key="test-server-1"
+ connected="1"/>
+ <rhq_resource id="2"
+ resource_type_id="2"
+ name="TestService1"
+ uuid="test-service-1"
+ resource_key="test-service-1"
+ connected="1"
+ parent_resource_id="1"/>
+
+ <rhq_resource_subcat/>
+ <rhq_resource_group/>
+ <rhq_resource_group_res_imp_map/>
+ <rhq_resource_group_res_exp_map/>
+ <rhq_config_group_update/>
+ <rhq_config_update/>
+ <rhq_tagging/>
+ <rhq_tagging_resource_map/>
+ <rhq_tagging_res_group_map/>
+ <rhq_prd_ver/>
+ <rhq_alert_definition/>
+ <rhq_alert_condition/>
+ <rhq_alert/>
+ <rhq_alert_condition_log/>
+ <rhq_alert_notif_log/>
+ <rhq_availability/>
+ <rhq_measurement_sched/>
+ <rhq_content_source/>
+ <rhq_package/>
+ <rhq_bundle/>
+ <rhq_drift_def_template/>
+ <rhq_drift_definition/>
+ <rhq_drift_change_set/>
+ <rhq_plugin/>
+</dataset>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/AlertMetadataManagerBeanTest/plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/AlertMetadataManagerBeanTest/plugin_v1.xml
new file mode 100644
index 0000000..3b9ad64
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/AlertMetadataManagerBeanTest/plugin_v1.xml
@@ -0,0 +1,8 @@
+<plugin name="AlertMetadataManagerBeanTestPlugin"
+ displayName="AlertMetadataManagerBean Test Plugin"
+ package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="AlertServer"/>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/AlertMetadataManagerBeanTest/plugin_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/AlertMetadataManagerBeanTest/plugin_v2.xml
new file mode 100644
index 0000000..f2664dc
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/AlertMetadataManagerBeanTest/plugin_v2.xml
@@ -0,0 +1,7 @@
+<plugin name="AlertMetadataManagerBeanTestPlugin"
+ displayName="AlertMetadataManagerBean Test Plugin"
+ package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ContentMetadataManagerBeanTest/plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ContentMetadataManagerBeanTest/plugin_v1.xml
new file mode 100644
index 0000000..79f9296
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ContentMetadataManagerBeanTest/plugin_v1.xml
@@ -0,0 +1,45 @@
+<plugin name="ContentMetadataManagerBeanTestPlugin"
+ displayName="ContentMetadataManagerBean Test Plugin"
+ package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="ContentServer">
+ <content name="ContentServer.Content.1" category="deployable"/>
+ </server>
+
+ <server name="ContentServer1"/>
+
+ <server name="ContentServer2">
+ <content name="ContentServer2.Content.1" category="executableScript"/>
+ </server>
+
+ <server name="ContentServer3">
+ <content name="ContentServer3.Content.1" category="deployable"/>
+ <content name="ContentServer3.Content.2" category="deployable"/>
+ <content name="ContentServer3.Content.3" category="deployable"/>
+ </server>
+
+ <server name="ContentServer4">
+ <content name="ContentServer4.Content.1" category="deployable"/>
+ </server>
+
+ <server name="ContentServer5">
+ <content name="ContentServer5.Content.1" category="deployable">
+ <configuration>
+ <c:simple-property name="x"/>
+ </configuration>
+ </content>
+ <content name="ContentServer5.Content.2" category="deployable">
+ <configuration>
+ <c:simple-property name="x"/>
+ </configuration>
+ </content>
+ </server>
+
+ <server name="ContentServer6"/>
+
+ <server name="ContentServer7">
+ <bundle type="ContentServer.Bundle.1"/>
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ContentMetadataManagerBeanTest/plugin_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ContentMetadataManagerBeanTest/plugin_v2.xml
new file mode 100644
index 0000000..f0cd7b8
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ContentMetadataManagerBeanTest/plugin_v2.xml
@@ -0,0 +1,49 @@
+<plugin name="ContentMetadataManagerBeanTestPlugin"
+ displayName="ContentMetadataManagerBean Test Plugin"
+ package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="ContentServer">
+ <content name="ContentServer.Content.1" category="deployable">
+ <configuration>
+ <c:simple-property name="version"/>
+ </configuration>
+ </content>
+ </server>
+
+ <server name="ContentServer1">
+ <content name="ContentServer1.Content.1" category="deployable"/>
+ <content name="ContentServer1.Content.2" category="configuration"/>
+ </server>
+
+ <server name="ContentServer2"/>
+
+ <server name="ContentServer3">
+ <content name="ContentServer3.Content.2" category="deployable"/>
+ <content name="ContentServer3.Content.3" category="deployable"/>
+ </server>
+
+ <server name="ContentServer4">
+ <content name="ContentServer4.Content.1" category="deployable"/>
+ <content name="ContentServer4.Content.2" category="deployable"/>
+ </server>
+
+ <server name="ContentServer5">
+ <content name="ContentServer5.Content.1" category="deployable">
+ <configuration>
+ <c:simple-property name="x"/>
+ <c:simple-property name="y"/>
+ </configuration>
+ </content>
+ <content name="ContentServer5.Content.2" category="deployable"/>
+ </server>
+
+ <server name="ContentServer6">
+ <bundle type="ContentServer6.Bundle.1"/>
+ </server>
+
+ <server name="ContentServer7">
+ <bundle type="ContentServer.Bundle.2"/>
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/EventMetadataManagerBeanTest/plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/EventMetadataManagerBeanTest/plugin_v1.xml
new file mode 100644
index 0000000..2786b05
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/EventMetadataManagerBeanTest/plugin_v1.xml
@@ -0,0 +1,23 @@
+<plugin name="EventMetadataManagerBeanTestPlugin"
+ displayName="MeasurementMetadataManagerBean Test Plugin"
+ package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="EventServer1">
+ <event name="event1" description="Event 1"/>
+ <event name="event2" description="Event 2"/>
+ </server>
+
+ <server name="EventServer2"/>
+
+ <server name="EventServer3">
+ <event name="event1" description="Event 1"/>
+ <event name="event2" description="Event 2"/>
+ </server>
+
+ <server name="EventServer4">
+ <event name="event1" description="Event 1"/>
+ <event name="event2" description="Event 2"/>
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/EventMetadataManagerBeanTest/plugin_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/EventMetadataManagerBeanTest/plugin_v2.xml
new file mode 100644
index 0000000..f4f765f
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/EventMetadataManagerBeanTest/plugin_v2.xml
@@ -0,0 +1,23 @@
+<plugin name="EventMetadataManagerBeanTestPlugin"
+ displayName="ContentMetadataManagerBean Test Plugin"
+ package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="EventServer1">
+ <event name="event1" description="Event 1"/>
+ <event name="event2" description="Event 2"/>
+ </server>
+
+ <server name="EventServer2">
+ <event name="event1" description="Event 1"/>
+ <event name="event2" description="Event 2"/>
+ </server>
+
+ <server name="EventServer3"/>
+
+ <server name="EventServer4">
+ <event name="event1" description="EVENT ONE"/>
+ <event name="event3" description="Event 3"/>
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MeasurementMetadataManagerBeanTest/plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MeasurementMetadataManagerBeanTest/plugin_v1.xml
new file mode 100644
index 0000000..0202079
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MeasurementMetadataManagerBeanTest/plugin_v1.xml
@@ -0,0 +1,48 @@
+<plugin name="MeasurementMetadataManagerBeanTestPlugin"
+ displayName="MeasurementMetadataManagerBean Test Plugin"
+ package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="MetricServer1">
+ <metric displayName="metric1" property="metric1" dataType="trait" displayType="summary"
+ description="Metric 1" category="availability" defaultInterval="30000" defaultOn="true"
+ units="milliseconds"/>
+ <metric displayName="metric2" property="metric2" dataType="measurement" displayType="detail"
+ description="Metric 2" category="performance" defaultInterval="30000" defaultOn="true"
+ units="megabytes" measurementType="trendsup"/>
+ <metric displayName="metric3" property="metric3" dataType="calltime" displayType="detail"
+ description="Metric 3" category="throughput" defaultInterval="30000" defaultOn="true"
+ units="milliseconds" destinationType="myMethod"/>
+ </server>
+ <server name="MetricServer2"/>
+ <server name="MetricServer3">
+ <metric displayName="metric1" property="metric1" dataType="trait" displayType="summary"
+ description="Metric 1" category="availability" defaultInterval="30000" defaultOn="true"
+ units="milliseconds"/>
+
+ <service name="MetricService1">
+ <metric property="rhq.availability" defaultInterval="120000" defaultOn="false" />
+ </service>
+ <service name="MetricService2" />
+ </server>
+ <server name="MetricServer4">
+ <metric displayName="metric1" property="metric1" dataType="trait" displayType="summary"
+ description="Metric 1" category="availability" defaultInterval="30000" defaultOn="true"
+ units="milliseconds"/>
+ </server>
+ <server name="MetricServer5">
+ <!--
+ Need to use names for these metrics that are unique across the plugin because the resource
+ type will be deleted and the metric definition cannot be looked up by resource type. We will
+ instead look them up by name only.
+ -->
+ <metric displayName="metric1" property="MetricServer5.metric1" dataType="trait" displayType="summary"
+ description="Metric 1" category="availability" defaultInterval="30000" defaultOn="true"
+ units="milliseconds"/>
+ <metric displayName="metric3" property="MetricServer5.metric3" dataType="calltime" displayType="detail"
+ description="Metric 3" category="throughput" defaultInterval="30000" defaultOn="true"
+ units="milliseconds" destinationType="myMethod"/>
+ </server>
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MeasurementMetadataManagerBeanTest/plugin_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MeasurementMetadataManagerBeanTest/plugin_v2.xml
new file mode 100644
index 0000000..d949778
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MeasurementMetadataManagerBeanTest/plugin_v2.xml
@@ -0,0 +1,40 @@
+<plugin name="MeasurementMetadataManagerBeanTestPlugin"
+ displayName="MeasurementMetadataManagerBean Test Plugin"
+ package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="MetricServer1">
+ <metric displayName="metric1" property="metric1" dataType="trait" displayType="summary"
+ description="Metric 1" category="availability" defaultInterval="30000" defaultOn="true"
+ units="milliseconds"/>
+ <metric displayName="metric2" property="metric2" dataType="measurement" displayType="detail"
+ description="Metric 2" category="performance" defaultInterval="30000" defaultOn="true"
+ units="megabytes" measurementType="trendsup"/>
+ <metric displayName="metric3" property="metric3" dataType="calltime" displayType="detail"
+ description="Metric 3" category="throughput" defaultInterval="30000" defaultOn="true"
+ units="milliseconds" destinationType="myMethod"/>
+ <metric displayName="cannotBeSet" property="rhq.availability"
+ description="cannotBeSet" defaultInterval="120000" defaultOn="true"/>
+ </server>
+ <server name="MetricServer2">
+ <metric displayName="metric1" property="metric1" dataType="trait" displayType="summary"
+ description="Metric 1" category="availability" defaultInterval="30000" defaultOn="true"
+ units="milliseconds"/>
+ </server>
+ <server name="MetricServer3">
+ <metric displayName="metric1" property="metric1" dataType="measurement" displayType="detail"
+ description="Metric One" category="performance" defaultInterval="60000" defaultOn="false"
+ units="milliseconds" measurementType="trendsup"/>
+
+ <service name="MetricService1">
+ <metric displayName="cannotBeSet" property="rhq.availability"
+ description="cannotBeSet" defaultInterval="240000" defaultOn="true" />
+ </service>
+ <service name="MetricService2">
+ <metric displayName="cannotBeSet" property="rhq.availability"
+ description="cannotBeSet" defaultInterval="480000" defaultOn="true" />
+ </service>
+ </server>
+ <server name="MetricServer4"/>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MetadataTest.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MetadataTest.xml
new file mode 100644
index 0000000..e914562
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MetadataTest.xml
@@ -0,0 +1,298 @@
+<dataset>
+ <rhq_config_def/>
+ <rhq_config_prop_grp_def/>
+ <rhq_config_prop_def/>
+ <rhq_config_pd_osrc/>
+ <rhq_conf_prop_def_enum/>
+ <rhq_config_prop_constr/>
+ <rhq_config/>
+ <rhq_config_property/>
+ <rhq_config_template/>
+ <rhq_raw_config/>
+ <rhq_affinity_group/>
+ <rhq_server/>
+ <rhq_agent/>
+ <rhq_partition_event/>
+ <rhq_partition_details/>
+ <rhq_failover_list/>
+ <rhq_failover_details/>
+ <rhq_principal id="2" PRINCIPAL="rhqadmin" PASSWORD="x1XwrxKuPvYUILiOnOZTLg=="/>
+ <rhq_subject
+ ID="1"
+ NAME="admin"
+ FIRST_NAME="Super"
+ LAST_NAME="User"
+ FSYSTEM="1"/>
+ <rhq_subject
+ ID="2"
+ NAME="rhqadmin"
+ FIRST_NAME="RHQ"
+ LAST_NAME="Administrator"
+ EMAIL_ADDRESS="nobody@localhost"
+ FSYSTEM="0"/>
+ <rhq_resource_type/>
+ <rhq_resource_subcat/>
+ <rhq_resource_type_parents/>
+ <rhq_process_scan/>
+ <rhq_prd_ver/>
+ <rhq_resource/>
+ <rhq_resource_error/>
+ <rhq_group_def/>
+ <rhq_resource_group/>
+ <rhq_resource_group_res_imp_map/>
+ <rhq_resource_group_res_exp_map/>
+ <rhq_config_group_update/>
+ <rhq_config_update/>
+ <rhq_tagging/>
+ <rhq_tagging_resource_map/>
+ <rhq_tagging_res_group_map/>
+ <rhq_role
+ ID="1"
+ NAME="Super User Role"
+ FSYSTEM="1"
+ DESCRIPTION="System superuser role that provides full access to everything. This role cannot be modified."/>
+ <rhq_role
+ ID="2"
+ NAME="All Resources Role"
+ FSYSTEM="0"
+ DESCRIPTION="Provides full access to all resources in inventory. Cannot modify users, roles or server settings."/>
+ <rhq_role_resource_group_map/>
+ <rhq_role_ldap_group/>
+ <rhq_permission ROLE_ID="1" OPERATION="0"/> <!-- Permission.MANAGE_SECURITY -->
+ <rhq_permission ROLE_ID="1" OPERATION="1"/> <!-- Permission.MANAGE_INVENTORY -->
+ <rhq_permission ROLE_ID="1" OPERATION="2"/> <!-- Permission.MANAGE_SETTINGS -->
+ <rhq_permission ROLE_ID="1" OPERATION="12"/> <!-- Permission.MANAGE_BUNDLE -->
+ <rhq_permission ROLE_ID="1" OPERATION="15"/> <!-- Permission.MANAGE_REPOSITORIES -->
+ <!-- resource permissions start here-->
+ <rhq_permission ROLE_ID="1" OPERATION="3"/> <!-- Permission.VIEW_RESOURCE -->
+ <rhq_permission ROLE_ID="1" OPERATION="4"/> <!-- Permission.MODIFY_RESOURCE -->
+ <rhq_permission ROLE_ID="1" OPERATION="5"/> <!-- Permission.DELETE_RESOURCE -->
+ <rhq_permission ROLE_ID="1" OPERATION="6"/> <!-- Permission.CREATE_CHILD_RESOURCES -->
+ <rhq_permission ROLE_ID="1" OPERATION="7"/> <!-- Permission.MANAGE_ALERTS -->
+ <rhq_permission ROLE_ID="1" OPERATION="8"/> <!-- Permission.MANAGE_MEASUREMENTS -->
+ <rhq_permission ROLE_ID="1" OPERATION="9"/> <!-- Permission.MANAGE_CONTENT -->
+ <rhq_permission ROLE_ID="1" OPERATION="10"/> <!-- Permission.CONTROL -->
+ <rhq_permission ROLE_ID="1" OPERATION="11"/> <!-- Permission.CONFIGURE -->
+ <rhq_permission ROLE_ID="1" OPERATION="14"/> <!-- Permission.MANAGE_EVENTS -->
+
+ <!-- give all-resources-role all permissions (resource perms is mainly just to show on view-role page) -->
+ <rhq_permission ROLE_ID="2" OPERATION="1"/> <!-- Permission.MANAGE_INVENTORY -->
+ <rhq_permission ROLE_ID="2" OPERATION="12"/> <!-- Permission.MANAGE_BUNDLE -->
+ <!-- resource permissions start here-->
+ <rhq_permission ROLE_ID="2" OPERATION="3"/> <!-- Permission.VIEW_RESOURCE -->
+ <rhq_permission ROLE_ID="2" OPERATION="4"/> <!-- Permission.MODIFY_RESOURCE -->
+ <rhq_permission ROLE_ID="2" OPERATION="5"/> <!-- Permission.DELETE_RESOURCE -->
+ <rhq_permission ROLE_ID="2" OPERATION="6"/> <!-- Permission.CREATE_CHILD_RESOURCES -->
+ <rhq_permission ROLE_ID="2" OPERATION="7"/> <!-- Permission.MANAGE_ALERTS -->
+ <rhq_permission ROLE_ID="2" OPERATION="8"/> <!-- Permission.MANAGE_MEASUREMENTS -->
+ <rhq_permission ROLE_ID="2" OPERATION="9"/> <!-- Permission.MANAGE_CONTENT -->
+ <rhq_permission ROLE_ID="2" OPERATION="10"/> <!-- Permission.CONTROL -->
+ <rhq_permission ROLE_ID="2" OPERATION="11"/> <!-- Permission.CONFIGURE -->
+ <rhq_permission ROLE_ID="2" OPERATION="14"/> <!-- Permission.MANAGE_EVENTS -->
+ <rhq_subject_role_map SUBJECT_ID="1" ROLE_ID="1"/>
+ <rhq_subject_role_map SUBJECT_ID="2" ROLE_ID="1"/>
+ <rhq_subject_role_ldap_map/>
+ <rhq_saved_search/>
+ <rhq_dashboard/>
+ <rhq_dashboard_portlet/>
+ <rhq_operation_def/>
+ <rhq_operation_history/>
+ <rhq_operation_schedule/>
+ <rhq_event_def/>
+ <rhq_event_source/>
+ <rhq_event/>
+ <rhq_alert_definition/>
+ <rhq_alert_dampen_event/>
+ <rhq_alert_condition/>
+ <rhq_alert/>
+ <rhq_alert_notif_log/>
+ <rhq_alert_condition_log/>
+ <rhq_alert_notification/>
+ <rhq_plugin/>
+ <rhq_measurement_def/>
+ <rhq_measurement_sched/>
+ <rhq_measurement_bline/>
+ <rhq_measurement_data_num_1h/>
+ <rhq_measurement_data_num_6h/>
+ <rhq_measurement_data_num_1d/>
+ <rhq_measurement_data_trait/>
+ <rhq_calltime_data_key/>
+ <rhq_calltime_data_value/>
+ <rhq_availability/>
+ <rhq_resource_avail/>
+ <rhq_measurement_oob/>
+ <rhq_measurement_oob_tmp/>
+ <rhq_numbers i="0"/>
+ <rhq_numbers i="1"/>
+ <rhq_numbers i="2"/>
+ <rhq_numbers i="3"/>
+ <rhq_numbers i="4"/>
+ <rhq_numbers i="5"/>
+ <rhq_numbers i="6"/>
+ <rhq_numbers i="7"/>
+ <rhq_numbers i="8"/>
+ <rhq_numbers i="9"/>
+ <rhq_numbers i="10"/>
+ <rhq_numbers i="11"/>
+ <rhq_numbers i="12"/>
+ <rhq_numbers i="13"/>
+ <rhq_numbers i="14"/>
+ <rhq_numbers i="15"/>
+ <rhq_numbers i="16"/>
+ <rhq_numbers i="17"/>
+ <rhq_numbers i="18"/>
+ <rhq_numbers i="19"/>
+ <rhq_numbers i="20"/>
+ <rhq_numbers i="21"/>
+ <rhq_numbers i="22"/>
+ <rhq_numbers i="23"/>
+ <rhq_numbers i="24"/>
+ <rhq_numbers i="25"/>
+ <rhq_numbers i="26"/>
+ <rhq_numbers i="27"/>
+ <rhq_numbers i="28"/>
+ <rhq_numbers i="29"/>
+ <rhq_numbers i="30"/>
+ <rhq_numbers i="31"/>
+ <rhq_numbers i="32"/>
+ <rhq_numbers i="33"/>
+ <rhq_numbers i="34"/>
+ <rhq_numbers i="35"/>
+ <rhq_numbers i="36"/>
+ <rhq_numbers i="37"/>
+ <rhq_numbers i="38"/>
+ <rhq_numbers i="39"/>
+ <rhq_numbers i="40"/>
+ <rhq_numbers i="41"/>
+ <rhq_numbers i="42"/>
+ <rhq_numbers i="43"/>
+ <rhq_numbers i="44"/>
+ <rhq_numbers i="45"/>
+ <rhq_numbers i="46"/>
+ <rhq_numbers i="47"/>
+ <rhq_numbers i="48"/>
+ <rhq_numbers i="49"/>
+ <rhq_numbers i="50"/>
+ <rhq_numbers i="51"/>
+ <rhq_numbers i="52"/>
+ <rhq_numbers i="53"/>
+ <rhq_numbers i="54"/>
+ <rhq_numbers i="55"/>
+ <rhq_numbers i="56"/>
+ <rhq_numbers i="57"/>
+ <rhq_numbers i="58"/>
+ <rhq_numbers i="59"/>
+ <rhq_meas_data_num_r00/>
+ <rhq_meas_data_num_r01/>
+ <rhq_meas_data_num_r02/>
+ <rhq_meas_data_num_r03/>
+ <rhq_meas_data_num_r04/>
+ <rhq_meas_data_num_r05/>
+ <rhq_meas_data_num_r06/>
+ <rhq_meas_data_num_r07/>
+ <rhq_meas_data_num_r08/>
+ <rhq_meas_data_num_r09/>
+ <rhq_meas_data_num_r10/>
+ <rhq_meas_data_num_r11/>
+ <rhq_meas_data_num_r12/>
+ <rhq_meas_data_num_r13/>
+ <rhq_meas_data_num_r14/>
+ <rhq_architecture id="1" name="noarch"/>
+ <rhq_architecture id="2" name="i386"/>
+ <rhq_architecture id="3" name="i486"/>
+ <rhq_architecture id="4" name="i586"/>
+ <rhq_architecture id="5" name="i686"/>
+ <rhq_architecture id="6" name="alpha"/>
+ <rhq_architecture id="7" name="alphaev6"/>
+ <rhq_architecture id="8" name="ia64"/>
+ <rhq_architecture id="9" name="sparc"/>
+ <rhq_architecture id="10" name="sparcv9"/>
+ <rhq_architecture id="11" name="sparc64"/>
+ <rhq_architecture id="12" name="src"/>
+ <rhq_architecture id="13" name="s390"/>
+ <rhq_architecture id="14" name="athlon"/>
+ <rhq_architecture id="15" name="s390x"/>
+ <rhq_architecture id="16" name="ppc"/>
+ <rhq_architecture id="17" name="ppc64"/>
+ <rhq_architecture id="18" name="pSeries"/>
+ <rhq_architecture id="19" name="iSeries"/>
+ <rhq_architecture id="20" name="x86_64"/>
+ <rhq_architecture id="21" name="ppc64iseries"/>
+ <rhq_architecture id="22" name="ppc64pseries"/>
+ <rhq_architecture id="23" name="sparc-solaris"/>
+ <rhq_architecture id="24" name="sparc.sun4u-solaris"/>
+ <rhq_architecture id="25" name="tar"/>
+ <rhq_architecture id="26" name="ia32e"/>
+ <rhq_architecture id="27" name="amd64"/>
+ <rhq_architecture id="28" name="i386-solaris"/>
+ <rhq_architecture id="29" name="nosrc"/>
+ <rhq_architecture id="30" name="sparc-solaris-patch"/>
+ <rhq_architecture id="31" name="i386-solaris-patch"/>
+ <rhq_architecture id="32" name="sparc-solaris-patch-cluster"/>
+ <rhq_architecture id="33" name="i386-solaris-patch-cluster"/>
+ <rhq_architecture id="34" name="noarch-solaris"/>
+ <rhq_architecture id="35" name="noarch-solaris-patch"/>
+ <rhq_architecture id="36" name="noarch-solaris-patch-cluster"/>
+ <rhq_architecture id="37" name="solaris-patch"/>
+ <rhq_architecture id="38" name="solaris-patch-cluster"/>
+ <rhq_repo_group_type id="1" name="family"/>
+ <rhq_repo_group/>
+ <rhq_content_source_type/>
+ <rhq_content_source/>
+ <rhq_repo/>
+ <rhq_repo_relation_type id="1" name="parent"/>
+ <rhq_repo_relation_type id="2" name="clone"/>
+ <rhq_repo_relation/>
+ <rhq_package_type/>
+ <rhq_package/>
+ <rhq_package_bits/>
+ <rhq_package_version/>
+ <rhq_content_req/>
+ <rhq_installed_package/>
+ <rhq_installed_pkg_hist/>
+ <rhq_content_src_sync/>
+ <rhq_repo_sync/>
+ <rhq_package_inst_step/>
+ <rhq_repo_resource_map/>
+ <rhq_repo_content_src_map/>
+ <rhq_repo_repo_group_map/>
+ <rhq_repo_repo_relation_map/>
+ <rhq_repo_pkg_version_map/>
+ <rhq_pkg_ver_content_src_map/>
+ <rhq_pkg_prd_map/>
+ <rhq_distribution_type id="1" name="kickstart" description="Linux kickstart distribution"/>
+ <rhq_distribution_type id="2" name="jumpstart" description="solaris jumpstart distribution"/>
+ <rhq_distribution/>
+ <rhq_repo_distribution/>
+ <rhq_distribution_file/>
+ <rhq_advisory/>
+ <rhq_advisory_package/>
+ <rhq_cve/>
+ <rhq_advisory_cve/>
+ <rhq_advisory_buglist/>
+ <rhq_repo_advisory/>
+ <rhq_bundle_type/>
+ <rhq_bundle/>
+ <rhq_bundle_version/>
+ <rhq_bundle_version_repo/>
+ <rhq_bundle_file/>
+ <rhq_bundle_destination/>
+ <rhq_bundle_deployment/>
+ <rhq_bundle_res_deploy/>
+ <rhq_bundle_res_dep_hist/>
+ <rhq_tagging_bundle_map/>
+ <rhq_tagging_bundle_version_map/>
+ <rhq_tagging_bundle_deploy_map/>
+ <rhq_tagging_bundle_dest_map/>
+ <rhq_create_res_hist/>
+ <rhq_delete_res_hist/>
+ <rhq_drift_def_template/>
+ <rhq_drift_definition/>
+ <rhq_drift_change_set/>
+ <jms_messages/>
+ <jms_transactions/>
+ <jms_users/>
+ <jms_roles/>
+ <jms_subscriptions/>
+</dataset>
+
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/child1_plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/child1_plugin_v1.xml
new file mode 100644
index 0000000..befc699
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/child1_plugin_v1.xml
@@ -0,0 +1,19 @@
+<plugin name="PluginExtensionMetadataChild1TestPlugin"
+ version="1.0"
+ displayName="Plugin Extension Metadata Child 1 Test Plugin"
+ package="org.rhq.plugins.test.child1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="OuterServerA">
+ <server name="Child1ServerA"
+ description="Child 1 Server type that extends Parent Server type"
+ discovery="Child1DiscoveryComponent"
+ class="Child1Component"
+ sourcePlugin="MultiplePluginExtensionMetadataParentTestPlugin"
+ sourceType="ParentServerA">
+ </server>
+ </server>
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/child2_plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/child2_plugin_v1.xml
new file mode 100644
index 0000000..0dafa9b
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/child2_plugin_v1.xml
@@ -0,0 +1,19 @@
+<plugin name="PluginExtensionMetadataChild2TestPlugin"
+ version="1.0"
+ displayName="Plugin Extension Metadata Child 2 Test Plugin"
+ package="org.rhq.plugins.test.child2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+
+ <server name="Child2ServerA"
+ description="Child 2 Server type that extends Parent Server type"
+ discovery="Child2DiscoveryComponent"
+ class="Child2Component"
+ sourcePlugin="MultiplePluginExtensionMetadataParentTestPlugin"
+ sourceType="ParentServerA">
+ </server>
+
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/parent_plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/parent_plugin_v1.xml
new file mode 100644
index 0000000..627c5a8
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/parent_plugin_v1.xml
@@ -0,0 +1,18 @@
+<plugin name="MultiplePluginExtensionMetadataParentTestPlugin"
+ version="1.0"
+ displayName="Multiple Plugin Extension Metadata Parent Test Plugin"
+ package="org.rhq.plugins.test.parent"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="ParentServerA"
+ description="Parent Server type that can be extended by a Child Server type"
+ discovery="ParentDiscoveryComponent"
+ class="ParentComponent">
+
+ <operation name="A-op" timeout="123456" description="a op"></operation>
+
+ </server>
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/parent_plugin_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/parent_plugin_v2.xml
new file mode 100644
index 0000000..2c0e9d8
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/parent_plugin_v2.xml
@@ -0,0 +1,18 @@
+<plugin name="MultiplePluginExtensionMetadataParentTestPlugin"
+ version="2.0"
+ displayName="Multiple Plugin Extension Metadata Parent Test Plugin"
+ package="org.rhq.plugins.test.parent"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="ParentServerA"
+ description="Parent Server type that can be extended by a Child Server type"
+ discovery="ParentDiscoveryComponent"
+ class="ParentComponent">
+
+ <operation name="A-op-NEW" timeout="987654" description="a new op"></operation>
+
+ </server>
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/child_plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/child_plugin_v1.xml
new file mode 100644
index 0000000..08ea056
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/child_plugin_v1.xml
@@ -0,0 +1,29 @@
+<plugin name="MultiplePluginExtensionSinglePluginDescriptorMetadataChildTestPlugin"
+ version="1.0"
+ displayName="Multiple Plugin Extension Single Descriptor Metadata Child Test Plugin"
+ package="org.rhq.plugins.test.child"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="OuterServerA">
+ <server name="Child1ServerA"
+ description="Child 1 Server type that extends Parent Server type"
+ discovery="Child1DiscoveryComponent"
+ class="Child1Component"
+ sourcePlugin="MultiplePluginExtensionSinglePluginDescriptorMetadataParentTestPlugin"
+ sourceType="ParentServerA">
+ </server>
+ </server>
+
+ <server name="OuterServerB">
+ <server name="Child2ServerA"
+ description="Child 2 Server type that extends Parent Server type"
+ discovery="Child2DiscoveryComponent"
+ class="Child2Component"
+ sourcePlugin="MultiplePluginExtensionSinglePluginDescriptorMetadataParentTestPlugin"
+ sourceType="ParentServerA">
+ </server>
+ </server>
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/parent_plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/parent_plugin_v1.xml
new file mode 100644
index 0000000..be977e7
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/parent_plugin_v1.xml
@@ -0,0 +1,24 @@
+<plugin name="MultiplePluginExtensionSinglePluginDescriptorMetadataParentTestPlugin"
+ version="1.0"
+ displayName="Multiple Plugin Extension Metadata Parent Test Plugin"
+ package="org.rhq.plugins.test.parent"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="ParentServerA"
+ description="Parent Server type that can be extended by a Child Server type"
+ discovery="ParentDiscoveryComponent"
+ class="ParentComponent">
+
+ <operation name="A-op" timeout="123456" description="a op"></operation>
+
+ <!-- BZ 789420 - if that bug isn't fixed and you uncomment this, the child plugin will fail to register properly
+ <service name="InnerServiceA">
+ <metric property="inner-A-metric" />
+ </service>
+ -->
+
+ </server>
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/parent_plugin_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/parent_plugin_v2.xml
new file mode 100644
index 0000000..9f02834
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/parent_plugin_v2.xml
@@ -0,0 +1,24 @@
+<plugin name="MultiplePluginExtensionSinglePluginDescriptorMetadataParentTestPlugin"
+ version="2.0"
+ displayName="Multiple Plugin Extension Metadata Parent Test Plugin"
+ package="org.rhq.plugins.test.parent"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="ParentServerA"
+ description="Parent Server type that can be extended by a Child Server type"
+ discovery="ParentDiscoveryComponent"
+ class="ParentComponent">
+
+ <operation name="A-op-NEW" timeout="987654" description="a new op"></operation>
+
+ <!-- BZ 789420 - if that bug isn't fixed and you uncomment this, the child plugin will fail to register properly
+ <service name="InnerServiceA">
+ <metric property="inner-A-metric" />
+ </service>
+ -->
+
+ </server>
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/OperationMetadataManagerBeanTest/plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/OperationMetadataManagerBeanTest/plugin_v1.xml
new file mode 100644
index 0000000..93a15ef
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/OperationMetadataManagerBeanTest/plugin_v1.xml
@@ -0,0 +1,42 @@
+<plugin name="OperationMetadataManagerBeanTestPlugin"
+ displayName="OperationMetadataManagerBean Test Plugin"
+ package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="OperationServer1">
+ <operation name="OperationServer1.Operation1"/>
+ </server>
+ <server name="OperationServer11">
+ <operation name="OperationServer11.Operation1">
+ <parameters>
+ <c:simple-property name="param1"/>
+ <c:simple-property name="param2"/>
+ </parameters>
+ </operation>
+ </server>
+
+ <server name="OperationServer2"/>
+ <server name="OperationServer21">
+ <operation name="OperationServer21.Operation1"/>
+ </server>
+ <server name="OperationServer22">
+ <operation name="OperationServer22.Operation1">
+ <parameters>
+ <c:simple-property name="param1"/>
+ <c:simple-property name="param2"/>
+ </parameters>
+ </operation>
+ </server>
+ <server name="OperationServer23">
+ <operation name="OperationServer23.Operation1"/>
+ </server>
+ <server name="OperationServer24">
+ <operation name="OperationServer24.Operation1"/>
+ <operation name="OperationServer24.Operation2">
+ <results>
+ <c:simple-property name="exitCode"/>
+ </results>
+ </operation>
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/OperationMetadataManagerBeanTest/plugin_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/OperationMetadataManagerBeanTest/plugin_v2.xml
new file mode 100644
index 0000000..a86fbcf
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/OperationMetadataManagerBeanTest/plugin_v2.xml
@@ -0,0 +1,41 @@
+<plugin name="OperationMetadataManagerBeanTestPlugin"
+ displayName="OperationMetadataManagerBean Test Plugin"
+ package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="OperationServer1">
+ <operation name="OperationServer1.Operation1"/>
+ </server>
+ <server name="OperationServer11">
+ <operation name="OperationServer11.Operation1">
+ <parameters>
+ <c:simple-property name="param1"/>
+ <c:simple-property name="param2"/>
+ </parameters>
+ </operation>
+ </server>
+
+ <server name="OperationServer2">
+ <operation name="OperationServer2.Operation1"/>
+ </server>
+ <server name="OperationServer21"/>
+ <server name="OperationServer22">
+ <operation name="OperationServer22.Operation1"/>
+ </server>
+ <server name="OperationServer23">
+ <operation name="OperationServer23.Operation1">
+ <results>
+ <c:simple-property name="exitCode"/>
+ </results>
+ </operation>
+ </server>
+ <server name="OperationServer24">
+ <operation name="OperationServer24.Operation1">
+ <parameters>
+ <c:simple-property name="param1"/>
+ </parameters>
+ </operation>
+ <operation name="OperationServer24.Operation2"/>
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/child_plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/child_plugin_v1.xml
new file mode 100644
index 0000000..ddedf10
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/child_plugin_v1.xml
@@ -0,0 +1,17 @@
+<plugin name="PluginExtensionMetadataChildTestPlugin"
+ version="1.0"
+ displayName="Plugin Extension Metadata Child Test Plugin"
+ package="org.rhq.plugins.test.child"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="ChildServerA"
+ description="Child Server type that extends Parent Server type"
+ discovery="ChildDiscoveryComponent"
+ class="ChildComponent"
+ sourcePlugin="PluginExtensionMetadataParentTestPlugin"
+ sourceType="ParentServerA">
+ </server>
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/parent_plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/parent_plugin_v1.xml
new file mode 100644
index 0000000..e640187
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/parent_plugin_v1.xml
@@ -0,0 +1,49 @@
+<plugin name="PluginExtensionMetadataParentTestPlugin"
+ version="1.0"
+ displayName="Plugin Extension Metadata Parent Test Plugin"
+ package="org.rhq.plugins.test.parent"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="ParentServerA"
+ description="Parent Server type that can be extended by a Child Server type"
+ discovery="ParentDiscoveryComponent"
+ class="ParentComponent">
+
+ <subcategories>
+ <subcategory name="A-subcat" displayName="a subcat"/>
+ </subcategories>
+
+ <plugin-configuration>
+ <c:group name="A-pc-group" hiddenByDefault="true">
+ <c:simple-property name="A-pc-prop" description="test plugin config prop" required="false" />
+ </c:group>
+ </plugin-configuration>
+
+ <process-scan name="A-process-scan" query="process|basename|match=A.exe"/>
+ <operation name="A-op" timeout="123456" description="a op"></operation>
+ <metric property="A-metric" defaultInterval="123456"></metric>
+ <event name="A-event" description="a event"></event>
+
+ <resource-configuration>
+ <c:simple-property name="A-rc-prop" description="test resource config prop" required="false" />
+ </resource-configuration>
+
+ <drift-definition name="A-drift-def">
+ <basedir>
+ <value-context>pluginConfiguration</value-context>
+ <value-name>A-pc-prop</value-name>
+ </basedir>
+ </drift-definition>
+
+ <bundle-target>
+ <destination-base-dir name="A-bundle-basedir">
+ <value-context>resourceConfiguration</value-context>
+ <value-name>A-rc-prop</value-name>
+ </destination-base-dir>
+ </bundle-target>
+
+ </server>
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/parent_plugin_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/parent_plugin_v2.xml
new file mode 100644
index 0000000..b0d4027
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/parent_plugin_v2.xml
@@ -0,0 +1,67 @@
+<plugin name="PluginExtensionMetadataParentTestPlugin"
+ version="2.0"
+ displayName="Plugin Extension Metadata Parent Test Plugin"
+ package="org.rhq.plugins.test.parent"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="ParentServerA"
+ description="Parent Server type that can be extended by a Child Server type"
+ discovery="ParentDiscoveryComponent"
+ class="ParentComponent">
+
+ <subcategories>
+ <subcategory name="A-subcat" displayName="a subcat"/>
+ </subcategories>
+
+ <plugin-configuration>
+ <c:group name="A-pc-group" hiddenByDefault="false">
+ <c:simple-property name="A-pc-prop-CHANGED" description="A-pc-prop desc 1" required="true" />
+ </c:group>
+ <c:group name="A-pc-group-NEW" hiddenByDefault="true">
+ <c:simple-property name="A-pc-prop-NEW" description="A-pc-prop desc 2" required="false" />
+ </c:group>
+ </plugin-configuration>
+
+ <process-scan name="A-process-scan" query="process|basename|match=CHANGED.exe"/> <!-- CHANGED, but same name -->
+ <process-scan name="A-process-scan-NEW" query="process|basename|match=NEW.exe"/>
+ <operation name="A-op" timeout="987654" description="a changed op"></operation> <!-- CHANGED, but same name -->
+ <operation name="A-op-NEW" timeout="111111" description="a new op"></operation>
+ <metric property="A-metric" defaultInterval="555555"></metric> <!-- CHANGED, but same name -->
+ <metric property="A-metric-NEW" defaultInterval="98765"></metric>
+ <event name="A-event-CHANGED" description="a changed event"></event>
+ <event name="A-event-NEW" description="a new event"></event>
+
+ <resource-configuration>
+ <c:simple-property name="A-rc-prop-CHANGED" description="test resource config prop 1" required="true" />
+ <c:simple-property name="A-rc-prop-NEW" description="test resource config prop 2" required="false" />
+ </resource-configuration>
+
+ <drift-definition name="A-drift-def-CHANGED">
+ <basedir>
+ <value-context>pluginConfiguration</value-context>
+ <value-name>A-pc-prop</value-name>
+ </basedir>
+ </drift-definition>
+ <drift-definition name="A-drift-def-NEW">
+ <basedir>
+ <value-context>resourceConfiguration</value-context>
+ <value-name>A-rc-prop</value-name>
+ </basedir>
+ </drift-definition>
+
+ <bundle-target>
+ <destination-base-dir name="A-bundle-basedir-CHANGED">
+ <value-context>resourceConfiguration</value-context>
+ <value-name>A-rc-prop</value-name>
+ </destination-base-dir>
+ <destination-base-dir name="A-bundle-basedir-NEW">
+ <value-context>pluginConfiguration</value-context>
+ <value-name>A-pc-prop</value-name>
+ </destination-base-dir>
+ </bundle-target>
+
+ </server>
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_1.xml
new file mode 100644
index 0000000..6680aa6
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_1.xml
@@ -0,0 +1,7 @@
+<plugin name="PluginManagerBeanTestPlugin1"
+ package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="TestServer1"/>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_2.xml
new file mode 100644
index 0000000..c6f8736
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_2.xml
@@ -0,0 +1,10 @@
+<plugin name="PluginManagerBeanTestPlugin2"
+ package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <depends plugin="PluginManagerBeanTestPlugin1" useClasses="true"/>
+
+ <server name="TestServer2"/>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_3.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_3.xml
new file mode 100644
index 0000000..78184bf
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_3.xml
@@ -0,0 +1,8 @@
+<plugin name="PluginManagerBeanTestPlugin3"
+ package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="TestServer3"/>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/child1_plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/child1_plugin_v1.xml
new file mode 100644
index 0000000..e006bc9
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/child1_plugin_v1.xml
@@ -0,0 +1,19 @@
+<plugin name="PluginScanningExtensionMetadataChild1TestPlugin"
+ version="1.0"
+ displayName="Plugin Scanning Extension Metadata Child 1 Test Plugin"
+ package="org.rhq.plugins.test.child1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="OuterServerA">
+ <server name="Child1ServerA"
+ description="Child 1 Server type that extends Parent Server type"
+ discovery="Child1DiscoveryComponent"
+ class="Child1Component"
+ sourcePlugin="PluginScanningExtensionMetadataParentTestPlugin"
+ sourceType="ParentServerA">
+ </server>
+ </server>
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/child2_plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/child2_plugin_v1.xml
new file mode 100644
index 0000000..18436bc
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/child2_plugin_v1.xml
@@ -0,0 +1,19 @@
+<plugin name="PluginScanningExtensionMetadataChild2TestPlugin"
+ version="1.0"
+ displayName="Plugin Scanning Extension Metadata Child 2 Test Plugin"
+ package="org.rhq.plugins.test.child2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+
+ <server name="Child2ServerA"
+ description="Child 2 Server type that extends Parent Server type"
+ discovery="Child2DiscoveryComponent"
+ class="Child2Component"
+ sourcePlugin="PluginScanningExtensionMetadataParentTestPlugin"
+ sourceType="ParentServerA">
+ </server>
+
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/parent_plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/parent_plugin_v1.xml
new file mode 100644
index 0000000..1622baa
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/parent_plugin_v1.xml
@@ -0,0 +1,18 @@
+<plugin name="PluginScanningExtensionMetadataParentTestPlugin"
+ version="1.0"
+ displayName="Plugin Scanning Extension Metadata Parent Test Plugin"
+ package="org.rhq.plugins.test.parent"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="ParentServerA"
+ description="Parent Server type that can be extended by a Child Server type"
+ discovery="ParentDiscoveryComponent"
+ class="ParentComponent">
+
+ <operation name="A-op" timeout="123456" description="a op"></operation>
+
+ </server>
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/parent_plugin_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/parent_plugin_v2.xml
new file mode 100644
index 0000000..b119590
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/parent_plugin_v2.xml
@@ -0,0 +1,18 @@
+<plugin name="PluginScanningExtensionMetadataParentTestPlugin"
+ version="2.0"
+ displayName="Plugin Scanning Extension Metadata Parent Test Plugin"
+ package="org.rhq.plugins.test.parent"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="ParentServerA"
+ description="Parent Server type that can be extended by a Child Server type"
+ discovery="ParentDiscoveryComponent"
+ class="ParentComponent">
+
+ <operation name="A-op-NEW" timeout="987654" description="a new op"></operation>
+
+ </server>
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/dup_drift.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/dup_drift.xml
new file mode 100644
index 0000000..bd9728b
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/dup_drift.xml
@@ -0,0 +1,19 @@
+<plugin name="TestPlugin" displayName="Test Plugin" package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="ServerWithDupDrift" description="has duplicate drift config names and thus is invalid">
+ <drift-definition name="drift-one">
+ <basedir>
+ <value-context>fileSystem</value-context>
+ <value-name>/a</value-name>
+ </basedir>
+ </drift-definition>
+ <drift-definition name="drift-one">
+ <basedir>
+ <value-context>fileSystem</value-context>
+ <value-name>/b</value-name>
+ </basedir>
+ </drift-definition>
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/parent_resource_type-plugin.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/parent_resource_type-plugin.xml
new file mode 100644
index 0000000..853e423
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/parent_resource_type-plugin.xml
@@ -0,0 +1,29 @@
+<plugin name="ParentResourceTypeTestPlugin" displayName="Test Plugin" package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <server name="Server A First Level" description="Server A description">
+ <server name="Server B Second Level" description="Server B description"/>
+ <service name="Service A Second Level" description="Service A description"/>
+ </server>
+
+ <server name="Server C First Level" description="Server C description">
+ <runs-inside>
+ <parent-resource-type name="Server B Second Level" plugin="ParentResourceTypeTestPlugin"/>
+ </runs-inside>
+ </server>
+
+ <service name="Service B First Level" description="Service B description">
+ <runs-inside>
+ <parent-resource-type name="Server B Second Level" plugin="ParentResourceTypeTestPlugin"/>
+ </runs-inside>
+ </service>
+
+ <service name="Service C First Level" description="Service C description">
+ <runs-inside>
+ <parent-resource-type name="Service A Second Level" plugin="ParentResourceTypeTestPlugin"/>
+ </runs-inside>
+ </service>
+
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/plugin_v1.xml
new file mode 100644
index 0000000..88cd39c
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/plugin_v1.xml
@@ -0,0 +1,92 @@
+<plugin name="TestPlugin" displayName="Test Plugin" package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="ServerA" description="Server A description">
+ <subcategories>
+ <subcategory name="Resources" description="Resources subcategory"/>
+ <subcategory name="Applications" description="Applications subcategory"/>
+ </subcategories>
+
+ <plugin-configuration>
+ <c:simple-property name="connectionPropertyX" default="x"/>
+ <c:simple-property name="connectionPropertyY" default="y"/>
+ </plugin-configuration>
+
+ <process-scan name="serverA" query="process|basename|match=^java.*,arg|org.jboss.Main|match=.*"/>
+
+ <operation name="start">
+ <parameters>
+ <c:simple-property name="immediate" type="boolean"/>
+ </parameters>
+ <results>
+ <c:simple-property name="exitCode" type="integer"/>
+ </results>
+ </operation>
+
+ <operation name="stop">
+ <parameters>
+ <c:simple-property name="immediate" type="boolean"/>
+ </parameters>
+ <results>
+ <c:simple-property name="exitCode" type="integer"/>
+ </results>
+ </operation>
+
+ <metric displayName="Metric 1" property="metric1" displayType="summary" defaultInterval="300000"/>
+ <metric displayName="Metric 2" property="metric2" displayType="summary" defaultInterval="300000" dataType="trait"/>
+
+ <event name="logAEntry" description="an entry was appended to a log file"/>
+ <event name="logBEntry" description="an entry was appended to a log file"/>
+
+ <content name="ServerA.Content.1" category="deployable">
+ <configuration>
+ <c:simple-property name="ServerA.Content.1.version"/>
+ </configuration>
+ </content>
+
+ <content name="ServerA.Content.2" category="deployable">
+ <configuration>
+ <c:simple-property name="ServerA.Content.2.version"/>
+ </configuration>
+ </content>
+
+ <drift-definition name="drift-pc">
+ <basedir>
+ <value-context>pluginConfiguration</value-context>
+ <value-name>connectionPropertyX</value-name>
+ </basedir>
+ <interval>123456</interval>
+ <includes>
+ <include path="foo/bar" pattern="**/*.blech"/>
+ </includes>
+ <excludes>
+ <exclude path="/wot/gorilla" pattern="*.xml" />
+ <exclude path="/hello"/>
+ </excludes>
+ </drift-definition>
+
+ <drift-definition name="drift-fs">
+ <basedir>
+ <value-context>fileSystem</value-context>
+ <value-name>/</value-name>
+ </basedir>
+ </drift-definition>
+
+ <bundle-target>
+ <destination-base-dir name="bundleTarget-pc" description="pc-description">
+ <value-context>pluginConfiguration</value-context>
+ <value-name>connectionPropertyY</value-name>
+ </destination-base-dir>
+ <destination-base-dir name="bundleTarget-fs"> <!-- note: no description, so we can test for proper null handling -->
+ <value-context>fileSystem</value-context>
+ <value-name>/wot/gorilla</value-name>
+ </destination-base-dir>
+ </bundle-target>
+
+ <service name="Child1" description="Child 1 description"/>
+ <service name="Child2" description="Child 2 description"/>
+ </server>
+
+ <server name="ServerB" description="Server B description"/>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/plugin_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/plugin_v2.xml
new file mode 100644
index 0000000..a89f679
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/plugin_v2.xml
@@ -0,0 +1,110 @@
+<plugin name="TestPlugin" displayName="Test Plugin" package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="ServerA" description="Server A description">
+
+ <subcategories>
+ <subcategory name="Resources" description="Resources subcategory"/>
+ <subcategory name="Applications" description="Applications subcategory"/>
+ </subcategories>
+
+ <plugin-configuration>
+ <c:simple-property name="connectionPropertyX" default="x"/>
+ <c:simple-property name="connectionPropertyY" default="y"/>
+ </plugin-configuration>
+
+ <process-scan name="processA" query="process|basename|match=^java.*,arg|org.jboss.MainA|match=.*"/>
+ <process-scan name="processB" query="process|basename|match=^java.*,arg|org.jboss.MainB|match=.*"/>
+
+ <operation name="start">
+ <parameters>
+ <c:simple-property name="immediate" type="boolean"/>
+ </parameters>
+ <results>
+ <c:simple-property name="exitCode" type="integer"/>
+ </results>
+ </operation>
+
+ <operation name="shutdown">
+ <parameters>
+ <c:simple-property name="immediate" type="boolean"/>
+ </parameters>
+ <results>
+ <c:simple-property name="exitCode" type="integer"/>
+ </results>
+ </operation>
+
+ <operation name="restart">
+ <parameters>
+ <c:simple-property name="immediate" type="boolean"/>
+ </parameters>
+ <results>
+ <c:simple-property name="exitCode" type="integer"/>
+ </results>
+ </operation>
+
+ <metric displayName="Metric 1" property="metric1" displayType="summary" defaultInterval="300000"/>
+ <metric displayName="Metric 2" property="metric2" displayType="summary" defaultInterval="300000" dataType="trait"/>
+
+ <event name="logAEntry" description="an entry was appended to a log file"/>
+ <event name="logCEntry" description="an entry was appended to a log file"/>
+
+ <content name="ServerA.Content.1" category="configuration">
+ <configuration>
+ <c:simple-property name="ServerA.Content.1.property1"/>
+ <c:simple-property name="ServerA.Content.1.property2"/>
+ </configuration>
+ </content>
+
+ <content name="ServerA.Content.3" category="deployable">
+ <configuration>
+ <c:simple-property name="ServerA.Content.3.version"/>
+ </configuration>
+ </content>
+
+ <drift-definition name="drift-rc">
+ <basedir>
+ <!-- this resource doesn't really have this resource config prop
+ but today we do not check for validity so this is OK. In the future, if we do
+ check, our tests will fail and we'll need to change this test drift config -->
+ <value-context>resourceConfiguration</value-context>
+ <value-name>resourceConfig1</value-name>
+ </basedir>
+ </drift-definition>
+
+ <drift-definition name="drift-mt">
+ <basedir>
+ <!-- this resource doesn't really have this metric trait
+ but today we do not check for validity so this is OK. In the future, if we do
+ check, our tests will fail and we'll need to change this test drift config -->
+ <value-context>measurementTrait</value-context>
+ <value-name>trait1</value-name>
+ </basedir>
+ </drift-definition>
+
+ <bundle-target>
+ <destination-base-dir name="bundleTarget-rc" description="rc-description">
+ <!-- this resource doesn't really have this resource config prop
+ but today we do not check for validity so this is OK. In the future, if we do
+ check, our tests will fail and we'll need to change this test drift config -->
+ <value-context>resourceConfiguration</value-context>
+ <value-name>resourceConfig1</value-name>
+ </destination-base-dir>
+ <destination-base-dir name="bundleTarget-mt" description="mt-description">
+ <!-- this resource doesn't really have this metric trait
+ but today we do not check for validity so this is OK. In the future, if we do
+ check, our tests will fail and we'll need to change this test drift config -->
+ <value-context>measurementTrait</value-context>
+ <value-name>trait1</value-name>
+ </destination-base-dir>
+ </bundle-target>
+
+ <service name="Child1"/>
+ <service name="Child3"/>
+ </server>
+
+ <server name="ServerB" description="Server B description">
+ <service name="Child2"/>
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_bundle_drift_config_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_bundle_drift_config_v1.xml
new file mode 100644
index 0000000..460954b
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_bundle_drift_config_v1.xml
@@ -0,0 +1,20 @@
+<plugin name="TestPlugin" displayName="Test Plugin" package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="ServerWithBundleAndDriftConfig">
+ <drift-definition name="drift1">
+ <basedir>
+ <value-context>fileSystem</value-context>
+ <value-name>/dirA</value-name>
+ </basedir>
+ </drift-definition>
+
+ <bundle-target>
+ <destination-base-dir name="destdir1">
+ <value-context>fileSystem</value-context>
+ <value-name>/dirB</value-name>
+ </destination-base-dir>
+ </bundle-target>
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_bundle_drift_config_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_bundle_drift_config_v2.xml
new file mode 100644
index 0000000..c92919d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_bundle_drift_config_v2.xml
@@ -0,0 +1,7 @@
+<plugin name="TestPlugin" displayName="Test Plugin" package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="ServerWithBundleAndDriftConfig">
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_types_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_types_v1.xml
new file mode 100644
index 0000000..60a9f93
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_types_v1.xml
@@ -0,0 +1,54 @@
+<plugin name="RemoveTypesPlugin" displayName="Remove Types Plugin" package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="ServerC" description="Server C description">
+
+ <subcategories>
+ <subcategory name="ServerC.Category1">
+ <subcategory name="ServerC.NestedCategory1"/>
+ </subcategory>
+ <subcategory name="ServerC.Category2"/>
+ </subcategories>
+
+ <bundle type="Test Bundle"/>
+
+ <process-scan name="scan1" query="process|basename|match=^java.*,arg|org.rhq.serverC1|match=.*"/>
+ <process-scan name="scan2" query="process|basename|match=^java.*,arg|org.rhq.serverC2|match=.*"/>
+
+ <operation name="run">
+ <parameters>
+ <c:simple-property name="script"/>
+ </parameters>
+ <results>
+ <c:simple-property name="errors"/>
+ </results>
+ </operation>
+
+ <metric displayName="Metric 1" property="ServerC::metric1" displayType="summary" defaultInterval="300000"/>
+
+ <event name="serverCEvent" description="an entry was appended to a log file"/>
+
+ <content name="ServerC.Content" category="deployable">
+ <configuration>
+ <c:simple-property name="ServerC.Content.version"/>
+ </configuration>
+ </content>
+ </server>
+
+ <server name="ServerD">
+ <service name="ServerD.Child1">
+ <service name="ServerD.GrandChild1"/>
+ </service>
+ </server>
+
+ <server name="ServerE">
+ <service name="ServiceE1">
+ <service name="ServiceE2">
+ <service name="ServiceE3">
+ <service name="serviceE4"/>
+ </service>
+ </service>
+ </service>
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_types_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_types_v2.xml
new file mode 100644
index 0000000..6b0cdb0
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_types_v2.xml
@@ -0,0 +1,8 @@
+<plugin name="RemoveTypesPlugin" displayName="Remove Types Plugin" package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="ServerD">
+ <service name="ServerD.GrandChild1"/>
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_plugin_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_plugin_v1.xml
new file mode 100644
index 0000000..944bd20
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_plugin_v1.xml
@@ -0,0 +1,59 @@
+<plugin name="TestPlugin" displayName="Test Plugin" package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="ServerA" description="Server A description">
+ <subcategories>
+ <subcategory name="Resources" description="Resources subcategory"/>
+ <subcategory name="Applications" description="Applications subcategory"/>
+ </subcategories>
+
+ <plugin-configuration>
+ <c:simple-property name="connectionPropertyX" default="x"/>
+ <c:simple-property name="connectionPropertyY" default="y"/>
+ </plugin-configuration>
+
+ <process-scan name="serverA" query="process|basename|match=^java.*,arg|org.jboss.Main|match=.*"/>
+
+ <operation name="start">
+ <parameters>
+ <c:simple-property name="immediate" type="boolean"/>
+ </parameters>
+ <results>
+ <c:simple-property name="exitCode" type="integer"/>
+ </results>
+ </operation>
+
+ <operation name="stop">
+ <parameters>
+ <c:simple-property name="immediate" type="boolean"/>
+ </parameters>
+ <results>
+ <c:simple-property name="exitCode" type="integer"/>
+ </results>
+ </operation>
+
+ <metric displayName="Metric 1" property="metric1" displayType="summary" defaultInterval="300000"/>
+ <metric displayName="Metric 2" property="metric2" displayType="summary" defaultInterval="300000"/>
+
+ <event name="logAEntry" description="an entry was appended to a log file"/>
+ <event name="logBEntry" description="an entry was appended to a log file"/>
+
+ <content name="ServerA.Content.1" category="deployable">
+ <configuration>
+ <c:simple-property name="ServerA.Content.1.version"/>
+ </configuration>
+ </content>
+
+ <content name="ServerA.Content.2" category="deployable">
+ <configuration>
+ <c:simple-property name="ServerA.Content.2.version"/>
+ </configuration>
+ </content>
+
+ <service name="Child1" description="Child 1 description"/>
+ <service name="Child2" description="Child 2 description"/>
+ </server>
+
+ <server name="ServerB" description="Server B description"/>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_plugin_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_plugin_v2.xml
new file mode 100644
index 0000000..ca79943
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_plugin_v2.xml
@@ -0,0 +1,73 @@
+<plugin name="TestPlugin" displayName="Test Plugin" package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="ServerA" description="Server A description">
+
+ <subcategories>
+ <subcategory name="Resources" description="Resources subcategory"/>
+ <subcategory name="Applications" description="Applications subcategory"/>
+ </subcategories>
+
+ <plugin-configuration>
+ <c:simple-property name="connectionPropertyX" default="x"/>
+ <c:simple-property name="connectionPropertyY" default="y"/>
+ </plugin-configuration>
+
+ <process-scan name="processA" query="process|basename|match=^java.*,arg|org.jboss.MainA|match=.*"/>
+ <process-scan name="processB" query="process|basename|match=^java.*,arg|org.jboss.MainB|match=.*"/>
+
+ <operation name="start">
+ <parameters>
+ <c:simple-property name="immediate" type="boolean"/>
+ </parameters>
+ <results>
+ <c:simple-property name="exitCode" type="integer"/>
+ </results>
+ </operation>
+
+ <operation name="shutdown">
+ <parameters>
+ <c:simple-property name="immediate" type="boolean"/>
+ </parameters>
+ <results>
+ <c:simple-property name="exitCode" type="integer"/>
+ </results>
+ </operation>
+
+ <operation name="restart">
+ <parameters>
+ <c:simple-property name="immediate" type="boolean"/>
+ </parameters>
+ <results>
+ <c:simple-property name="exitCode" type="integer"/>
+ </results>
+ </operation>
+
+ <metric displayName="Metric 1" property="metric1" displayType="summary" defaultInterval="300000"/>
+ <metric displayName="Metric 2" property="metric2" displayType="summary" defaultInterval="300000"/>
+
+ <event name="logAEntry" description="an entry was appended to a log file"/>
+ <event name="logCEntry" description="an entry was appended to a log file"/>
+
+ <content name="ServerA.Content.1" category="configuration">
+ <configuration>
+ <c:simple-property name="ServerA.Content.1.property1"/>
+ <c:simple-property name="ServerA.Content.1.property2"/>
+ </configuration>
+ </content>
+
+ <content name="ServerA.Content.3" category="deployable">
+ <configuration>
+ <c:simple-property name="ServerA.Content.3.version"/>
+ </configuration>
+ </content>
+
+ <service name="Child1"/>
+ <service name="Child3"/>
+ </server>
+
+ <server name="ServerB" description="Server B description">
+ <service name="Child2"/>
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_remove_types_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_remove_types_v1.xml
new file mode 100644
index 0000000..60a9f93
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_remove_types_v1.xml
@@ -0,0 +1,54 @@
+<plugin name="RemoveTypesPlugin" displayName="Remove Types Plugin" package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="ServerC" description="Server C description">
+
+ <subcategories>
+ <subcategory name="ServerC.Category1">
+ <subcategory name="ServerC.NestedCategory1"/>
+ </subcategory>
+ <subcategory name="ServerC.Category2"/>
+ </subcategories>
+
+ <bundle type="Test Bundle"/>
+
+ <process-scan name="scan1" query="process|basename|match=^java.*,arg|org.rhq.serverC1|match=.*"/>
+ <process-scan name="scan2" query="process|basename|match=^java.*,arg|org.rhq.serverC2|match=.*"/>
+
+ <operation name="run">
+ <parameters>
+ <c:simple-property name="script"/>
+ </parameters>
+ <results>
+ <c:simple-property name="errors"/>
+ </results>
+ </operation>
+
+ <metric displayName="Metric 1" property="ServerC::metric1" displayType="summary" defaultInterval="300000"/>
+
+ <event name="serverCEvent" description="an entry was appended to a log file"/>
+
+ <content name="ServerC.Content" category="deployable">
+ <configuration>
+ <c:simple-property name="ServerC.Content.version"/>
+ </configuration>
+ </content>
+ </server>
+
+ <server name="ServerD">
+ <service name="ServerD.Child1">
+ <service name="ServerD.GrandChild1"/>
+ </service>
+ </server>
+
+ <server name="ServerE">
+ <service name="ServiceE1">
+ <service name="ServiceE2">
+ <service name="ServiceE3">
+ <service name="serviceE4"/>
+ </service>
+ </service>
+ </service>
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_remove_types_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_remove_types_v2.xml
new file mode 100644
index 0000000..6b0cdb0
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest_remove_types_v2.xml
@@ -0,0 +1,8 @@
+<plugin name="RemoveTypesPlugin" displayName="Remove Types Plugin" package="org.rhq.plugins.test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="ServerD">
+ <service name="ServerD.GrandChild1"/>
+ </server>
+</plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/util/db-data-combined-2.3.1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/util/db-data-combined-2.3.1.xml
new file mode 100644
index 0000000..f399ba4
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/util/db-data-combined-2.3.1.xml
@@ -0,0 +1,663 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<dbsetup name="data.xml">
+<!-- BEGIN: rhq-data.xml -->
+<!-- BEGIN: auth-data.xml -->
+
+
+ <table name="RHQ_PRINCIPAL">
+ <data id="2" PRINCIPAL="rhqadmin" PASSWORD="x1XwrxKuPvYUILiOnOZTLg=="/>
+ </table>
+
+<!-- END: auth-data.xml -->
+<!-- BEGIN: authz-data.xml -->
+
+
+ <!-- the overlord user -->
+ <table name="RHQ_SUBJECT">
+ <data ID="1"
+ NAME="admin"
+ FIRST_NAME="Super"
+ LAST_NAME="User"
+ FSYSTEM="TRUE"/>
+ </table>
+
+ <!-- the initial rhqadmin user -->
+ <table name="RHQ_SUBJECT">
+ <data ID="2"
+ NAME="rhqadmin"
+ FIRST_NAME="RHQ"
+ LAST_NAME="Administrator"
+ EMAIL_ADDRESS="rhqadmin@localhost"
+ FSYSTEM="FALSE"/>
+ </table>
+
+ <!-- Define the system root role which includes our overlord and rhqadmin users -->
+ <table name="RHQ_ROLE">
+ <data ID="1"
+ NAME="Super User Role"
+ FSYSTEM="TRUE"
+ DESCRIPTION="System superuser role that provides full access to everything. This role cannot be modified."/>
+ <data ID="2"
+ NAME="All Resources Role"
+ FSYSTEM="FALSE"
+ DESCRIPTION="Provides full access to all resources in inventory. Cannot modify users, roles or server settings."/>
+ </table>
+
+ <!-- associate the root users with all security permissions -->
+ <table name="RHQ_SUBJECT_ROLE_MAP">
+ <data SUBJECT_ID="1" ROLE_ID="1"/>
+ <!-- overlord user -->
+ <data SUBJECT_ID="2" ROLE_ID="1"/>
+ <!-- rhqadmin user -->
+ </table>
+
+ <table name="RHQ_PERMISSION">
+ <!-- give super-user-role all permissions (resource perms is mainly just to show on view-role page) -->
+ <data ROLE_ID="1" OPERATION="0"/>
+ <!-- Permission.MANAGE_SECURITY -->
+ <data ROLE_ID="1" OPERATION="1"/>
+ <!-- Permission.MANAGE_INVENTORY -->
+ <data ROLE_ID="1" OPERATION="2"/>
+ <!-- Permission.MANAGE_SETTINGS -->
+ <!-- resource permissions start here-->
+ <data ROLE_ID="1" OPERATION="3"/>
+ <!-- Permission.VIEW_RESOURCE -->
+ <data ROLE_ID="1" OPERATION="4"/>
+ <!-- Permission.MODIFY_RESOURCE -->
+ <data ROLE_ID="1" OPERATION="5"/>
+ <!-- Permission.DELETE_RESOURCE -->
+ <data ROLE_ID="1" OPERATION="6"/>
+ <!-- Permission.CREATE_CHILD_RESOURCES -->
+ <data ROLE_ID="1" OPERATION="7"/>
+ <!-- Permission.MANAGE_ALERTS -->
+ <data ROLE_ID="1" OPERATION="8"/>
+ <!-- Permission.MANAGE_MEASUREMENTS -->
+ <data ROLE_ID="1" OPERATION="9"/>
+ <!-- Permission.MANAGE_CONTENT -->
+ <data ROLE_ID="1" OPERATION="10"/>
+ <!-- Permission.CONTROL -->
+ <data ROLE_ID="1" OPERATION="11"/>
+ <!-- Permission.CONFIGURE -->
+
+ <!-- give all-resources-role all permissions (resource perms is mainly just to show on view-role page) -->
+ <data ROLE_ID="2" OPERATION="1"/>
+ <!-- Permission.MANAGE_INVENTORY -->
+ <!-- resource permissions start here-->
+ <data ROLE_ID="2" OPERATION="3"/>
+ <!-- Permission.VIEW_RESOURCE -->
+ <data ROLE_ID="2" OPERATION="4"/>
+ <!-- Permission.MODIFY_RESOURCE -->
+ <data ROLE_ID="2" OPERATION="5"/>
+ <!-- Permission.DELETE_RESOURCE -->
+ <data ROLE_ID="2" OPERATION="6"/>
+ <!-- Permission.CREATE_CHILD_RESOURCES -->
+ <data ROLE_ID="2" OPERATION="7"/>
+ <!-- Permission.MANAGE_ALERTS -->
+ <data ROLE_ID="2" OPERATION="8"/>
+ <!-- Permission.MANAGE_MEASUREMENTS -->
+ <data ROLE_ID="2" OPERATION="9"/>
+ <!-- Permission.MANAGE_CONTENT -->
+ <data ROLE_ID="2" OPERATION="10"/>
+ <!-- Permission.CONTROL -->
+ <data ROLE_ID="2" OPERATION="11"/>
+ <!-- Permission.CONFIGURE -->
+ </table>
+
+<!-- END: authz-data.xml -->
+<!-- BEGIN: sysconfig-data.xml -->
+
+
+ <!--
+ This file contains the seed data for the configuration table.
+ All keys mentioned here should be referenced via the RHQConstants class
+ -->
+ <table name="RHQ_SYSTEM_CONFIG">
+ <data ID="1" PROPERTY_KEY="SERVER_VERSION" PROPERTY_VALUE="1.3.1.GA"
+ DEFAULT_PROPERTY_VALUE="1.3.1.GA" FREAD_ONLY="TRUE"/>
+ <data ID="2" PROPERTY_KEY="DB_SCHEMA_VERSION" PROPERTY_VALUE="2.59"
+ DEFAULT_PROPERTY_VALUE="2.59" FREAD_ONLY="TRUE"/>
+ <data ID="3" PROPERTY_KEY="CAM_JAAS_PROVIDER" PROPERTY_VALUE="JDBC"
+ DEFAULT_PROPERTY_VALUE="JDBC" FREAD_ONLY="FALSE"/>
+ <data ID="4" PROPERTY_KEY="CAM_BASE_URL" PROPERTY_VALUE="http://169.254.222.60:7080/"
+ DEFAULT_PROPERTY_VALUE="http://169.254.222.60:7080/" FREAD_ONLY="FALSE"/>
+ <data ID="9" PROPERTY_KEY="CAM_HELP_USER" PROPERTY_VALUE="web"
+ DEFAULT_PROPERTY_VALUE="web" FREAD_ONLY="FALSE"/>
+ <data ID="10" PROPERTY_KEY="CAM_HELP_PASSWORD" PROPERTY_VALUE="user"
+ DEFAULT_PROPERTY_VALUE="user" FREAD_ONLY="FALSE"/>
+
+ <!-- default LDAP configuration options -->
+ <data ID="11" PROPERTY_KEY="CAM_LDAP_NAMING_FACTORY_INITIAL"
+ PROPERTY_VALUE="com.sun.jndi.ldap.LdapCtxFactory"
+ DEFAULT_PROPERTY_VALUE="com.sun.jndi.ldap.LdapCtxFactory"
+ FREAD_ONLY="FALSE"/>
+ <data ID="12" PROPERTY_KEY="CAM_LDAP_NAMING_PROVIDER_URL"
+ PROPERTY_VALUE="ldap://localhost/"
+ DEFAULT_PROPERTY_VALUE="ldap://localhost/"
+ FREAD_ONLY="FALSE"/>
+ <data ID="13" PROPERTY_KEY="CAM_LDAP_LOGIN_PROPERTY"
+ PROPERTY_VALUE="cn"
+ DEFAULT_PROPERTY_VALUE="cn" FREAD_ONLY="FALSE"/>
+ <data ID="14" PROPERTY_KEY="CAM_LDAP_BASE_DN"
+ PROPERTY_VALUE="o=JBoss,c=US"
+ DEFAULT_PROPERTY_VALUE="o=JBoss,c=US"
+ FREAD_ONLY="FALSE"/>
+ <data ID="15" PROPERTY_KEY="CAM_LDAP_BIND_DN"
+ PROPERTY_VALUE=""
+ DEFAULT_PROPERTY_VALUE="" FREAD_ONLY="FALSE"/>
+ <data ID="16" PROPERTY_KEY="CAM_LDAP_BIND_PW"
+ PROPERTY_VALUE=""
+ DEFAULT_PROPERTY_VALUE="" FREAD_ONLY="FALSE"/>
+ <data ID="17" PROPERTY_KEY="CAM_LDAP_PROTOCOL"
+ PROPERTY_VALUE="" DEFAULT_PROPERTY_VALUE=""
+ FREAD_ONLY="FALSE"/>
+ <data ID="18" PROPERTY_KEY="CAM_LDAP_FILTER"
+ PROPERTY_VALUE="" DEFAULT_PROPERTY_VALUE=""
+ FREAD_ONLY="FALSE"/>
+
+ <!-- Does this build support Syslog actions? -->
+ <data ID="21" PROPERTY_KEY="CAM_SYSLOG_ACTIONS_ENABLED"
+ PROPERTY_VALUE="false" DEFAULT_PROPERTY_VALUE="false"
+ FREAD_ONLY="FALSE"/>
+ <data ID="23" PROPERTY_KEY="CAM_GUIDE_ENABLED"
+ PROPERTY_VALUE="true"
+ DEFAULT_PROPERTY_VALUE="true" FREAD_ONLY="FALSE"/>
+ <data ID="24" PROPERTY_KEY="CAM_RT_COLLECT_IP_ADDRS"
+ PROPERTY_VALUE="true"
+ DEFAULT_PROPERTY_VALUE="true" FREAD_ONLY="FALSE"/>
+
+ <!-- Default data storage options -->
+ <!-- Default 14 days -->
+ <data ID="26" PROPERTY_KEY="CAM_DATA_PURGE_1H"
+ PROPERTY_VALUE="1209600000" DEFAULT_PROPERTY_VALUE="1209600000"
+ FREAD_ONLY="FALSE"/>
+ <!-- Default 31 days -->
+ <data ID="27" PROPERTY_KEY="CAM_DATA_PURGE_6H"
+ PROPERTY_VALUE="2678400000" DEFAULT_PROPERTY_VALUE="2678400000"
+ FREAD_ONLY="FALSE"/>
+ <!-- Default 1 year -->
+ <data ID="28" PROPERTY_KEY="CAM_DATA_PURGE_1D"
+ PROPERTY_VALUE="31536000000" DEFAULT_PROPERTY_VALUE="31536000000"
+ FREAD_ONLY="FALSE"/>
+
+ <!-- Baseline options -->
+ <!-- How often to calculate, default 3 days; if 0, never calculate them automatically -->
+ <data ID="29" PROPERTY_KEY="CAM_BASELINE_FREQUENCY"
+ PROPERTY_VALUE="259200000" DEFAULT_PROPERTY_VALUE="259200000"
+ FREAD_ONLY="FALSE"/>
+ <!-- How much data to include in the calulation, default 7 days -->
+ <data ID="30" PROPERTY_KEY="CAM_BASELINE_DATASET"
+ PROPERTY_VALUE="604800000" DEFAULT_PROPERTY_VALUE="604800000"
+ FREAD_ONLY="FALSE"/>
+
+ <!-- ID 31 has been deleted -->
+
+ <!-- How often to run database maintainence routines -->
+ <data ID="32" PROPERTY_KEY="CAM_DATA_MAINTENANCE"
+ PROPERTY_VALUE="3600000" DEFAULT_PROPERTY_VALUE="3600000" FREAD_ONLY="FALSE"/>
+
+ <!-- How long to keep RT data around -->
+ <data ID="34" PROPERTY_KEY="RT_DATA_PURGE" PROPERTY_VALUE="2678400000"
+ DEFAULT_PROPERTY_VALUE="2678400000" FREAD_ONLY="FALSE"/>
+
+ <!-- Whether to reindex the data tables nightly -->
+ <data ID="35" PROPERTY_KEY="DATA_REINDEX_NIGHTLY" PROPERTY_VALUE="true"
+ DEFAULT_PROPERTY_VALUE="true" FREAD_ONLY="FALSE"/>
+
+ <!-- How long to keep alerts around -->
+ <data ID="36" PROPERTY_KEY="ALERT_PURGE" PROPERTY_VALUE="2678400000"
+ DEFAULT_PROPERTY_VALUE="2678400000" FREAD_ONLY="FALSE"/>
+
+ <!-- Determines if SNMP actions will be used -->
+ <data ID="37" PROPERTY_KEY="SNMP_VERSION" PROPERTY_VALUE="" DEFAULT_PROPERTY_VALUE="" FREAD_ONLY="FALSE"/>
+ <data ID="38" PROPERTY_KEY="SNMP_AUTH_PROTOCOL" PROPERTY_VALUE="MD5" DEFAULT_PROPERTY_VALUE=""
+ FREAD_ONLY="FALSE"/>
+ <data ID="39" PROPERTY_KEY="SNMP_AUTH_PASSPHRASE" PROPERTY_VALUE="" DEFAULT_PROPERTY_VALUE=""
+ FREAD_ONLY="FALSE"/>
+ <data ID="40" PROPERTY_KEY="SNMP_PRIV_PASSPHRASE" PROPERTY_VALUE="" DEFAULT_PROPERTY_VALUE=""
+ FREAD_ONLY="FALSE"/>
+ <data ID="41" PROPERTY_KEY="SNMP_COMMUNITY" PROPERTY_VALUE="public" DEFAULT_PROPERTY_VALUE=""
+ FREAD_ONLY="FALSE"/>
+ <data ID="42" PROPERTY_KEY="SNMP_ENGINE_ID" PROPERTY_VALUE="" DEFAULT_PROPERTY_VALUE="" FREAD_ONLY="FALSE"/>
+ <data ID="43" PROPERTY_KEY="SNMP_CONTEXT_NAME" PROPERTY_VALUE="" DEFAULT_PROPERTY_VALUE="" FREAD_ONLY="FALSE"/>
+ <data ID="44" PROPERTY_KEY="SNMP_SECURITY_NAME" PROPERTY_VALUE="" DEFAULT_PROPERTY_VALUE="" FREAD_ONLY="FALSE"/>
+ <data ID="45" PROPERTY_KEY="SNMP_TRAP_OID" PROPERTY_VALUE="" DEFAULT_PROPERTY_VALUE="" FREAD_ONLY="FALSE"/>
+ <data ID="46" PROPERTY_KEY="SNMP_ENTERPRISE_OID" PROPERTY_VALUE="" DEFAULT_PROPERTY_VALUE=""
+ FREAD_ONLY="FALSE"/>
+ <data ID="47" PROPERTY_KEY="SNMP_GENERIC_ID" PROPERTY_VALUE="" DEFAULT_PROPERTY_VALUE="" FREAD_ONLY="FALSE"/>
+ <data ID="48" PROPERTY_KEY="SNMP_SPECIFIC_ID" PROPERTY_VALUE="" DEFAULT_PROPERTY_VALUE="" FREAD_ONLY="FALSE"/>
+ <data ID="49" PROPERTY_KEY="SNMP_AGENT_ADDRESS" PROPERTY_VALUE="" DEFAULT_PROPERTY_VALUE="" FREAD_ONLY="FALSE"/>
+ <data ID="50" PROPERTY_KEY="SNMP_PRIVACY_PROTOCOL" PROPERTY_VALUE="" DEFAULT_PROPERTY_VALUE=""
+ FREAD_ONLY="FALSE"/>
+
+ <!-- How long to keep events around (1209600000 millis == 14 days) -->
+ <data ID="51" PROPERTY_KEY="EVENT_PURGE" PROPERTY_VALUE="1209600000"
+ DEFAULT_PROPERTY_VALUE="1209600000" FREAD_ONLY="FALSE"/>
+
+ <!-- How long an agent is allowed to be quiet before we consider it down and backfill it -->
+ <data ID="52" PROPERTY_KEY="AGENT_MAX_QUIET_TIME_ALLOWED" PROPERTY_VALUE="900000"
+ DEFAULT_PROPERTY_VALUE="900000" FREAD_ONLY="FALSE"/>
+
+ <!-- Will our server-cloud support agents auto-updating themselves? -->
+ <data ID="53" PROPERTY_KEY="ENABLE_AGENT_AUTO_UPDATE" PROPERTY_VALUE="true"
+ DEFAULT_PROPERTY_VALUE="true" FREAD_ONLY="FALSE"/>
+
+ <!-- How old does a trait have to be in order to get purged -->
+ <data ID="54" PROPERTY_KEY="TRAIT_PURGE" PROPERTY_VALUE="31536000000"
+ DEFAULT_PROPERTY_VALUE="31536000000" FREAD_ONLY="FALSE"/>
+
+ <!-- How old does availability have to be in order to get purged -->
+ <data ID="55" PROPERTY_KEY="AVAILABILITY_PURGE" PROPERTY_VALUE="31536000000"
+ DEFAULT_PROPERTY_VALUE="31536000000" FREAD_ONLY="FALSE"/>
+
+ </table>
+
+<!-- END: sysconfig-data.xml -->
+<!-- BEGIN: measurement-data.xml -->
+
+ <table name="RHQ_NUMBERS">
+ <data i="0"/>
+ <data i="1"/>
+ <data i="2"/>
+ <data i="3"/>
+ <data i="4"/>
+ <data i="5"/>
+ <data i="6"/>
+ <data i="7"/>
+ <data i="8"/>
+ <data i="9"/>
+ <data i="10"/>
+ <data i="11"/>
+ <data i="12"/>
+ <data i="13"/>
+ <data i="14"/>
+ <data i="15"/>
+ <data i="16"/>
+ <data i="17"/>
+ <data i="18"/>
+ <data i="19"/>
+ <data i="20"/>
+ <data i="21"/>
+ <data i="22"/>
+ <data i="23"/>
+ <data i="24"/>
+ <data i="25"/>
+ <data i="26"/>
+ <data i="27"/>
+ <data i="28"/>
+ <data i="29"/>
+ <data i="30"/>
+ <data i="31"/>
+ <data i="32"/>
+ <data i="33"/>
+ <data i="34"/>
+ <data i="35"/>
+ <data i="36"/>
+ <data i="37"/>
+ <data i="38"/>
+ <data i="39"/>
+ <data i="40"/>
+ <data i="41"/>
+ <data i="42"/>
+ <data i="43"/>
+ <data i="44"/>
+ <data i="45"/>
+ <data i="46"/>
+ <data i="47"/>
+ <data i="48"/>
+ <data i="49"/>
+ <data i="50"/>
+ <data i="51"/>
+ <data i="52"/>
+ <data i="53"/>
+ <data i="54"/>
+ <data i="55"/>
+ <data i="56"/>
+ <data i="57"/>
+ <data i="58"/>
+ <data i="59"/>
+ </table>
+
+<!-- END: measurement-data.xml -->
+<!-- BEGIN: content-data.xml -->
+
+ <table name="RHQ_ARCHITECTURE">
+ <data id="1" name="noarch"/>
+ <data id="2" name="i386"/>
+ <data id="3" name="i486"/>
+ <data id="4" name="i586"/>
+ <data id="5" name="i686"/>
+ <data id="6" name="alpha"/>
+ <data id="7" name="alphaev6"/>
+ <data id="8" name="ia64"/>
+ <data id="9" name="sparc"/>
+ <data id="10" name="sparcv9"/>
+ <data id="11" name="sparc64"/>
+ <data id="12" name="src"/>
+ <data id="13" name="s390"/>
+ <data id="14" name="athlon"/>
+ <data id="15" name="s390x"/>
+ <data id="16" name="ppc"/>
+ <data id="17" name="ppc64"/>
+ <data id="18" name="pSeries"/>
+ <data id="19" name="iSeries"/>
+ <data id="20" name="x86_64"/>
+ <data id="21" name="ppc64iseries"/>
+ <data id="22" name="ppc64pseries"/>
+ <data id="23" name="sparc-solaris"/>
+ <data id="24" name="sparc.sun4u-solaris"/>
+ <data id="25" name="tar"/>
+ <data id="26" name="ia32e"/>
+ <data id="27" name="amd64"/>
+ <data id="28" name="i386-solaris"/>
+ <data id="29" name="nosrc"/>
+ <data id="30" name="sparc-solaris-patch"/>
+ <data id="31" name="i386-solaris-patch"/>
+ <data id="32" name="sparc-solaris-patch-cluster"/>
+ <data id="33" name="i386-solaris-patch-cluster"/>
+ <data id="34" name="noarch-solaris"/>
+ <data id="35" name="noarch-solaris-patch"/>
+ <data id="36" name="noarch-solaris-patch-cluster"/>
+ <data id="37" name="solaris-patch"/>
+ <data id="38" name="solaris-patch-cluster"/>
+ </table>
+<!-- END: content-data.xml -->
+<!-- BEGIN: jms-data.xml -->
+
+<!-- the schema matches that which would be automatically created by the JMS subsystem -->
+<!-- see deploy/jms/rhq-jdbc-state-service.xml and rhq-jdbc2-service.xml -->
+<!-- the data must match that which is expected in conf/login-config.xml -->
+
+
+ <table name="JMS_USERS">
+ <data USERID="guest" PASSWD="guest" />
+ </table>
+
+ <table name="JMS_ROLES">
+ <data ROLEID="guest" USERID="guest" />
+ </table>
+
+<!-- END: jms-data.xml -->
+<!-- END: rhq-data.xml -->
+<!-- BEGIN: jon-data.xml -->
+
+
+ <!-- *** metadata *** -->
+
+ <table name="RHQ_CONFIG_DEF">
+ <data ID="101"
+ NAME="JBossASPatchSource"/>
+ </table>
+
+ <table name="RHQ_CONFIG_PROP_DEF">
+ <data ID="101"
+ NAME="url"
+ DISPLAY_NAME="Feed URL"
+ DESCRIPTION="Destination URL of the feed."
+ REQUIRED="1"
+ READONLY="0"
+ SUMMARY="0"
+ ACTIVATION_POLICY="IMMEDIATE"
+ ORDER_INDEX="0"
+ SIMPLE_TYPE="STRING"
+ ALLOW_CUSTOM_ENUM_VALUE="0"
+ DTYPE="property"
+ CONFIG_DEF_ID="101"
+ UNITS="0"/>
+ <data ID="102"
+ NAME="username"
+ DISPLAY_NAME="Username"
+ DESCRIPTION="Username used to log into the feed."
+ REQUIRED="0"
+ READONLY="0"
+ SUMMARY="0"
+ ACTIVATION_POLICY="IMMEDIATE"
+ ORDER_INDEX="1"
+ SIMPLE_TYPE="STRING"
+ ALLOW_CUSTOM_ENUM_VALUE="0"
+ DTYPE="property"
+ CONFIG_DEF_ID="101"
+ UNITS="0"/>
+ <data ID="103"
+ NAME="password"
+ DISPLAY_NAME="Password"
+ DESCRIPTION="Password used to log into the feed."
+ REQUIRED="0"
+ READONLY="0"
+ SUMMARY="0"
+ ACTIVATION_POLICY="IMMEDIATE"
+ ORDER_INDEX="2"
+ SIMPLE_TYPE="PASSWORD"
+ ALLOW_CUSTOM_ENUM_VALUE="0"
+ DTYPE="property"
+ CONFIG_DEF_ID="101"
+ UNITS="0"/>
+ <data ID="104"
+ NAME="active"
+ DISPLAY_NAME="Active"
+ DESCRIPTION="Indicates if this instance should go out and check the feed for packages."
+ REQUIRED="1"
+ READONLY="0"
+ SUMMARY="0"
+ ACTIVATION_POLICY="IMMEDIATE"
+ ORDER_INDEX="3"
+ SIMPLE_TYPE="BOOLEAN"
+ ALLOW_CUSTOM_ENUM_VALUE="0"
+ DTYPE="property"
+ CONFIG_DEF_ID="101"
+ UNITS="0"/>
+ <data ID="105"
+ NAME="proxyUrl"
+ DISPLAY_NAME="Proxy URL"
+ REQUIRED="0"
+ READONLY="0"
+ SUMMARY="0"
+ ACTIVATION_POLICY="IMMEDIATE"
+ ORDER_INDEX="4"
+ SIMPLE_TYPE="STRING"
+ ALLOW_CUSTOM_ENUM_VALUE="0"
+ DTYPE="property"
+ CONFIG_DEF_ID="101"
+ UNITS="0"/>
+ <data ID="106"
+ NAME="proxyPort"
+ DISPLAY_NAME="Proxy Port"
+ REQUIRED="0"
+ READONLY="0"
+ SUMMARY="0"
+ ACTIVATION_POLICY="IMMEDIATE"
+ ORDER_INDEX="5"
+ SIMPLE_TYPE="STRING"
+ ALLOW_CUSTOM_ENUM_VALUE="0"
+ DTYPE="property"
+ CONFIG_DEF_ID="101"
+ UNITS="0"/>
+ <data ID="107"
+ NAME="proxyUsername"
+ DISPLAY_NAME="Proxy Username"
+ REQUIRED="0"
+ READONLY="0"
+ SUMMARY="0"
+ ACTIVATION_POLICY="IMMEDIATE"
+ ORDER_INDEX="6"
+ SIMPLE_TYPE="STRING"
+ ALLOW_CUSTOM_ENUM_VALUE="0"
+ DTYPE="property"
+ CONFIG_DEF_ID="101"
+ UNITS="0"/>
+ <data ID="108"
+ NAME="proxyPassword"
+ DISPLAY_NAME="Proxy Password"
+ REQUIRED="0"
+ READONLY="0"
+ SUMMARY="0"
+ ACTIVATION_POLICY="IMMEDIATE"
+ ORDER_INDEX="7"
+ SIMPLE_TYPE="STRING"
+ ALLOW_CUSTOM_ENUM_VALUE="0"
+ DTYPE="property"
+ CONFIG_DEF_ID="101"
+ UNITS="0"/>
+ </table>
+
+ <table name="RHQ_CONTENT_SOURCE_TYPE">
+ <data ID="101"
+ NAME="JBossASPatchSource"
+ DISPLAY_NAME="JBoss CSP Patch Content Source"
+ DESCRIPTION="This content source retrieves packages from the JBoss CSP RSS feed."
+ PLUGIN_NAME="JBossASPatchContentSourcePlugin"
+ DEFAULT_LAZY_LOAD="1"
+ DEFAULT_DOWNLOAD_MODE="FILESYSTEM"
+ DEFAULT_SYNC_SCHEDULE="0 0 3 * * ?"
+ API_CLASS="org.rhq.enterprise.server.plugins.jboss.software.JBossSoftwareContentSourceAdapter"
+ SOURCE_CONFIG_DEF_ID="101"/>
+ </table>
+
+
+ <!-- Default template for the AS software content source type's configuration -->
+ <table name="RHQ_CONFIG">
+ <data ID="101"
+ VERSION="0"
+ CTIME="1267099200000"
+ MTIME="1267099200000"/>
+ </table>
+
+ <table name="RHQ_CONFIG_PROPERTY">
+ <data ID="101"
+ NAME="url"
+ CONFIGURATION_ID="101"
+ STRING_VALUE=""
+ OVERRIDE="0"
+ DTYPE="property"/>
+ <data ID="102"
+ NAME="username"
+ CONFIGURATION_ID="101"
+ OVERRIDE="0"
+ DTYPE="property"/>
+ <data ID="103"
+ NAME="password"
+ CONFIGURATION_ID="101"
+ OVERRIDE="0"
+ DTYPE="property"/>
+ <data ID="104"
+ NAME="proxyUrl"
+ CONFIGURATION_ID="101"
+ OVERRIDE="0"
+ DTYPE="property"/>
+ <data ID="105"
+ NAME="proxyPort"
+ CONFIGURATION_ID="101"
+ OVERRIDE="0"
+ DTYPE="property"/>
+ <data ID="106"
+ NAME="active"
+ CONFIGURATION_ID="101"
+ STRING_VALUE="true"
+ OVERRIDE="0"
+ DTYPE="property"/>
+ <data ID="107"
+ NAME="proxyUsername"
+ CONFIGURATION_ID="101"
+ OVERRIDE="0"
+ DTYPE="property"/>
+ <data ID="108"
+ NAME="proxyPassword"
+ CONFIGURATION_ID="101"
+ OVERRIDE="0"
+ DTYPE="property"/>
+ </table>
+
+ <table name="RHQ_CONFIG_TEMPLATE">
+ <data ID="101"
+ NAME="default"
+ DESCRIPTION="the default template"
+ CONFIG_ID="101"
+ CONFIG_DEF_ID="101"
+ IS_DEFAULT="1"/>
+ </table>
+
+
+ <!-- *** data *** -->
+
+ <table name="RHQ_CONFIG">
+ <data ID="102"
+ VERSION="0"
+ CTIME="1267099200000"
+ MTIME="1267099200000"/>
+ </table>
+
+ <!-- Data for the content source itself -->
+ <table name="RHQ_CONFIG_PROPERTY">
+ <data ID="111"
+ NAME="url"
+ CONFIGURATION_ID="102"
+ STRING_VALUE="https://support.redhat.com/jbossnetwork/restricted/feed/software.html?pro..."
+ OVERRIDE="0"
+ DTYPE="property"/>
+ <data ID="112"
+ NAME="username"
+ CONFIGURATION_ID="102"
+ OVERRIDE="0"
+ DTYPE="property"/>
+ <data ID="113"
+ NAME="password"
+ CONFIGURATION_ID="102"
+ OVERRIDE="0"
+ DTYPE="property"/>
+ <data ID="114"
+ NAME="proxyUrl"
+ CONFIGURATION_ID="102"
+ OVERRIDE="0"
+ DTYPE="property"/>
+ <data ID="115"
+ NAME="proxyPort"
+ CONFIGURATION_ID="102"
+ OVERRIDE="0"
+ DTYPE="property"/>
+ <data ID="116"
+ NAME="active"
+ CONFIGURATION_ID="102"
+ STRING_VALUE="false"
+ OVERRIDE="0"
+ DTYPE="property"/>
+ <data ID="117"
+ NAME="proxyUsername"
+ CONFIGURATION_ID="102"
+ OVERRIDE="0"
+ DTYPE="property"/>
+ <data ID="118"
+ NAME="proxyPassword"
+ CONFIGURATION_ID="102"
+ OVERRIDE="0"
+ DTYPE="property"/>
+ </table>
+
+ <table name="RHQ_CONTENT_SOURCE">
+ <data ID="101"
+ NAME="JBoss Patch Content Source"
+ DESCRIPTION="All patches provided by the JBoss Subscription"
+ LAZY_LOAD="1"
+ DOWNLOAD_MODE="FILESYSTEM"
+ SYNC_SCHEDULE="0 0 3 * * ?"
+ CREATION_TIME="1267099200000"
+ LAST_MODIFIED_TIME="1267099200000"
+ CONTENT_SOURCE_TYPE_ID="101"
+ CONFIGURATION_ID="102"/>
+ </table>
+
+ <table name="RHQ_CHANNEL">
+ <data ID="101"
+ NAME="JBoss Patch Channel"
+ DESCRIPTION="JBoss Subscription Channel"
+ CREATION_TIME="1267099200000"
+ LAST_MODIFIED_TIME="1267099200000"/>
+ </table>
+
+ <table name="RHQ_CHANNEL_CONTENT_SRC_MAP">
+ <data CHANNEL_ID="101"
+ CONTENT_SRC_ID="101"
+ CTIME="1267099200000"/>
+ </table>
+
+
+<!-- END: jon-data.xml -->
+</dbsetup>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/util/db-schema-combined-2.3.1.xml b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/util/db-schema-combined-2.3.1.xml
new file mode 100644
index 0000000..3cd91ad
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/util/db-schema-combined-2.3.1.xml
@@ -0,0 +1,1916 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<dbsetup name="schema">
+<!-- BEGIN: config-schema.xml -->
+
+
+ <!-- Definition or Metadata tables -->
+
+ <table name="RHQ_CONFIG_DEF">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="NAME" type="VARCHAR2" required="true" size="100"/>
+ <column name="DESCRIPTION" type="VARCHAR2" required="false" size="250"/>
+ <column name="VERSION" type="VARCHAR2" required="false" size="50"/>
+ </table>
+
+ <table name="RHQ_CONFIG_PROP_GRP_DEF">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="NAME" type="VARCHAR2" required="true" size="100"/>
+ <column name="DISPLAY_NAME" type="VARCHAR2" required="false" size="100"/>
+ <column name="DESCRIPTION" type="VARCHAR2" required="false" size="250"/>
+ <column name="DEFAULT_HIDDEN" type="BOOLEAN" required="false"/>
+ <column name="ORDER_INDEX" type="INTEGER" required="false"/>
+ </table>
+
+ <table name="RHQ_CONFIG_PROP_DEF">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="NAME" type="VARCHAR2" required="false" size="100"/>
+ <column name="DISPLAY_NAME" type="VARCHAR2" required="false" size="100"/>
+ <column name="DESCRIPTION" type="VARCHAR2" required="false" size="1000"/>
+ <column name="DEFAULT_VALUE" type="VARCHAR2" required="false" size="2000"/>
+ <column name="REQUIRED" type="BOOLEAN" required="false"/>
+ <column name="READONLY" type="BOOLEAN" required="false"/>
+ <column name="SUMMARY" type="BOOLEAN" required="false"/>
+ <column name="ACTIVATION_POLICY" type="VARCHAR2" required="false" size="20"/>
+ <column name="GROUP_ID" type="INTEGER" required="false" references="RHQ_CONFIG_PROP_GRP_DEF"/>
+ <column name="ORDER_INDEX" type="INTEGER" required="false"/>
+ <column name="VERSION" type="VARCHAR2" required="false" size="50"/>
+ <column name="PARENT_MAP_DEFINITION_ID" type="INTEGER" required="false" references="RHQ_CONFIG_PROP_DEF"/>
+ <column name="PARENT_LIST_DEFINITION_ID" type="INTEGER" required="false" references="RHQ_CONFIG_PROP_DEF"/>
+ <column name="SIMPLE_TYPE" type="VARCHAR2" required="false" size="20"/>
+ <column name="ALLOW_CUSTOM_ENUM_VALUE" type="BOOLEAN" required="false"/>
+ <column name="DTYPE" type="VARCHAR2" required="true" size="10"/>
+ <column name="CONFIG_DEF_ID" type="INTEGER" required="false" references="RHQ_CONFIG_DEF"/>
+
+ <!-- only simple properties (not lists and maps) have this -->
+ <column name="UNITS" type="SMALLINT" required="false"/>
+ </table>
+
+ <table name="RHQ_CONF_PROP_DEF_ENUM">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="STRING_VALUE" type="VARCHAR2" required="false" size="500"/>
+ <column name="ORDER_INDEX" type="INTEGER" required="false"/>
+ <column name="IS_DEFAULT" type="BOOLEAN" required="false"/>
+ <column name="NAME" type="VARCHAR2" required="false" size="100"/>
+ <column name="PROPERTY_DEF_ID" type="INTEGER" required="false" references="RHQ_CONFIG_PROP_DEF"/>
+ </table>
+
+ <table name="RHQ_CONFIG_PROP_CONSTR">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="DTYPE" type="VARCHAR2" required="true" size="15"/>
+ <column name="DETAILS" type="VARCHAR2" required="false" size="250"/>
+ <column name="CONFIG_PROP_DEF_ID" type="INTEGER" required="false" references="RHQ_CONFIG_PROP_DEF"/>
+ <column name="ORDER_INDEX" type="INTEGER" required="false"/>
+ </table>
+
+
+ <!-- Content or value tables -->
+
+ <table name="RHQ_CONFIG">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="NOTES" type="VARCHAR2" required="false" size="512"/>
+ <column name="VERSION" type="VARCHAR2" required="false" size="50"/>
+ <column name="CTIME" type="LONG" required="true"/>
+ <column name="MTIME" type="LONG" required="true"/>
+ </table>
+
+ <table name="RHQ_CONFIG_PROPERTY">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="CONFIGURATION_ID" type="INTEGER" required="false" references="RHQ_CONFIG" ondelete="cascade"/>
+ <column name="STRING_VALUE" type="VARCHAR2" required="false" size="2000"/>
+ <column name="OVERRIDE" type="BOOLEAN" required="false"/>
+ <column name="NAME" type="VARCHAR2" required="true" size="100"/>
+ <column name="DTYPE" type="VARCHAR2" required="true" size="10"/>
+ <!-- Recursive cascade path to RHQ_CONFIG_PROPERTY causes constraint creation errors on SQL Server, see
+ http://support.microsoft.com/kb/321843 -->
+ <column name="PARENT_LIST_ID" type="INTEGER" required="false" references="RHQ_CONFIG_PROPERTY" ondelete="cascade" />
+ <column name="PARENT_MAP_ID" type="INTEGER" required="false" references="RHQ_CONFIG_PROPERTY" ondelete="cascade" />
+ <column name="LIST_INDEX" type="INTEGER"/>
+ <column name="ERROR_MESSAGE" type="LONGVARCHAR" required="false"/>
+ <index name="RHQ_CONFIG_PROP_idx_prop_key" unique="false">
+ <field ref="CONFIGURATION_ID"/>
+ <field ref="NAME"/>
+ </index>
+ <index name="RHQ_CONFIG_PROP_idx_map_key" unique="false">
+ <field ref="PARENT_MAP_ID"/>
+ <field ref="NAME"/>
+ </index>
+ <index name="RHQ_CONFIG_PROP_idx_list_key" unique="false">
+ <field ref="PARENT_LIST_ID"/>
+ </index>
+ <!-- List entries all have the same name -->
+ </table>
+
+ <table name="RHQ_CONFIG_TEMPLATE">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="NAME" type="VARCHAR2" required="false" size="100"/>
+ <column name="DESCRIPTION" type="VARCHAR2" required="false" size="500"/>
+ <column name="CONFIG_ID" type="INTEGER" required="false" references="RHQ_CONFIG"/>
+ <column name="CONFIG_DEF_ID" type="INTEGER" required="false" references="RHQ_CONFIG_DEF"/>
+ <column name="IS_DEFAULT" type="BOOLEAN" required="false"/>
+ </table>
+
+<!-- END: config-schema.xml -->
+<!-- BEGIN: cluster-schema.xml -->
+
+ <table name="RHQ_AFFINITY_GROUP">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" required="true" size="255" type="VARCHAR2"/>
+ </table>
+
+ <table name="RHQ_SERVER">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" required="true" size="255" type="VARCHAR2"/>
+ <column name="ADDRESS" required="true" size="255" type="VARCHAR2"/>
+ <column name="PORT" required="true" type="INTEGER"/>
+ <column name="SECURE_PORT" required="true" type="INTEGER"/>
+ <column name="CTIME" required="true" type="LONG"/>
+ <column name="MTIME" required="true" type="LONG"/>
+ <column name="AFFINITY_GROUP_ID" type="INTEGER" references="RHQ_AFFINITY_GROUP" required="false"/>
+ <column name="COMPUTE_POWER" required="true" type="INTEGER"/>
+ <column name="OPERATION_MODE" required="true" size="32" type="VARCHAR2"/>
+ <column name="STATUS" type="INTEGER" required="false" default="0" />
+
+ <!-- This index is for constraint, not performance -->
+ <index name="RHQ_SERVER_NAME_UNIQUE" unique="true">
+ <field ref="NAME"/>
+ </index>
+ </table>
+
+ <!-- new agent -->
+ <table name="RHQ_AGENT">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" required="true" size="255" type="VARCHAR2"/>
+ <column name="ADDRESS" required="true" size="255" type="VARCHAR2"/>
+ <column name="PORT" required="true" type="INTEGER"/>
+ <column name="AGENTTOKEN" required="true" size="100" type="VARCHAR2"/>
+ <column name="REMOTE_ENDPOINT" required="false" size="4000" type="VARCHAR2"/>
+ <column name="CTIME" required="true" type="LONG"/>
+ <column name="MTIME" required="true" type="LONG"/>
+ <column name="LAST_AVAILABILITY_REPORT" required="false" type="LONG"/>
+ <column name="AFFINITY_GROUP_ID" type="INTEGER" references="RHQ_AFFINITY_GROUP" required="false"/>
+ <column name="SERVER_ID" type="INTEGER" references="RHQ_SERVER" required="false"/>
+ <column name="STATUS" type="INTEGER" required="false" default="0" />
+ <column name="BACKFILLED" type="BOOLEAN" required="true" />
+
+ <index name="RHQ_AGENT_NAME_UNIQUE" unique="true">
+ <field ref="NAME"/>
+ </index>
+
+ <index name="RHQ_AGENT_ADDRESS_PORT" unique="true">
+ <field ref="ADDRESS"/>
+ <field ref="PORT"/>
+ </index>
+
+ <index name="RHQ_AGENT_TOKEN_UNIQUE" unique="true">
+ <field ref="AGENTTOKEN"/>
+ </index>
+ </table>
+
+ <table name="RHQ_PARTITION_EVENT">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="SUBJECT_NAME" required="true" size="255" type="VARCHAR2"/>
+ <column name="CTIME" required="true" type="LONG"/>
+ <column name="EVENT_TYPE" required="true" size="50" type="VARCHAR2"/>
+ <column name="EVENT_DETAIL" required="false" size="512" type="VARCHAR2"/>
+ <column name="EXECUTION_STATUS" required="true" size="32" type="VARCHAR2"/>
+ </table>
+
+ <table name="RHQ_PARTITION_DETAILS">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="PARTITION_EVENT_ID" type="INTEGER" references="RHQ_PARTITION_EVENT" required="true"/>
+ <column name="AGENT_NAME" type="VARCHAR2" size="255" required="true"/>
+ <column name="SERVER_NAME" type="VARCHAR2" size="255" required="true"/>
+ </table>
+
+ <table name="RHQ_FAILOVER_LIST">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="PARTITION_EVENT_ID" type="INTEGER" references="RHQ_PARTITION_EVENT" required="true"/>
+ <column name="AGENT_ID" type="INTEGER" references="RHQ_AGENT" required="true"/>
+ <column name="CTIME" required="true" type="LONG"/>
+ </table>
+
+ <table name="RHQ_FAILOVER_DETAILS">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="FAILOVER_LIST_ID" type="INTEGER" references="RHQ_FAILOVER_LIST" required="true"/>
+ <column name="SERVER_ID" type="INTEGER" references="RHQ_SERVER" required="true"/>
+ <column name="ORDINAL" type = "INTEGER" required="true"/>
+ </table>
+
+<!-- END: cluster-schema.xml -->
+<!-- BEGIN: inventory-schema.xml -->
+
+
+ <!-- NEW RESOURCE TYPES -->
+ <table name="RHQ_RESOURCE_TYPE">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" type="VARCHAR2" size="100" required="true"/>
+ <column name="CATEGORY" type="VARCHAR2" size="16" required="true"/>
+ <column name="CREATION_DATA_TYPE" type="VARCHAR2" size="16" required="true"/>
+ <column name="CREATE_DELETE_POLICY" type="VARCHAR2" size="16" required="true"/>
+ <column name="SINGLETON" type="BOOLEAN" required="true"/>
+ <column name="SUPPORTS_MANUAL_ADD" type="BOOLEAN" required="true"/>
+ <column name="DESCRIPTION" type="VARCHAR2" size="1000"/>
+ <column name="PLUGIN" type="VARCHAR2" size="100"/>
+ <column name="CTIME" type="LONG"/>
+ <column name="MTIME" type="LONG"/>
+ <column name="SUBCATEGORY_ID" type="INTEGER"/>
+ <!--
+ TODO add support to DB setup for tables with circular dependencies and then add back this RI
+ <column name="SUBCATEGORY_ID" type="INTEGER" references="RHQ_RESOURCE_SUBCAT" />
+ -->
+ <column name="PLUGIN_CONFIG_DEF_ID" type="INTEGER" references="RHQ_CONFIG_DEF(ID)"/>
+ <column name="RES_CONFIG_DEF_ID" type="INTEGER" references="RHQ_CONFIG_DEF(ID)"/>
+
+ <index name="RHQ_RES_TYPE_IDX_PLG_NAME">
+ <field ref="NAME"/>
+ <field ref="PLUGIN"/>
+ </index>
+ </table>
+
+ <!-- NEW RESOURCE SUBCATEGORIES -->
+ <table name="RHQ_RESOURCE_SUBCAT">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" type="VARCHAR2" size="100"/>
+ <column name="DISPLAY_NAME" type="VARCHAR2" size="100"/>
+ <column name="DESCRIPTION" type="VARCHAR2" size="1000"/>
+ <column name="CTIME" type="LONG"/>
+ <column name="MTIME" type="LONG"/>
+ <column name="PARENT_SUBCATEGORY_ID" type="INTEGER" references="RHQ_RESOURCE_SUBCAT"/>
+ <!-- resourceTypeId is not required on child sub categories -->
+ <column name="RESOURCE_TYPE_ID" type="INTEGER" references="RHQ_RESOURCE_TYPE"/>
+ </table>
+
+ <!-- Many To Many mapping for resource type to its parents -->
+ <table name="RHQ_RESOURCE_TYPE_PARENTS">
+ <column name="RESOURCE_TYPE_ID" required="true" type="INTEGER" references="RHQ_RESOURCE_TYPE"/>
+ <column name="PARENT_RESOURCE_TYPE_ID" required="true" type="INTEGER" references="RHQ_RESOURCE_TYPE"/>
+
+ <!-- not using full words to fit index name length -->
+ <constraint name="RHQ_RES_TYPE_PARENTS_KEY">
+ <primaryKey>
+ <field ref="RESOURCE_TYPE_ID"/>
+ <field ref="PARENT_RESOURCE_TYPE_ID"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+ <table name="RHQ_PROCESS_SCAN">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="QUERY" type="VARCHAR2" size="256" required="true"/>
+ <column name="NAME" type="VARCHAR2" size="100" required="false"/>
+ <column name="RESOURCE_TYPE_ID" type="INTEGER" references="RHQ_RESOURCE_TYPE"/>
+
+ <index name="RHQ_PROCESS_SCAN_QUERY_INDEX" unique="true">
+ <field ref="QUERY"/>
+ <field ref="RESOURCE_TYPE_ID"/>
+ </index>
+ </table>
+
+ <table name="RHQ_PRD_VER">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="VERSION" type="VARCHAR2" size="50" required="true"/>
+ <column name="RES_TYPE_ID" type="INTEGER" required="true" references="RHQ_RESOURCE_TYPE"/>
+ </table>
+
+ <table name="RHQ_RESOURCE">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="RESOURCE_TYPE_ID" type="INTEGER" required="true" references="RHQ_RESOURCE_TYPE"/>
+ <column name="UUID" type="CHAR" size="36" required="true"/>
+ <column name="NAME" type="VARCHAR2" size="500"/>
+ <column name="RESOURCE_KEY" type="VARCHAR2" required="true" size="500"/>
+ <column name="AGENT_ID" required="false" type="INTEGER" references="RHQ_AGENT(id)"/>
+ <column name="INVENTORY_STATUS" type="VARCHAR2" size="20"/>
+ <column name="CONNECTED" type="BOOLEAN"/>
+ <column name="DESCRIPTION" type="VARCHAR2" size="1000"/>
+ <column name="VERSION" type="VARCHAR2" size="50"/>
+ <column name="CTIME" type="LONG"/>
+ <column name="MTIME" type="LONG"/>
+ <column name="ITIME" type="LONG"/>
+ <column name="RES_CONFIGURATION_ID" type="INTEGER" references="RHQ_CONFIG"/>
+ <column name="PLUGIN_CONFIGURATION_ID" type="INTEGER" references="RHQ_CONFIG"/>
+ <column name="MODIFIED_BY" required="false" type="INTEGER"/>
+ <column name="LOCATION" required="false" size="100" type="VARCHAR2"/>
+ <column name="PARENT_RESOURCE_ID" type="INTEGER" references="RHQ_RESOURCE"/>
+ <column name="PRODUCT_VERSION_ID" type="INTEGER" references="RHQ_PRD_VER"/>
+
+ <index name="RHQ_RESOURCE_idx_key">
+ <field ref="RESOURCE_KEY"/>
+ </index>
+
+ <index name="RHQ_RESOURCE_idx_type">
+ <field ref="RESOURCE_TYPE_ID"/>
+ </index>
+
+ <index name="RHQ_RESOURCE_idx_agent">
+ <field ref="AGENT_ID"/>
+ </index>
+
+ <index name="RHQ_RESOURCE_idx_parent">
+ <field ref="PARENT_RESOURCE_ID"/>
+ </index>
+
+ </table>
+
+ <table name="RHQ_RESOURCE_ERROR">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="RESOURCE_ID" type="INTEGER" required="true" references="RHQ_RESOURCE"/>
+ <column name="TIME_OCCURRED" type="LONG" required="true"/>
+ <column name="ERROR_TYPE" type="VARCHAR2" required="true" size="32"/>
+ <column name="SUMMARY" type="VARCHAR2" required="true" size="1000"/>
+ <column name="DETAIL" type="LONGVARCHAR" required="false"/>
+
+ <index name="RHQ_RES_ERROR_IDX_RES_ID">
+ <field ref="RESOURCE_ID"/>
+ </index>
+ </table>
+
+ <table name="RHQ_GROUP_DEF">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" required="true" size="100" type="VARCHAR2"/>
+ <column name="DESCRIPTION" size="100" type="VARCHAR2"/>
+ <column name="CTIME" type="LONG"/>
+ <column name="MTIME" type="LONG"/>
+ <column name="CALC_TIME" type="LONG"/>
+ <column name="CALC_INTERVAL" type="LONG"/>
+ <column name="RECURSIVE" type="BOOLEAN"/>
+ <column name="EXPRESSION" type="VARCHAR2" size="1000"/>
+
+ <index name="RHQ_GROUP_DEF_NAME" unique="true">
+ <field ref="NAME"/>
+ </index>
+ </table>
+
+ <table name="RHQ_RESOURCE_GROUP">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <!-- this name can be longer than the size of the GROUP_BY column, which is used to uniquely identify it -->
+ <!-- Max bytes for Oracle Varchar2 to accommodate large cluster keys -->
+ <column name="NAME" required="true" size="4000" type="VARCHAR2"/>
+ <column name="DESCRIPTION" size="100" type="VARCHAR2"/>
+ <column name="LOCATION" required="false" size="100" type="VARCHAR2"/>
+ <column name="RESOURCE_TYPE_ID" type="INTEGER" references="RHQ_RESOURCE_TYPE"/>
+ <!-- Compatible groups only -->
+ <column name="CTIME" type="LONG"/>
+ <column name="MTIME" type="LONG"/>
+ <column name="MODIFIED_BY" required="false" type="INTEGER"/>
+ <!-- TODO: Reorder to allow this references="RHQ_SUBJECT" -->
+ <column name="RECURSIVE" type="BOOLEAN"/>
+
+ <column name="GROUP_DEFINITION_ID" required="false" type="INTEGER" references="RHQ_GROUP_DEF"/>
+ <column name="GROUP_BY" size="500" type="VARCHAR2"/>
+
+ <column name="CATEGORY" type="VARCHAR2" size="20" required="true"/>
+
+ <column name="CLUSTER_KEY" type="VARCHAR2" size="4000" required="false"/>
+
+ <!-- These two only set if this is a backing group for a resource cluster -->
+ <column name="CLUSTER_RESOURCE_GROUP_ID" type="INTEGER" references="RHQ_RESOURCE_GROUP"/>
+
+ <column name="VISIBLE" type="BOOLEAN"/>
+
+ <index name="RHQ_RES_GROUP_NAME" unique="false">
+ <field ref="NAME"/>
+ </index>
+ </table>
+
+ <!-- Many To Many mapping for groups to implicit resources -->
+ <table name="RHQ_RESOURCE_GROUP_RES_IMP_MAP">
+ <column name="RESOURCE_ID" required="true" type="INTEGER" references="RHQ_RESOURCE"/>
+ <column name="RESOURCE_GROUP_ID" required="true" type="INTEGER" references="RHQ_RESOURCE_GROUP"/>
+
+ <!-- not using full words to fit index name length -->
+ <constraint name="RHQ_RES_GROUP_RES_IMP_MAP_KEY">
+ <primaryKey>
+ <field ref="RESOURCE_ID"/>
+ <field ref="RESOURCE_GROUP_ID"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+ <!-- Many To Many mapping for groups to explicit resources -->
+ <table name="RHQ_RESOURCE_GROUP_RES_EXP_MAP">
+ <column name="RESOURCE_ID" required="true" type="INTEGER" references="RHQ_RESOURCE"/>
+ <column name="RESOURCE_GROUP_ID" required="true" type="INTEGER" references="RHQ_RESOURCE_GROUP"/>
+
+ <!-- not using full words to fit index name length -->
+ <constraint name="RHQ_RES_GROUP_RES_EXP_MAP_KEY">
+ <primaryKey>
+ <field ref="RESOURCE_ID"/>
+ <field ref="RESOURCE_GROUP_ID"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+ <table name="RHQ_CONFIG_GROUP_UPDATE">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="GROUP_ID" type="INTEGER" required="true" references="RHQ_RESOURCE_GROUP"/>
+ <column name="CONFIGURATION_ID" type="INTEGER" required="true" references="RHQ_CONFIG"/>
+ <column name="STATUS" type="VARCHAR2" required="true" size="16"/>
+ <column name="ERROR_MESSAGE" type="LONGVARCHAR" required="false"/>
+ <column name="SUBJECT_NAME" type="VARCHAR2" required="false" size="100"/>
+ <column name="CTIME" type="LONG" required="true"/>
+ <column name="MTIME" type="LONG" required="true"/>
+ <column name="DTYPE" type="VARCHAR2" required="true" size="10"/>
+ </table>
+
+ <table name="RHQ_CONFIG_UPDATE">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="CONFIGURATION_ID" type="INTEGER" required="true" references="RHQ_CONFIG" ondelete="cascade"/>
+ <column name="STATUS" type="VARCHAR2" required="true" size="16"/>
+ <column name="ERROR_MESSAGE" type="LONGVARCHAR" required="false"/>
+ <column name="SUBJECT_NAME" type="VARCHAR2" required="false" size="100"/>
+ <column name="CTIME" type="LONG" required="true"/>
+ <column name="MTIME" type="LONG" required="true"/>
+ <column name="CONFIG_RES_ID" type="INTEGER" required="false" references="RHQ_RESOURCE"/>
+ <column name="PLUGIN_CONFIG_RES_ID" type="INTEGER" required="false" references="RHQ_RESOURCE"/>
+ <column name="AGG_RES_UPDATE_ID" type="INTEGER" required="false" references="RHQ_CONFIG_GROUP_UPDATE"/>
+ <column name="AGG_PLUGIN_UPDATE_ID" type="INTEGER" required="false" references="RHQ_CONFIG_GROUP_UPDATE"/>
+ <column name="DTYPE" type="VARCHAR2" required="true" size="10"/>
+ </table>
+
+<!-- END: inventory-schema.xml -->
+<!-- BEGIN: auth-schema.xml -->
+
+
+ <table name="RHQ_PRINCIPAL">
+
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="PRINCIPAL" required="true" type="VARCHAR2" size="100"/>
+ <column name="PASSWORD" required="true" type="VARCHAR2" size="64"/>
+
+ <!-- ensure that principals are unique -->
+ <index name="RHQ_PRINCIPAL_PRINCIPAL_KEY" unique="true">
+ <field ref="PRINCIPAL"/>
+ </index>
+
+ </table>
+
+<!-- END: auth-schema.xml -->
+<!-- BEGIN: authz-schema.xml -->
+
+
+ <table name="RHQ_ROLE">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" required="true" size="100" type="VARCHAR2"/>
+ <column name="DESCRIPTION" size="100" type="VARCHAR2"/>
+ <column name="FSYSTEM" type="BOOLEAN" default="false"/>
+
+ <index name="RHQ_ROLE_NAME_KEY" unique="true">
+ <field ref="NAME"/>
+ </index>
+ </table>
+
+ <table name="RHQ_ROLE_RESOURCE_GROUP_MAP">
+ <column name="ROLE_ID" required="true" type="INTEGER" references="RHQ_ROLE"/>
+ <column name="RESOURCE_GROUP_ID" required="true" type="INTEGER" references="RHQ_RESOURCE_GROUP"/>
+
+ <constraint name="RHQ_ROLE_RES_GROUP_MAP_KEY">
+ <primaryKey>
+ <field ref="ROLE_ID"/>
+ <field ref="RESOURCE_GROUP_ID"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+ <table name="RHQ_PERMISSION">
+ <column name="ROLE_ID" type="INTEGER" references="RHQ_ROLE" required="true"/>
+ <column name="OPERATION" type="INTEGER" required="true"/>
+ <constraint name="RHQ_PERMISSION_PK">
+ <primaryKey>
+ <field ref="ROLE_ID"/>
+ <field ref="OPERATION"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+ <table name="RHQ_SUBJECT">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" required="true" size="100" type="VARCHAR2"/>
+ <column name="CONFIGURATION_ID" type="INTEGER" references="RHQ_CONFIG"/>
+ <column name="FIRST_NAME" required="false" size="100" type="VARCHAR2"/>
+ <column name="LAST_NAME" required="false" size="100" type="VARCHAR2"/>
+ <column name="EMAIL_ADDRESS" size="100" type="VARCHAR2"/>
+ <column name="SMS_ADDRESS" size="100" type="VARCHAR2"/>
+ <column name="PHONE_NUMBER" size="100" type="VARCHAR2"/>
+ <column name="DEPARTMENT" size="100" type="VARCHAR2"/>
+ <column name="FACTIVE" required="true" type="BOOLEAN" default="true"/>
+ <column name="FSYSTEM" required="true" type="BOOLEAN" default="false"/>
+
+ <index name="RHQ_SUBJECT_AUTH_KEY" unique="true">
+ <field ref="NAME"/>
+ </index>
+ </table>
+
+ <table name="RHQ_SUBJECT_ROLE_MAP">
+ <column name="SUBJECT_ID" required="true" type="INTEGER" references="RHQ_SUBJECT"/>
+ <column name="ROLE_ID" required="true" type="INTEGER" references="RHQ_ROLE"/>
+
+ <constraint name="RHQ_SUBJECT_ROLE_MAPPING_KEY">
+ <primaryKey>
+ <field ref="SUBJECT_ID"/>
+ <field ref="ROLE_ID"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+<!-- END: authz-schema.xml -->
+<!-- BEGIN: operation-schema.xml -->
+
+
+ <table name="RHQ_OPERATION_DEF">
+
+ <!-- === required columns === -->
+
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="RESOURCE_TYPE_ID" type="INTEGER" required="true" references="RHQ_RESOURCE_TYPE(ID)"/>
+ <column name="NAME" type="VARCHAR2" required="true" size="100"/>
+
+ <!-- === optional columns === -->
+
+ <!-- an OSGI version range - if null, the operation def applies to all versions of the associated resource type -->
+ <column name="RESOURCE_VERSION_RANGE" type="VARCHAR2" size="100"/>
+
+ <!-- A parameter config definition is only required for operations that have parameters. -->
+ <!-- A results config definition is only required for operations that return data. -->
+ <column name="PARAMETER_CONFIG_DEF_ID" type="INTEGER" references="RHQ_CONFIG_DEF(ID)"/>
+ <column name="RESULTS_CONFIG_DEF_ID" type="INTEGER" references="RHQ_CONFIG_DEF(ID)"/>
+ <column name="DISPLAY_NAME" type="VARCHAR2" size="100"/>
+ <column name="DESCRIPTION" type="VARCHAR2" size="4000"/>
+ <column name="TIMEOUT" type="INTEGER"/>
+
+ <!-- === business key (RESOURCE_TYPE_ID + NAME) === -->
+ <index name="RHQ_OPERATION_DEF_KEY_IDX" unique="true">
+ <field ref="RESOURCE_TYPE_ID"/>
+ <field ref="NAME"/>
+ </index>
+
+ </table>
+
+ <table name="RHQ_OPERATION_HISTORY">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="DTYPE" type="VARCHAR2" required="true" size="8"/>
+ <column name="JOB_NAME" type="VARCHAR2" required="true" size="100"/>
+ <column name="JOB_GROUP" type="VARCHAR2" required="true" size="100"/>
+ <column name="OPERATION_DEF_ID" type="INTEGER" required="true" references="RHQ_OPERATION_DEF"/>
+ <column name="STATUS" type="VARCHAR2" required="true" size="16"/>
+ <column name="ERROR_MESSAGE" type="LONGVARCHAR" required="false"/>
+ <column name="SUBJECT_NAME" type="VARCHAR2" required="true" size="100"/>
+ <column name="CTIME" type="LONG" required="true"/>
+ <column name="STIME" type="LONG" required="true"/>
+ <column name="MTIME" type="LONG" required="true"/>
+ <column name="PARAMETERS_CONFIG_ID" type="INTEGER" required="false" references="RHQ_CONFIG"/>
+
+ <!-- for resource history -->
+ <column name="RESOURCE_ID" type="INTEGER" required="false" references="RHQ_RESOURCE"/>
+ <column name="RESULTS_CONFIG_ID" type="INTEGER" required="false" references="RHQ_CONFIG"/>
+ <column name="GROUP_HISTORY_ID" type="INTEGER" required="false" references="RHQ_OPERATION_HISTORY"/>
+
+ <!-- for group history -->
+ <column name="GROUP_ID" type="INTEGER" required="false" references="RHQ_RESOURCE_GROUP"/>
+
+ <index name="RHQ_OPERATION_HISTORY_JOB_IDX" unique="true">
+ <field ref="JOB_NAME"/>
+ <field ref="JOB_GROUP"/>
+ <field ref="CTIME"/>
+ </index>
+
+ </table>
+
+ <!--
+ This table is really just to support some specific use-cases.
+ Specifically, to be able to get a list of histories for a specific schedule (aka quartz job)
+ and to be able to query a list of all schedules along with their associated resource/group IDs
+ possibly sorted by their next fire time.
+ Note that a NULL next fire time means it won't fire again and the row is probaby about to be deleted;
+ we can probably not even insert rows with NULL and make it a non-nullable field. But rather than
+ code special conditions into the session bean, we'll allow a short-lived NULL next fire time row.
+ -->
+ <table name="RHQ_OPERATION_SCHEDULE">
+ <column name="JOB_NAME" type="VARCHAR2" required="true" size="100"/>
+ <column name="JOB_GROUP" type="VARCHAR2" required="true" size="100"/>
+ <column name="DTYPE" type="VARCHAR2" required="true" size="8"/>
+ <column name="NEXT_FIRE_TIME" type="LONG" required="false"/>
+
+ <!-- for resource history -->
+ <column name="RESOURCE_ID" type="INTEGER" required="false" references="RHQ_RESOURCE"/>
+
+ <!-- for group history -->
+ <column name="GROUP_ID" type="INTEGER" required="false" references="RHQ_RESOURCE_GROUP"/>
+
+ <!--
+ Note that this is the same primary key that Quartz uses for its schedules (RHQ_qrtz_job_details).
+ We do not need to add DTYPE to the key, because we ensure the name/group are unique
+ across resource/group schedules
+ -->
+ <constraint name="RHQ_OPERATION_SCHEDULE_KEY">
+ <primaryKey>
+ <field ref="JOB_NAME"/>
+ <field ref="JOB_GROUP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+<!-- END: operation-schema.xml -->
+<!-- BEGIN: sysconfig-schema.xml -->
+
+
+ <table name="RHQ_SYSTEM_CONFIG">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="PROPERTY_KEY" type="VARCHAR2" size="80"/>
+ <column name="PROPERTY_VALUE" type="VARCHAR2" size="300"/>
+ <column name="DEFAULT_PROPERTY_VALUE" type="VARCHAR2" size="300"/>
+ <column name="FREAD_ONLY" type="BOOLEAN" default="FALSE"/>
+
+ <index name="RHQ_SYSTEM_CONFIG_KEY_INDX" unique="true">
+ <field ref="PROPERTY_KEY"/>
+ </index>
+ </table>
+
+<!-- END: sysconfig-schema.xml -->
+<!-- BEGIN: scheduler-schema.xml -->
+
+
+ <table name="RHQ_QRTZ_JOB_DETAILS">
+ <column name="JOB_NAME" required="true" type="VARCHAR2" size="80"/>
+ <column name="JOB_GROUP" required="true" type="VARCHAR2" size="80"/>
+ <column name="DESCRIPTION" required="false" type="VARCHAR2" size="120"/>
+ <column name="JOB_CLASS_NAME" required="true" type="VARCHAR2" size="128"/>
+ <column name="IS_DURABLE" required="true" type="BOOLEAN" default="FALSE"/>
+ <column name="IS_VOLATILE" required="true" type="BOOLEAN"/>
+ <column name="IS_STATEFUL" required="true" type="BOOLEAN" default="FALSE"/>
+ <column name="REQUESTS_RECOVERY" required="true" type="BOOLEAN" default="FALSE"/>
+ <column name="JOB_DATA" required="false" type="BLOB"/>
+
+ <constraint name="RHQ_PK_QRTZ_JOB_DETAILS">
+ <primaryKey>
+ <field ref="JOB_NAME"/>
+ <field ref="JOB_GROUP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+ <table name="RHQ_QRTZ_JOB_LISTENERS">
+ <column name="JOB_NAME" required="true" type="VARCHAR2" size="80"/>
+ <column name="JOB_GROUP" required="true" type="VARCHAR2" size="80"/>
+ <column name="JOB_LISTENER" required="true" type="VARCHAR2" size="80"/>
+
+ <constraint name="RHQ_PK_QRTZ_JOB_LISTENERS">
+ <primaryKey>
+ <field ref="JOB_NAME"/>
+ <field ref="JOB_GROUP"/>
+ <field ref="JOB_LISTENER"/>
+ </primaryKey>
+ </constraint>
+ <constraint name="RHQ_FK_QRTZ_JOB_LSTNRS_JN_JG">
+ <foreignKey local="JOB_NAME,JOB_GROUP"
+ references="RHQ_QRTZ_JOB_DETAILS(JOB_NAME,JOB_GROUP)"
+ ondelete="cascade"/>
+ </constraint>
+ </table>
+
+ <table name="RHQ_QRTZ_TRIGGERS">
+ <column name="TRIGGER_NAME" type="VARCHAR2" required="true" size="80"/>
+ <column name="TRIGGER_GROUP" type="VARCHAR2" required="true" size="80"/>
+ <column name="JOB_NAME" type="VARCHAR2" required="true" size="80"/>
+ <column name="JOB_GROUP" type="VARCHAR2" required="true" size="80"/>
+ <column name="IS_VOLATILE" type="BOOLEAN" required="true"/>
+ <column name="DESCRIPTION" type="VARCHAR2" required="false" size="120"/>
+ <column name="NEXT_FIRE_TIME" type="LONG" required="false"/>
+ <column name="PREV_FIRE_TIME" type="LONG" required="false"/>
+ <column name="PRIORITY" type="INTEGER" required="false"/>
+ <column name="TRIGGER_STATE" type="VARCHAR" required="true" size="16"/>
+ <column name="TRIGGER_TYPE" type="VARCHAR" required="true" size="8"/>
+ <column name="START_TIME" type="LONG" required="true"/>
+ <column name="END_TIME" type="LONG" required="false"/>
+ <column name="CALENDAR_NAME" type="VARCHAR2" required="false" size="80"/>
+ <column name="MISFIRE_INSTR" type="INTEGER" required="false"/>
+ <column name="JOB_DATA" type="BLOB" required="false"/>
+
+ <constraint name="RHQ_PK_QRTZ_TRIGGERS">
+ <primaryKey>
+ <field ref="TRIGGER_NAME"/>
+ <field ref="TRIGGER_GROUP"/>
+ </primaryKey>
+ </constraint>
+ <constraint name="RHQ_FK_QRTZ_TRIGGERS_JN_JG">
+ <foreignKey local="JOB_NAME,JOB_GROUP"
+ references="RHQ_QRTZ_JOB_DETAILS(JOB_NAME,JOB_GROUP)"
+ ondelete="cascade"/>
+ </constraint>
+
+ <!-- Quartz docs recommend these indexes. -->
+ <index name="RHQ_QRTZ_TRIGGERS_JN_JG_IDX">
+ <field ref="JOB_NAME"/>
+ <field ref="JOB_GROUP"/>
+ </index>
+ <index name="RHQ_QRTZ_TRIGGERS_NFT_IDX">
+ <field ref="NEXT_FIRE_TIME"/>
+ </index>
+ <index name="RHQ_QRTZ_TRIGGERS_TS_IDX">
+ <field ref="TRIGGER_STATE"/>
+ </index>
+ <index name="RHQ_QRTZ_TRIGGERS_TS_NFT_IDX">
+ <field ref="TRIGGER_STATE"/>
+ <field ref="NEXT_FIRE_TIME"/>
+ </index>
+
+ </table>
+
+ <table name="RHQ_QRTZ_SIMPLE_TRIGGERS">
+ <column name="TRIGGER_NAME" type="VARCHAR2" required="true" size="80"/>
+ <column name="TRIGGER_GROUP" type="VARCHAR2" required="true" size="80"/>
+ <column name="REPEAT_COUNT" type="LONG" required="true"/>
+ <column name="REPEAT_INTERVAL" type="LONG" required="true"/>
+ <column name="TIMES_TRIGGERED" type="LONG" required="true"/>
+
+ <constraint name="RHQ_PK_QRTZ_SIMPLE_TRIGGERS">
+ <primaryKey>
+ <field ref="TRIGGER_NAME"/>
+ <field ref="TRIGGER_GROUP"/>
+ </primaryKey>
+ </constraint>
+ <constraint name="RHQ_FK_QRTZ_SIMPLE_TRGRS_TN_TG">
+ <foreignKey local="TRIGGER_NAME,TRIGGER_GROUP"
+ references="RHQ_QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP)"
+ ondelete="cascade"/>
+ </constraint>
+
+ <!-- Quartz docs recommend this index. -->
+ <!-- Commenting out, because Oracle auto-creates an index for the
+ primary key column(s) and fails if you try to create another
+ index for the same column(s) (ips, 03/29/07).
+ -->
+ <!--
+ <index name="RHQ_QRTZ_SIMPLE_TRGRS_TN_TG_IDX">
+ <field ref="TRIGGER_NAME"/>
+ <field ref="TRIGGER_GROUP"/>
+ </index>
+ -->
+ </table>
+
+ <table name="RHQ_QRTZ_CRON_TRIGGERS">
+ <column name="TRIGGER_NAME" type="VARCHAR2" size="80" required="true"/>
+ <column name="TRIGGER_GROUP" type="VARCHAR2" size="80" required="true"/>
+ <column name="CRON_EXPRESSION" type="VARCHAR2" size="80" required="true"/>
+ <column name="TIME_ZONE_ID" type="VARCHAR2" size="80" required="false"/>
+
+ <constraint name="RHQ_PK_QRTZ_CRON_TRIGGERS">
+ <primaryKey>
+ <field ref="TRIGGER_NAME"/>
+ <field ref="TRIGGER_GROUP"/>
+ </primaryKey>
+ </constraint>
+ <constraint name="RHQ_FK_QRTZ_CRON_TRIG_TN_TG">
+ <foreignKey local="TRIGGER_NAME,TRIGGER_GROUP"
+ references="RHQ_QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP)"
+ ondelete="cascade"/>
+ </constraint>
+
+ <!-- Quartz docs recommend this index. -->
+ <!-- Commenting out, because Oracle auto-creates an index for the
+ primary key column(s) and fails if you try to create another
+ index for the same column(s) (ips, 03/29/07).
+ -->
+ <!--
+ <index name="RHQ_QRTZ_CRON_TRGRS_TN_TG_IDX">
+ <field ref="TRIGGER_NAME"/>
+ <field ref="TRIGGER_GROUP"/>
+ </index>
+ -->
+ </table>
+
+ <table name="RHQ_QRTZ_BLOB_TRIGGERS">
+ <column name="TRIGGER_NAME" type="VARCHAR2" size="80" required="true"/>
+ <column name="TRIGGER_GROUP" type="VARCHAR2" size="80" required="true"/>
+ <column name="BLOB_DATA" type="BLOB" required="false"/>
+
+ <constraint name="RHQ_PK_QRTZ_BLOB_TRIGGERS">
+ <primaryKey>
+ <field ref="TRIGGER_NAME"/>
+ <field ref="TRIGGER_GROUP"/>
+ </primaryKey>
+ </constraint>
+ <constraint name="RHQ_FK_QRTZ_BLOB_TRIGG_TN_TG">
+ <foreignKey local="TRIGGER_NAME,TRIGGER_GROUP"
+ references="RHQ_QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP)"
+ ondelete="cascade"/>
+ </constraint>
+
+ <!-- Quartz docs recommend this index. -->
+ <!-- Commenting out, because Oracle auto-creates an index for the
+ primary key column(s) and fails if you try to create another
+ index for the same column(s) (ips, 03/29/07).
+ -->
+ <!--
+ <index name="RHQ_QRTZ_BLOB_TRGRS_TN_TG_IDX">
+ <field ref="TRIGGER_NAME"/>
+ <field ref="TRIGGER_GROUP"/>
+ </index>
+ -->
+ </table>
+
+ <table name="RHQ_QRTZ_TRIGGER_LISTENERS">
+ <column name="TRIGGER_NAME" type="VARCHAR2" size="80" required="true"/>
+ <column name="TRIGGER_GROUP" type="VARCHAR2" size="80" required="true"/>
+ <column name="TRIGGER_LISTENER" type="VARCHAR2" size="80" required="true"/>
+
+ <constraint name="RHQ_PK_QRTZ_TRIGGER_LISTENERS">
+ <primaryKey>
+ <field ref="TRIGGER_NAME"/>
+ <field ref="TRIGGER_GROUP"/>
+ <field ref="TRIGGER_LISTENER"/>
+ </primaryKey>
+ </constraint>
+ <constraint name="RHQ_FK_QRTZ_TRGR_LSTNRS_TN_TG">
+ <foreignKey local="TRIGGER_NAME,TRIGGER_GROUP"
+ references="RHQ_QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP)"
+ ondelete="cascade"/>
+ </constraint>
+
+ <!-- Quartz docs recommend this index. -->
+ <index name="RHQ_QRTZ_TRGR_LSTNRS_TN_TG_IDX">
+ <field ref="TRIGGER_NAME"/>
+ <field ref="TRIGGER_GROUP"/>
+ </index>
+
+ </table>
+
+ <table name="RHQ_QRTZ_FIRED_TRIGGERS">
+ <column name="ENTRY_ID" primarykey="true" type="VARCHAR2" size="95" required="true"/>
+ <column name="TRIGGER_NAME" type="VARCHAR2" size="80" required="true"/>
+ <column name="TRIGGER_GROUP" type="VARCHAR2" size="80" required="true"/>
+ <column name="INSTANCE_NAME" type="VARCHAR2" size="80" required="true"/>
+ <column name="FIRED_TIME" type="LONG" required="true"/>
+ <column name="PRIORITY" type="INTEGER" required="false"/>
+ <column name="STATE" type="VARCHAR2" size="16" required="true"/>
+ <column name="IS_VOLATILE" type="BOOLEAN" required="true"/>
+ <column name="JOB_NAME" type="VARCHAR2" size="80" required="false"/>
+ <column name="JOB_GROUP" type="VARCHAR2" size="80" required="false"/>
+ <column name="IS_STATEFUL" type="BOOLEAN" required="false"/>
+ <column name="REQUESTS_RECOVERY" type="BOOLEAN" required="false"/>
+
+ <!-- Quartz docs recommend these indexes. -->
+ <index name="RHQ_QRTZ_FIRED_TRGRS_TN_IDX">
+ <field ref="TRIGGER_NAME"/>
+ </index>
+ <index name="RHQ_QRTZ_FIRED_TRGRS_TG_IDX">
+ <field ref="TRIGGER_GROUP"/>
+ </index>
+ <index name="RHQ_QRTZ_FIRED_TRGRS_TN_TG_IDX">
+ <field ref="TRIGGER_NAME"/>
+ <field ref="TRIGGER_GROUP"/>
+ </index>
+ <index name="RHQ_QRTZ_FIRED_TRGRS_IN_IDX">
+ <field ref="INSTANCE_NAME"/>
+ </index>
+ <index name="RHQ_QRTZ_FIRED_TRGRS_JN_IDX">
+ <field ref="JOB_NAME"/>
+ </index>
+ <index name="RHQ_QRTZ_FIRED_TRGRS_JG_IDX">
+ <field ref="JOB_GROUP"/>
+ </index>
+
+ </table>
+
+ <table name="RHQ_QRTZ_CALENDARS">
+ <column name="CALENDAR_NAME" primarykey="true" type="VARCHAR2" size="80" required="true"/>
+ <column name="CALENDAR" type="BLOB" required="true"/>
+ </table>
+
+ <table name="RHQ_QRTZ_PAUSED_TRIGGER_GRPS">
+ <column name="TRIGGER_GROUP" primarykey="true" type="VARCHAR2" size="80" required="true"/>
+ </table>
+
+ <table name="RHQ_QRTZ_SCHEDULER_STATE">
+ <column name="INSTANCE_NAME" primarykey="true" type="VARCHAR2" size="80" required="true"/>
+ <column name="LAST_CHECKIN_TIME" type="LONG" required="true"/>
+ <column name="CHECKIN_INTERVAL" type="LONG" required="true"/>
+ <column name="RECOVERER" type="VARCHAR2" size="80" required="false"/>
+ </table>
+
+ <table name="RHQ_QRTZ_LOCKS">
+ <column name="LOCK_NAME" primarykey="true" type="VARCHAR2" size="40" required="true"/>
+ <data LOCK_NAME="TRIGGER_ACCESS"/>
+ <data LOCK_NAME="JOB_ACCESS"/>
+ <data LOCK_NAME="CALENDAR_ACCESS"/>
+ <data LOCK_NAME="STATE_ACCESS"/>
+ <data LOCK_NAME="MISFIRE_ACCESS"/>
+ </table>
+
+<!-- END: scheduler-schema.xml -->
+<!-- BEGIN: amps-schema.xml -->
+
+
+
+ <table name="RHQ_PLUGIN">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" size="200" type="VARCHAR2" required="true"/>
+ <column name="DISPLAY_NAME" size="200" type="VARCHAR2" required="true"/>
+ <column name="DESCRIPTION" size="4000" type="VARCHAR2" required="false"/>
+ <column name="VERSION" size="200" type="VARCHAR2" required="false"/>
+ <column name="ENABLED" type="BOOLEAN" required="true"/>
+ <column name="HELP" type="CLOB" required="false"/>
+ <column name="PATH" size="500" type="VARCHAR2" required="true"/>
+ <column name="MD5" size="100" type="VARCHAR2" required="true"/>
+ <column name="CTIME" type="LONG" required="true"/>
+ <column name="MTIME" type="LONG" required="true"/>
+ <column name="CONTENT" type="BLOB" required="false"/>
+
+ <index name="RHQ_PLUGIN_NAME_IDX" unique="true">
+ <field ref="NAME"/>
+ </index>
+ </table>
+
+<!-- END: amps-schema.xml -->
+<!-- BEGIN: measurement-schema.xml -->
+
+ <table name="RHQ_MEASUREMENT_DEF">
+
+ <!-- === required columns === -->
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="RESOURCE_TYPE_ID" type="INTEGER" required="true" references="RHQ_RESOURCE_TYPE(ID)"/>
+ <column name="NAME" type="VARCHAR2" size="100" required="true"/>
+
+ <!-- === optional columns === -->
+ <!-- an OSGI version range - if null, the metric def applies to all versions of the associated resource type -->
+ <column name="RESOURCE_VERSION_RANGE" type="VARCHAR2" size="100"/>
+ <column name="CATEGORY" type="SMALLINT"/>
+ <column name="UNITS" type="SMALLINT"/>
+ <column name="NUMERIC_TYPE" type="SMALLINT"/>
+ <column name="DISPLAY_TYPE" type="SMALLINT"/>
+ <column name="DATA_TYPE" type="SMALLINT"/>
+ <column name="RAW_NUMERIC_TYPE" type="SMALLINT"/>
+ <column name="DEFAULT_ON" type="BOOLEAN" default="false"/>
+ <column name="DEFAULT_INTERVAL" type="LONG" />
+ <column name="DISPLAY_NAME" type="VARCHAR2" size="100"/>
+ <column name="DISPLAY_ORDER" type="INTEGER" default="1000"/>
+ <column name="DESCRIPTION" type="VARCHAR2" size="500"/>
+ <column name="DESTINATION_TYPE" type="VARCHAR2" size="100"/>
+
+ <column name="VERSION" type="INTEGER"/>
+ <!-- for optimistic locking -->
+
+ <!-- === business key (RESOURCE_TYPE_ID + NAME + RAW_NUMERIC_TYPE) === -->
+ <index name="RHQ_METRIC_DEF_KEY_IDX" unique="true">
+ <field ref="RESOURCE_TYPE_ID"/>
+ <field ref="NAME"/>
+ <field ref="RAW_NUMERIC_TYPE"/>
+ </index>
+ </table>
+
+
+ <table name="RHQ_MEASUREMENT_SCHED">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+
+ <column name="ENABLED" type="BOOLEAN" default="false"/>
+ <column name="MTIME" type="LONG" />
+ <column name="DEFINITION" type="INTEGER" references="RHQ_MEASUREMENT_DEF(ID)"/>
+ <column name="VERSION" type="INTEGER" />
+ <column name="COLL_INTERVAL" type="LONG" />
+ <column name="RESOURCE_ID" type="INTEGER" references="RHQ_RESOURCE(ID)"/>
+ <index name="RHQ_MEAS_SCHED_UNIQ" unique="true">
+ <field ref="RESOURCE_ID"/>
+ <field ref="DEFINITION"/>
+ </index>
+ </table>
+
+
+ <table name="RHQ_MEASUREMENT_BLINE">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+
+ <column name="BL_USER_ENTERED" type="BOOLEAN" default="false" required="true"/>
+ <column name="BL_MIN" type="DOUBLE" required="true"/>
+ <column name="BL_MAX" type="DOUBLE" required="true"/>
+ <column name="BL_MEAN" type="DOUBLE" required="true"/>
+ <column name="BL_COMPUTE_TIME" type="LONG" required="true"/>
+ <column name="SCHEDULE_ID" type="INTEGER" required="true" references="RHQ_MEASUREMENT_SCHED(ID)"/>
+ <index name="RHQ_MEAS_BASELINE_CTIME_IDX">
+ <field ref="BL_COMPUTE_TIME"/>
+ </index>
+ <index name="RHQ_MEAS_BASELINE_SID_IDX">
+ <field ref="SCHEDULE_ID"/>
+ </index>
+ </table>
+
+
+ <table name="RHQ_MEASUREMENT_DATA_NUM_1H" logging="false" cache="true"
+ tablespace="DEFAULT" storage-options="freelists 20">
+
+ <column name="TIME_STAMP" required="true" type="LONG"/>
+ <column name="SCHEDULE_ID" required="true" type="INTEGER"/>
+ <column name="VALUE" required="false" type="DOUBLE"/>
+ <column name="MINVALUE" required="false" type="DOUBLE"/>
+ <column name="MAXVALUE" required="false" type="DOUBLE"/>
+
+ <constraint name="RHQ_MEAS_DATA_1H_ID_TIME_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+
+ <index name="RHQ_MEAS_DATA_1H_TIME_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ </table>
+
+
+ <table name="RHQ_MEASUREMENT_DATA_NUM_6H" logging="false" cache="true"
+ tablespace="DEFAULT" storage-options="freelists 20">
+
+ <column name="TIME_STAMP" required="true" type="LONG"/>
+ <column name="SCHEDULE_ID" required="true" type="INTEGER"/>
+ <column name="VALUE" required="false" type="DOUBLE"/>
+ <column name="MINVALUE" required="false" type="DOUBLE"/>
+ <column name="MAXVALUE" required="false" type="DOUBLE"/>
+
+ <constraint name="RHQ_MEAS_DATA_6H_ID_TIME_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+
+ <index name="RHQ_MEAS_DATA_6H_TIME_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ </table>
+
+
+ <table name="RHQ_MEASUREMENT_DATA_NUM_1D" logging="false" cache="true"
+ tablespace="DEFAULT" storage-options="freelists 20">
+
+ <column name="TIME_STAMP" required="true" type="LONG"/>
+ <column name="SCHEDULE_ID" required="true" type="INTEGER"/>
+ <column name="VALUE" required="false" type="DOUBLE"/>
+ <column name="MINVALUE" required="false" type="DOUBLE"/>
+ <column name="MAXVALUE" required="false" type="DOUBLE"/>
+
+ <constraint name="RHQ_MEAS_DATA_1D_ID_TIME_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+
+ <table name="RHQ_MEASUREMENT_DATA_TRAIT">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER" />
+ <column name="VALUE" type="VARCHAR2" size="4000" />
+ <constraint name="RHQ_MEAS_DATA_TRAIT_ID_TIME_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+
+ <table name="RHQ_CALLTIME_DATA_KEY">
+ <column name="ID" type="INTEGER" default="sequence-only" initial="10001" primarykey="true" required="true"/>
+ <column name="SCHEDULE_ID" type="INTEGER" required="true"/>
+ <column name="CALL_DESTINATION" type="VARCHAR2" size="4000" required="true"/>
+ <index name="RHQ_CALLTIME_DATA_KEY_IDX" unique="true">
+ <field ref="SCHEDULE_ID"/>
+ <field ref="CALL_DESTINATION"/>
+ </index>
+ </table>
+
+
+ <table name="RHQ_CALLTIME_DATA_VALUE">
+ <column name="ID" type="INTEGER" default="sequence-only" initial="10001" primarykey="true" required="true"/>
+ <column name="KEY_ID" type="INTEGER" references="RHQ_CALLTIME_DATA_KEY(ID)" required="true"/>
+ <column name="BEGIN_TIME" type="LONG" required="true"/>
+ <column name="END_TIME" type="LONG" required="true"/>
+ <column name="MINIMUM" type="DOUBLE" required="true"/>
+ <column name="MAXIMUM" type="DOUBLE" required="true"/>
+ <column name="TOTAL" type="DOUBLE" required="true"/>
+ <column name="COUNT" type="LONG" required="true"/>
+ </table>
+
+
+ <table name="RHQ_AVAILABILITY">
+ <column name="ID" type="INTEGER" default="sequence-only" initial="10001" primarykey="true" required="true"/>
+ <column name="RESOURCE_ID" type="INTEGER" required="true" references="RHQ_RESOURCE(ID)"/>
+ <column name="START_TIME" type="LONG" required="true" />
+ <column name="END_TIME" type="LONG" required="false" />
+ <column name="AVAILABILITY_TYPE" type="SMALLINT" required="false" />
+ <index name="RHQ_AVAIL_RESOURCE_START_IDX">
+ <field ref="RESOURCE_ID"/>
+ <field ref="START_TIME"/>
+ </index>
+ <!-- only one null row can exist for any resource -->
+ <index name="RHQ_AVAIL_RESOURCE_END_IDX" condition="END_TIME IS NULL">
+ <field ref="RESOURCE_ID"/>
+ <field ref="END_TIME" />
+ </index>
+ </table>
+
+ <table name="RHQ_RESOURCE_AVAIL">
+ <column name="ID" type="INTEGER" default="sequence-only" initial="10001" primarykey="true" required="true"/>
+ <column name="RESOURCE_ID" type="INTEGER" required="true" references="RHQ_RESOURCE(ID)" ondelete="cascade"/>
+ <column name="AVAILABILITY_TYPE" type="SMALLINT" required="false" />
+ <index name="RHQ_RESOURCE_AVAIL_IDX">
+ <field ref="RESOURCE_ID" />
+ </index>
+ </table>
+
+ <!-- !!!!! REMOVED !!!!! -->
+ <table name="RHQ_MEASUREMENT_OOB" obsolete="true">
+ <column name="ID" type="INTEGER" default="sequence-only" initial="10001" primarykey="true" required="true"/>
+ <column name="SCHEDULE_ID" type="INTEGER" references="RHQ_MEASUREMENT_SCHED(ID)" required="true"/>
+ <column name="OCCURRED" type="LONG" required="true"/>
+ <column name="DIFF" type="DOUBLE" required="true"/>
+
+ <index name="RHQ_MEASUREMENT_OOB_IDX" unique="true">
+ <field ref="SCHEDULE_ID" />
+ <field ref="OCCURRED" />
+ </index>
+ </table>
+
+ <table name="RHQ_MEASUREMENT_OOB">
+ <column name="SCHEDULE_ID" type="INTEGER" references="RHQ_MEASUREMENT_SCHED(ID)" required="true"/>
+ <column name="TIME_STAMP" type="LONG" required="true"/>
+ <column name="OOB_FACTOR" type="INTEGER" required="true" />
+ <constraint name="RHQ_MEAS_OOB_ID_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+ <table name="RHQ_MEASUREMENT_OOB_TMP">
+ <column name="SCHEDULE_ID" type="INTEGER" required="true"/>
+ <column name="TIME_STAMP" type="LONG" required="true"/>
+ <column name="OOB_FACTOR" type="INTEGER" required="true" />
+ <constraint name="RHQ_MEAS_OOB_TMP_ID_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+ <table name="RHQ_NUMBERS">
+ <column name="i" type="INTEGER" default="sequence-only" initial="10001" primarykey="true" required="true" />
+ </table>
+
+
+ <table name="RHQ_MEAS_DATA_NUM_R00">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R00_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R00_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+ <table name="RHQ_MEAS_DATA_NUM_R01">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R01_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R01_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+ <table name="RHQ_MEAS_DATA_NUM_R02">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R02_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R02_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+ <table name="RHQ_MEAS_DATA_NUM_R03">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R03_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R03_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+ <table name="RHQ_MEAS_DATA_NUM_R04">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R04_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R04_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+ <table name="RHQ_MEAS_DATA_NUM_R05">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R05_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R05_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+ <table name="RHQ_MEAS_DATA_NUM_R06">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R06_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R06_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+ <table name="RHQ_MEAS_DATA_NUM_R07">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R07_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R07_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+ <table name="RHQ_MEAS_DATA_NUM_R08">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R08_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R08_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+ <table name="RHQ_MEAS_DATA_NUM_R09">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R09_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R09_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+ <table name="RHQ_MEAS_DATA_NUM_R10">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R10_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R10_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+ <table name="RHQ_MEAS_DATA_NUM_R11">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R11_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R11_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+ <table name="RHQ_MEAS_DATA_NUM_R12">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R12_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R12_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+ <table name="RHQ_MEAS_DATA_NUM_R13">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R13_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R13_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+ <table name="RHQ_MEAS_DATA_NUM_R14">
+ <column name="TIME_STAMP" type="LONG"/>
+ <column name="SCHEDULE_ID" type="INTEGER"/>
+ <column name="VALUE" type="DOUBLE"/>
+ <index name="RHQ_MEAS_DATA_R14_TS_IDX">
+ <field ref="TIME_STAMP"/>
+ </index>
+ <constraint name="RHQ_MEAS_DATA_NUM_R14_ID_T_PK">
+ <primaryKey>
+ <field ref="SCHEDULE_ID"/>
+ <field ref="TIME_STAMP"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+<!-- END: measurement-schema.xml -->
+<!-- BEGIN: content-schema.xml -->
+
+
+ <table name="RHQ_ARCHITECTURE">
+ <column name="ID" default="sequence-only" initial="100" primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" size="50" type="VARCHAR2" required="true"/>
+ <index name="RHQ_ARCHITECTURE_NAME_IDX" unique="true">
+ <field ref="NAME"/>
+ </index>
+ </table>
+
+ <table name="RHQ_CONTENT_SOURCE_TYPE">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" size="200" type="VARCHAR2" required="true"/>
+ <column name="DISPLAY_NAME" size="200" type="VARCHAR2" required="false"/>
+ <column name="DESCRIPTION" size="500" type="VARCHAR2" required="false"/>
+ <column name="PLUGIN_NAME" size="100" type="VARCHAR2" required="false"/>
+ <!-- we might want this as part of natural key -->
+ <column name="DEFAULT_LAZY_LOAD" type="BOOLEAN" required="true"/>
+ <column name="DEFAULT_DOWNLOAD_MODE" size="16" type="VARCHAR2" required="true"/>
+ <column name="DEFAULT_SYNC_SCHEDULE" size="64" type="VARCHAR2" required="false"/>
+ <column name="API_CLASS" size="100" type="VARCHAR2" required="true"/>
+
+ <column name="SOURCE_CONFIG_DEF_ID" type="INTEGER" references="RHQ_CONFIG_DEF" required="false"/>
+
+ <index name="RHQ_CONTENT_SOURCE_TYPE_IDX" unique="true">
+ <field ref="NAME"/>
+ <!-- <field ref="PLUGIN_NAME"/> -->
+ </index>
+ </table>
+
+ <table name="RHQ_CONTENT_SOURCE">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" size="200" type="VARCHAR2" required="true"/>
+ <column name="DESCRIPTION" size="500" type="VARCHAR2" required="false"/>
+ <column name="LAZY_LOAD" type="BOOLEAN" required="true"/>
+ <column name="DOWNLOAD_MODE" size="16" type="VARCHAR2" required="true"/>
+ <column name="SYNC_SCHEDULE" size="64" type="VARCHAR2" required="false"/>
+ <column name="LOAD_ERROR_MESSAGE" type="LONGVARCHAR" required="false"/>
+ <column name="CREATION_TIME" type="LONG" required="true"/>
+ <column name="LAST_MODIFIED_TIME" type="LONG" required="true"/>
+
+ <column name="CONTENT_SOURCE_TYPE_ID" type="INTEGER" references="RHQ_CONTENT_SOURCE_TYPE" required="true"/>
+ <column name="CONFIGURATION_ID" type="INTEGER" references="RHQ_CONFIG" required="false"/>
+
+ <index name="RHQ_CONTENT_SOURCE_IDX" unique="true">
+ <field ref="NAME"/>
+ <field ref="CONTENT_SOURCE_TYPE_ID"/>
+ </index>
+ </table>
+
+ <table name="RHQ_CHANNEL">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" size="200" type="VARCHAR2" required="true"/>
+ <column name="DESCRIPTION" size="500" type="VARCHAR2" required="false"/>
+ <column name="CREATION_TIME" type="LONG" required="true"/>
+ <column name="LAST_MODIFIED_TIME" type="LONG" required="true"/>
+
+ <index name="RHQ_CHANNEL_IDX" unique="true">
+ <field ref="NAME"/>
+ </index>
+ </table>
+
+ <table name="RHQ_PACKAGE_TYPE">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" size="200" type="VARCHAR2" required="true"/>
+ <column name="DISPLAY_NAME" size="200" type="VARCHAR2" required="false"/>
+ <column name="DESCRIPTION" size="500" type="VARCHAR2" required="false"/>
+ <column name="CATEGORY" size="50" type="VARCHAR2" required="false"/>
+ <column name="DISCOVERY_INTERVAL" type="INTEGER" required="false"/>
+ <column name="IS_CREATION_DATA" type="BOOLEAN" required="true"/>
+ <column name="SUPPORTS_ARCHITECTURE" type="BOOLEAN" required="true"/>
+
+ <column name="RESOURCE_TYPE_ID" type="INTEGER" references="RHQ_RESOURCE_TYPE" required="true"/>
+ <column name="DEPLOYMENT_CONFIG_DEF_ID" type="INTEGER" references="RHQ_CONFIG_DEF" required="false"/>
+ <column name="PACKAGE_EXTRA_CONFIG_ID" type="INTEGER" references="RHQ_CONFIG_DEF" required="false"/>
+
+ <index name="RHQ_PACKAGE_TYPE_IDX" unique="true">
+ <field ref="NAME"/>
+ <field ref="RESOURCE_TYPE_ID"/>
+ </index>
+
+ </table>
+
+ <table name="RHQ_PACKAGE">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" size="200" type="VARCHAR2" required="true"/>
+ <column name="CLASSIFICATION" size="200" type="VARCHAR2" required="false"/>
+
+ <column name="PACKAGE_TYPE_ID" type="INTEGER" references="RHQ_PACKAGE_TYPE" required="true"/>
+
+ <index name="RHQ_PACKAGE_IDX" unique="true">
+ <field ref="NAME"/>
+ <field ref="PACKAGE_TYPE_ID"/>
+ </index>
+ </table>
+
+ <table name="RHQ_PACKAGE_BITS">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="BITS" type="BLOB" required="false"/>
+ </table>
+
+ <table name="RHQ_PACKAGE_VERSION">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="DISPLAY_NAME" size="200" type="VARCHAR2" required="false"/>
+ <column name="SHORT_DESCRIPTION" size="10000" type="CLOB" required="false"/>
+ <column name="LONG_DESCRIPTION" size="50000" type="CLOB" required="false"/>
+ <column name="VERSION" size="500" type="VARCHAR2" required="true"/>
+ <column name="DISPLAY_VERSION" size="500" type="VARCHAR2" required="false"/>
+ <column name="FILE_NAME" size="255" type="VARCHAR2" required="false"/>
+ <column name="FILE_SIZE" type="LONG" required="false"/>
+ <column name="FILE_MD5" size="32" type="VARCHAR2" required="false"/>
+ <column name="FILE_SHA256" size="64" type="VARCHAR2" required="false"/>
+ <column name="FILE_CREATION_TIME" type="LONG" required="false"/>
+ <column name="LICENSE_NAME" size="255" type="VARCHAR2" required="false"/>
+ <column name="LICENSE_VERSION" size="20" type="VARCHAR2" required="false"/>
+ <column name="METADATA" type="BLOB" required="false"/>
+
+ <column name="PACKAGE_ID" type="INTEGER" references="RHQ_PACKAGE" required="true"/>
+ <column name="ARCHITECTURE_ID" type="INTEGER" references="RHQ_ARCHITECTURE" required="true"/>
+ <column name="CONFIG_ID" type="INTEGER" references="RHQ_CONFIG" required="false"/>
+ <column name="PACKAGE_BITS_ID" type="INTEGER" references="RHQ_PACKAGE_BITS" required="false"/>
+
+ <index name="RHQ_PACKAGE_VERSION_IDX" unique="true">
+ <field ref="PACKAGE_ID"/>
+ <field ref="VERSION"/>
+ <field ref="ARCHITECTURE_ID"/>
+ </index>
+
+ </table>
+
+ <table name="RHQ_CONTENT_REQ">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="RESOURCE_ID" type="INTEGER" required="true" references="RHQ_RESOURCE"/>
+ <column name="STATUS" type="VARCHAR2" required="true" size="16"/>
+ <column name="ERROR_MESSAGE" type="LONGVARCHAR" required="false"/>
+ <column name="SUBJECT_NAME" type="VARCHAR2" required="true" size="100"/>
+ <column name="CTIME" type="LONG" required="true"/>
+ <column name="MTIME" type="LONG" required="true"/>
+ <column name="REQUEST_TYPE" type="VARCHAR2" required="true" size="20"/>
+ <column name="NOTES" type="VARCHAR2" required="false" size="512"/>
+ </table>
+
+ <table name="RHQ_INSTALLED_PACKAGE">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="INSTALLATION_TIME" type="LONG" required="false"/>
+
+ <column name="RESOURCE_ID" type="INTEGER" references="RHQ_RESOURCE" required="true"/>
+ <column name="PACKAGE_VERSION_ID" type="INTEGER" references="RHQ_PACKAGE_VERSION" required="true"/>
+ <column name="SUBJECT_ID" type="INTEGER" references="RHQ_SUBJECT" required="false"/>
+ </table>
+
+ <table name="RHQ_INSTALLED_PKG_HIST">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="STATUS" type="VARCHAR2" size="24" required="true"/>
+ <column name="ERROR_MESSAGE" type="LONGVARCHAR" required="false"/>
+ <column name="HISTORY_TIMESTAMP" type="LONG" required="false"/>
+
+ <column name="PACKAGE_VERSION_ID" type="INTEGER" references="RHQ_PACKAGE_VERSION" required="true"/>
+ <column name="RESOURCE_ID" type="INTEGER" references="RHQ_RESOURCE" required="true"/>
+ <column name="DEPLOYMENT_CONFIG_ID" type="INTEGER" references="RHQ_CONFIG" required="false"/>
+ <column name="CONTENT_SERVICE_REQUEST_ID" type="INTEGER" references="RHQ_CONTENT_REQ" required="false"/>
+ </table>
+
+ <table name="RHQ_CONTENT_SRC_SYNC">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="STATUS" type="VARCHAR2" size="16" required="true"/>
+ <column name="START_TIME" type="LONG" required="true"/>
+ <column name="END_TIME" type="LONG" required="false"/>
+ <column name="RESULTS" type="LONGVARCHAR" required="false"/>
+
+ <column name="CONTENT_SRC_ID" type="INTEGER" required="true" references="RHQ_CONTENT_SOURCE"/>
+ </table>
+
+ <table name="RHQ_PACKAGE_INST_STEP">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="STEP_KEY" type="VARCHAR2" size="500" required="true"/>
+ <column name="STEP_ORDER" type="INTEGER" required="true"/>
+ <column name="DESCRIPTION" type="VARCHAR2" size="4000" required="true"/>
+ <column name="ERROR_MSG" type="LONGVARCHAR" required="false"/>
+ <column name="RESULT" type="VARCHAR2" size="25" required="true"/>
+
+ <column name="INSTALLED_PKG_HIST_ID" type="INTEGER" references="RHQ_INSTALLED_PKG_HIST"/>
+ </table>
+
+ <table name="RHQ_CHANNEL_RESOURCE_MAP">
+ <column name="CHANNEL_ID" type="INTEGER" required="true" references="RHQ_CHANNEL"/>
+ <column name="RESOURCE_ID" type="INTEGER" required="true" references="RHQ_RESOURCE"/>
+ <column name="CTIME" type="LONG" required="true"/>
+
+ <constraint name="RHQ_CHANNEL_RESOURCE_MAP_KEY">
+ <primaryKey>
+ <field ref="CHANNEL_ID"/>
+ <field ref="RESOURCE_ID"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+ <table name="RHQ_CHANNEL_CONTENT_SRC_MAP">
+ <column name="CHANNEL_ID" type="INTEGER" required="true" references="RHQ_CHANNEL"/>
+ <column name="CONTENT_SRC_ID" type="INTEGER" required="true" references="RHQ_CONTENT_SOURCE"/>
+ <column name="CTIME" type="LONG" required="true"/>
+
+ <constraint name="RHQ_CHAN_CONTENT_SRC_MAP_KEY">
+ <primaryKey>
+ <field ref="CHANNEL_ID"/>
+ <field ref="CONTENT_SRC_ID"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+ <table name="RHQ_CHANNEL_PKG_VERSION_MAP">
+ <column name="CHANNEL_ID" type="INTEGER" required="true" references="RHQ_CHANNEL"/>
+ <column name="PACKAGE_VERSION_ID" type="INTEGER" required="true" references="RHQ_PACKAGE_VERSION"/>
+ <column name="CTIME" type="LONG" required="true"/>
+
+ <constraint name="RHQ_CHANNEL_PKG_VER_MAP_KEY">
+ <primaryKey>
+ <field ref="CHANNEL_ID"/>
+ <field ref="PACKAGE_VERSION_ID"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+ <table name="RHQ_PKG_VER_CONTENT_SRC_MAP">
+ <column name="PACKAGE_VERSION_ID" type="INTEGER" required="true" references="RHQ_PACKAGE_VERSION"/>
+ <column name="CONTENT_SRC_ID" type="INTEGER" required="true" references="RHQ_CONTENT_SOURCE"/>
+ <column name="LOCATION" type="VARCHAR2" size="4000" required="true"/>
+
+ <constraint name="RHQ_PKG_VER_CONTENT_SRC_KEY">
+ <primaryKey>
+ <field ref="PACKAGE_VERSION_ID"/>
+ <field ref="CONTENT_SRC_ID"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+ <table name="RHQ_PKG_PRD_MAP">
+ <column name="PKG_ID" type="INTEGER" required="true" references="RHQ_PACKAGE_VERSION"/>
+ <column name="PRD_ID" type="INTEGER" required="true" references="RHQ_PRD_VER"/>
+
+ <constraint name="RHQ_PKG_PRD_KEY">
+ <primaryKey>
+ <field ref="PKG_ID"/>
+ <field ref="PRD_ID"/>
+ </primaryKey>
+ </constraint>
+
+ </table>
+
+<!-- END: content-schema.xml -->
+<!-- BEGIN: resource-request-schema.xml -->
+
+
+ <table name="RHQ_CREATE_RES_HIST">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="PARENT_RESOURCE_ID" type="INTEGER" required="true" references="RHQ_RESOURCE"/>
+ <column name="CREATED_RESOURCE_NAME" type="VARCHAR2" size="500" required="false"/>
+ <column name="NEW_RESOURCE_KEY" type="VARCHAR2" required="false" size="500"/>
+ <column name="STATUS" type="VARCHAR2" required="true" size="16"/>
+ <column name="ERROR_MESSAGE" type="LONGVARCHAR" required="false"/>
+ <column name="SUBJECT_NAME" type="VARCHAR2" required="true" size="100"/>
+ <column name="CTIME" type="LONG" required="true"/>
+ <column name="MTIME" type="LONG" required="true"/>
+ <column name="RESOURCE_TYPE_ID" type="INTEGER" required="true" references="RHQ_RESOURCE_TYPE"/>
+ <column name="CONFIGURATION_ID" type="INTEGER" required="false" references="RHQ_CONFIG"/>
+ <column name="INSTALLED_PACKAGE_ID" type="INTEGER" required="false" references="RHQ_INSTALLED_PACKAGE"/>
+ </table>
+
+ <table name="RHQ_DELETE_RES_HIST">
+ <column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
+ <column name="ERROR_MESSAGE" type="LONGVARCHAR" required="false"/>
+ <column name="SUBJECT_NAME" type="VARCHAR2" required="true" size="100"/>
+ <column name="CTIME" type="LONG" required="true"/>
+ <column name="MTIME" type="LONG" required="true"/>
+ <column name="STATUS" type="VARCHAR2" required="true" size="16"/>
+ <column name="RESOURCE_ID" type="INTEGER" required="true" references="RHQ_RESOURCE"/>
+ </table>
+
+<!-- END: resource-request-schema.xml -->
+<!-- BEGIN: jms-schema.xml -->
+
+<!-- the schema matches that which would be automatically created by the JMS subsystem -->
+<!-- see deploy/jms/rhq-jdbc-state-service.xml and rhq-jdbc2-service.xml -->
+
+
+ <table name="JMS_MESSAGES">
+ <column name="MESSAGEID" required="true" type="INTEGER" />
+ <column name="DESTINATION" required="true" type="VARCHAR2" size="255" />
+ <column name="TXID" required="false" type="INTEGER" />
+ <column name="TXOP" required="false" type="CHAR" size="1" />
+ <column name="MESSAGEBLOB" required="false" type="BLOB" />
+
+ <constraint name="JMS_MESSAGES_PKEY">
+ <primaryKey>
+ <field ref="MESSAGEID"/>
+ <field ref="DESTINATION"/>
+ </primaryKey>
+ </constraint>
+
+ <index name="JMS_MESSAGES_TXOP_TXID">
+ <field ref="TXOP"/>
+ <field ref="TXID"/>
+ </index>
+ <index name="JMS_MESSAGES_DESTINATION">
+ <field ref="DESTINATION"/>
+ </index>
+ </table>
+
+ <table name="JMS_TRANSACTIONS">
+ <column name="TXID" required="true" type="INTEGER" primarykey="true" />
+ </table>
+
+ <table name="JMS_USERS">
+ <column name="USERID" required="true" type="VARCHAR2" size="32" primarykey="true" />
+ <column name="PASSWD" required="true" type="VARCHAR2" size="32" />
+ <column name="CLIENTID" required="false" type="VARCHAR2" size="128" />
+ </table>
+
+ <table name="JMS_ROLES">
+ <column name="ROLEID" required="true" type="VARCHAR2" size="32" />
+ <column name="USERID" required="true" type="VARCHAR2" size="32" />
+
+ <constraint name="JMS_ROLES_PKEY">
+ <primaryKey>
+ <field ref="USERID"/>
+ <field ref="ROLEID"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+ <table name="JMS_SUBSCRIPTIONS">
+ <column name="CLIENTID" required="true" type="VARCHAR2" size="128" />
+ <column name="SUBNAME" required="true" type="VARCHAR2" size="128" />
+ <column name="TOPIC" required="true" type="VARCHAR2" size="255" />
+ <column name="SELECTOR" required="false" type="VARCHAR2" size="255" />
+
+ <constraint name="JMS_SUBSCRIPTIONS_PKEY">
+ <primaryKey>
+ <field ref="CLIENTID"/>
+ <field ref="SUBNAME"/>
+ </primaryKey>
+ </constraint>
+ </table>
+
+<!-- END: jms-schema.xml -->
+<!-- BEGIN: alert-schema.xml -->
+
+
+ <table name="RHQ_ALERT_DEFINITION">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" required="true" size="100" type="VARCHAR2"/>
+ <column name="CTIME" type="LONG" required="true"/>
+ <column name="MTIME" type="LONG" required="true"/>
+ <column name="PARENT_ID" type="INTEGER" required="false"/>
+ <column name="GROUP_ALERT_DEF_ID" type="INTEGER" required="false"/>
+ <column name="DESCRIPTION" required="false" size="250" type="VARCHAR2"/>
+ <column name="PRIORITY" type="VARCHAR2" size="15" required="true"/>
+ <column name="RESOURCE_TYPE_ID" type="INTEGER" references="RHQ_RESOURCE_TYPE" required="false"/>
+ <column name="RESOURCE_ID" type="INTEGER" references="RHQ_RESOURCE" required="false"/>
+ <column name="RESOURCE_GROUP_ID" type="INTEGER" references="RHQ_RESOURCE_GROUP" required="false"/>
+ <column name="ENABLED" required="true" default="TRUE" type="BOOLEAN"/>
+
+ <column name="REQUIRED" required="true" type="SMALLINT"/>
+
+ <column name="RECOVERY_ID" type="INTEGER" required="true"/>
+ <!-- required, but 0 effectively means null -->
+ <column name="WILL_RECOVER" required="true" default="false" type="BOOLEAN"/>
+ <column name="NOTIFY_FILTERED" required="true" default="false" type="BOOLEAN"/>
+ <column name="CONTROL_FILTERED" required="true" default="FALSE" type="BOOLEAN"/>
+
+ <column name="DELETED" required="true" default="FALSE" type="BOOLEAN"/>
+ <column name="READ_ONLY" required="true" default="FALSE" type="BOOLEAN"/>
+
+ <column name="DAMPENING_CATEGORY" type="SMALLINT" required="true"/>
+ <column name="DAMPENING_VALUE" type="INTEGER"/>
+ <column name="DAMPENING_VALUE_UNITS" type="SMALLINT"/>
+ <column name="DAMPENING_PERIOD" type="INTEGER"/>
+ <column name="DAMPENING_PERIOD_UNITS" type="SMALLINT"/>
+
+ <column name="OPERATION_DEF_ID" type="INTEGER" references="RHQ_OPERATION_DEF(ID)"/>
+ </table>
+
+ <table name="RHQ_ALERT_DAMPEN_EVENT">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="ALERT_DEFINITION_ID" required="false" type="INTEGER" references="RHQ_ALERT_DEFINITION(ID)"/>
+ <column name="EVENT_TYPE" required="true" type="SMALLINT"/>
+ <column name="EVENT_TIMESTAMP" required="true" type="LONG"/>
+
+ <index name="RHQ_DAMPENING_EVENT_TYPE_IDX">
+ <field ref="EVENT_TYPE"/>
+ </index>
+ <index name="RHQ_DAMPENING_EVENT_TS_IDX">
+ <field ref="EVENT_TIMESTAMP"/>
+ </index>
+ </table>
+
+ <table name="RHQ_ALERT_CONDITION">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="TYPE" required="true" type="VARCHAR2" size="15"/>
+ <!--
+ <column name="REQUIRED" required="true" type="BOOLEAN"/>
+ -->
+ <column name="MEASUREMENT_DEFINITION_ID" required="false" type="INTEGER"/>
+ <column name="NAME" required="false" size="100" type="VARCHAR2"/>
+ <column name="COMPARATOR" required="false" size="2" type="VARCHAR2"/>
+ <column name="THRESHOLD" required="false" type="DOUBLE"/>
+ <!-- event-based conditions use OPTION_STATUS for the string match, so should be a decent length -->
+ <column name="OPTION_STATUS" required="false" size="256" type="VARCHAR2"/>
+ <column name="ALERT_DEFINITION_ID" required="false" type="INTEGER" references="RHQ_ALERT_DEFINITION(ID)"/>
+ <column name="TRIGGER_ID" required="false" type="INTEGER"/>
+ </table>
+
+ <table name="RHQ_ALERT" tablespace="DEFAULT"
+ storage-options="freelists 5" cache="true" logging="false">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="ALERT_DEFINITION_ID" required="false" type="INTEGER" references="RHQ_ALERT_DEFINITION(ID)"/>
+ <column name="CTIME" required="true" type="LONG"/>
+ <column name="TRIGGERED_OPERATION" required="false" type="VARCHAR2" size="255"/>
+ <column name="RECOVERY_ID" type="INTEGER" required="true"/>
+ <!-- required, but 0 effectively means null -->
+ <column name="WILL_RECOVER" required="true" default="false" type="BOOLEAN"/>
+ <index name="RHQ_ALERT_IDX_TIME" unique="false">
+ <field ref="CTIME"/>
+ </index>
+ <index name="RHQ_ALERT_IDX_ALERTDEF" unique="false">
+ <field ref="ALERT_DEFINITION_ID"/>
+ </index>
+ </table>
+
+ <table name="RHQ_ALERT_NOTIF_LOG" tablespace="DEFAULT"
+ storage-options="freelists 5" cache="true" logging="false">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="ALERT_ID" required="true" type="INTEGER" references="RHQ_ALERT(ID)"/>
+ <index name="RHQ_ALERT_IDX_ALERT" unique="true">
+ <field ref="ALERT_ID"/>
+ </index>
+ <column name="ROLES" required="false" size="200" type="VARCHAR2"/>
+ <column name="SUBJECTS" required="false" size="200" type="VARCHAR2"/>
+ <column name="EMAILS" required="false" size="200" type="VARCHAR2"/>
+ </table>
+
+ <table name="RHQ_ALERT_CONDITION_LOG" tablespace="DEFAULT"
+ storage-options="freelists 5" cache="true" logging="false">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="CTIME" required="true" type="LONG"/>
+ <column name="ALERT_ID" required="false" type="INTEGER" references="RHQ_ALERT(ID)"/>
+ <column name="CONDITION_ID" required="true" type="INTEGER" references="RHQ_ALERT_CONDITION(ID)"/>
+ <column name="VALUE" required="false" size="250" type="VARCHAR2"/>
+ <index name="RHQ_ALERT_COND_LOG_IDX_TIME">
+ <field ref="CTIME" />
+ </index>
+ <index name="RHQ_ALERT_COND_LOG_IDX_ALERT">
+ <field ref="ALERT_ID"/>
+ </index>
+ </table>
+
+ <table name="RHQ_ALERT_NOTIFICATION" tablespace="DEFAULT"
+ storage-options="freelists 5" cache="true" logging="false">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="NOTIFICATION_TYPE" required="true" size="20" type="VARCHAR2"/>
+ <column name="ALERT_DEFINITION_ID" required="false" type="INTEGER" references="RHQ_ALERT_DEFINITION(ID)"/>
+ <column name="ROLE_ID" type="INTEGER" references="RHQ_ROLE(ID)"/>
+ <column name="SUBJECT_ID" type="INTEGER" references="RHQ_SUBJECT(ID)"/>
+ <column name="EMAIL_ADDRESS" size="100" type="VARCHAR2"/>
+ <column name="SNMP_HOST" size="100" type="VARCHAR2"/>
+ <column name="SNMP_PORT" type="INTEGER"/>
+ <column name="SNMP_OID" size="250" type="VARCHAR2"/>
+ </table>
+
+<!-- END: alert-schema.xml -->
+<!-- BEGIN: event-schema.xml -->
+
+
+ <!-- metadata -->
+
+ <table name="RHQ_EVENT_DEF">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="RESOURCE_TYPE_ID" type="INTEGER" required="true" references="RHQ_RESOURCE_TYPE(ID)"/>
+
+ <column name="NAME" type="VARCHAR2" size="100" required="true"/>
+ <column name="DISPLAY_NAME" type="VARCHAR2" size="100"/>
+ <column name="DESCRIPTION" type="VARCHAR2" size="1000"/>
+
+ <index name="RHQ_EVENT_DEF_IDX" unique="true">
+ <field ref="RESOURCE_TYPE_ID"/>
+ <field ref="NAME"/>
+ </index>
+ </table>
+
+ <!-- instance data -->
+
+ <table name="RHQ_EVENT_SOURCE">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="EVENT_DEF_ID" type="INTEGER" required="true" references="RHQ_EVENT_DEF(ID)"/>
+ <column name="RESOURCE_ID" type="INTEGER" required="true" references="RHQ_RESOURCE(ID)"/>
+
+ <column name="LOCATION" required="true" size="2000" type="VARCHAR2"/>
+
+ <index name="RHQ_EVENT_SOURCE_IDX" unique="true">
+ <field ref="EVENT_DEF_ID"/>
+ <field ref="RESOURCE_ID"/>
+ <field ref="LOCATION"/>
+ </index>
+ </table>
+
+ <table name="RHQ_EVENT">
+ <column name="ID" default="sequence-only" initial="10001"
+ primarykey="true" required="true" type="INTEGER"/>
+ <column name="EVENT_SOURCE_ID" type="INTEGER" required="true" references="RHQ_EVENT_SOURCE(ID)"/>
+
+ <column name="TIMESTAMP" required="true" type="LONG"/>
+ <column name="SEVERITY" required="true" size="20" type="VARCHAR2"/>
+ <column name="DETAIL" required="true" size="4000" type="VARCHAR2"/>
+ <index name="RHQ_EVENT_IDX" unique="false">
+ <field ref="EVENT_SOURCE_ID"/>
+ <field ref="TIMESTAMP"/>
+ </index>
+ </table>
+
+<!-- END: event-schema.xml -->
+</dbsetup>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/util/test-ds.properties b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/util/test-ds.properties
new file mode 100644
index 0000000..448c69e
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/org/rhq/enterprise/server/util/test-ds.properties
@@ -0,0 +1,7 @@
+# The values of these properties get substituted by Maven during the test:resources phase.
+rhq.test.ds.driver-class = ${rhq.test.ds.driver-class}
+rhq.test.ds.connection-url = ${rhq.test.ds.connection-url}
+rhq.test.ds.server-name = ${rhq.test.ds.server-name}
+rhq.test.ds.db-name = ${rhq.test.ds.db-name}
+rhq.test.ds.user-name = ${rhq.test.ds.user-name}
+rhq.test.ds.password = ${rhq.test.ds.password}
diff --git a/modules/enterprise/server/itests-2/src/test/resources/perftest/AvailabilityInsertPurgeTest-testOne-data.xml.zip b/modules/enterprise/server/itests-2/src/test/resources/perftest/AvailabilityInsertPurgeTest-testOne-data.xml.zip
new file mode 100644
index 0000000..70bd0ce
Binary files /dev/null and b/modules/enterprise/server/itests-2/src/test/resources/perftest/AvailabilityInsertPurgeTest-testOne-data.xml.zip differ
diff --git a/modules/enterprise/server/itests-2/src/test/resources/persistence.jar b/modules/enterprise/server/itests-2/src/test/resources/persistence.jar
new file mode 100644
index 0000000..fe807c8
Binary files /dev/null and b/modules/enterprise/server/itests-2/src/test/resources/persistence.jar differ
diff --git a/modules/enterprise/server/itests-2/src/test/resources/persistence.xml b/modules/enterprise/server/itests-2/src/test/resources/persistence.xml
new file mode 100644
index 0000000..0785870
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/persistence.xml
@@ -0,0 +1,53 @@
+<!--
+ ~ RHQ Management Platform
+ ~ Copyright (C) 2005-2012 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.
+-->
+
+<persistence
+ version="2.0"
+ xmlns="http://java.sun.com/xml/ns/persistence"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/persistence
+ http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
+ <persistence-unit name="rhqpu">
+ <jta-data-source>java:jboss/datasources/RHQDS</jta-data-source>
+
+ <properties>
+ <!-- This allows us to lookup the EMF by name prior to when Arquillian injects it, which is currently only in the @Test,
+ and not the @BeforeMethod (1.0.1.Final) -->
+ <property
+ name="jboss.entity.manager.factory.jndi.name"
+ value="java:jboss/RHQEntityManagerFactory" />
+
+
+ <!--
+ <property name="hibernate.show_sql" value="true" />
+ <property name="hibernate.format_sql" value="true" />
+ <property name="hibernate.use_sql_comments" value="true" />
+ -->
+
+ <property
+ name="hibernate.jdbc.batch_size"
+ value="30" />
+ <property
+ name="hibernate.cache.use_second_level_cache"
+ value="false" />
+
+ </properties>
+ </persistence-unit>
+</persistence>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/rhq-mdb-beans.xml b/modules/enterprise/server/itests-2/src/test/resources/rhq-mdb-beans.xml
new file mode 100644
index 0000000..ad05b5e
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/rhq-mdb-beans.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
+ xmlns="urn:jboss:bean-deployer:2.0">
+
+ <bean name="jboss.mq.destination:service=Queue,name=AlertConditionQueue" class="org.jboss.mq.kernel.Queue">
+ <property name="destinationManagerPojo"><inject bean="jboss.mq:service=DestinationManager"/></property>
+ <property name="initialContextProperties"><inject bean="InitialContextProperties"/></property>
+ <property name="destinationName">AlertConditionQueue</property>
+ </bean>
+
+ <bean name="jboss.mq.destination:service=Queue,name=DriftChangesetQueue" class="org.jboss.mq.kernel.Queue">
+ <property name="destinationManagerPojo"><inject bean="jboss.mq:service=DestinationManager"/></property>
+ <property name="initialContextProperties"><inject bean="InitialContextProperties"/></property>
+ <property name="destinationName">DriftChangesetQueue</property>
+ </bean>
+
+ <bean name="jboss.mq.destination:service=Queue,name=DriftFileQueue" class="org.jboss.mq.kernel.Queue">
+ <property name="destinationManagerPojo"><inject bean="jboss.mq:service=DestinationManager"/></property>
+ <property name="initialContextProperties"><inject bean="InitialContextProperties"/></property>
+ <property name="destinationName">DriftFileQueue</property>
+ </bean>
+
+</deployment>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/security-beans.xml b/modules/enterprise/server/itests-2/src/test/resources/security-beans.xml
new file mode 100644
index 0000000..84fa819
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/security-beans.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:jboss:bean-deployer bean-deployer_1_0.xsd"
+ xmlns="urn:jboss:bean-deployer">
+
+ <bean class="org.jboss.ejb3.embedded.JaasSecurityManagerService"
+ name="jboss.security:service=JaasSecurityManager">
+ <property name="initialContextProperties">
+ <inject bean="InitialContextProperties"/>
+ </property>
+ </bean>
+</deployment>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/serverplugins/simple-generic-serverplugin.xml b/modules/enterprise/server/itests-2/src/test/resources/serverplugins/simple-generic-serverplugin.xml
new file mode 100644
index 0000000..5044d16
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/serverplugins/simple-generic-serverplugin.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<generic-plugin name="TestSimpleGenericPlugin"
+ displayName="Test Simple Generic Plugin"
+ description="A test generic plugin that is simple."
+ version="1.0"
+ apiVersion="2.0"
+ xmlns="urn:xmlns:rhq-serverplugin.generic"
+ xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <serverplugin:plugin-component class="org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener"></serverplugin:plugin-component>
+
+ <serverplugin:plugin-configuration>
+ <c:simple-property name="plugin-simple-prop-1" defaultValue="prop1value" required="true" />
+ </serverplugin:plugin-configuration>
+</generic-plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/single-line-rhql.txt b/modules/enterprise/server/itests-2/src/test/resources/single-line-rhql.txt
new file mode 100644
index 0000000..25746f8
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/single-line-rhql.txt
@@ -0,0 +1,91 @@
+
+# simple term, all operators
+context = value
+context == value
+context != value
+context !== value
+context = null
+context != null
+
+# simple term, all operators, quoted value
+context = 'quoted value'
+context == 'quoted value'
+context != 'quoted value'
+context !== 'quoted value'
+context = null
+context != null
+
+# parameterized term, all operators
+context[param] = value
+context[param] == value
+context[param] != value
+context[param] !== value
+context[param] = null
+context[param] != null
+
+# deeply nested parenthetical simple terms
+((context = value))
+(((context = value)))
+((((context = value))))
+(((((context = value)))))
+
+# simple parenthetical term, all operators
+(context = value)
+(context == value)
+(context != value)
+(context !== value)
+(context = null)
+(context != null)
+
+# parameterized parenthetical term, all operators
+(context[param] = value)
+(context[param] == value)
+(context[param] != value)
+(context[param] !== value)
+(context[param] = null)
+(context[param] != null)
+
+
+
+# single-pair parenthetical combinations
+# simple expression, '|' boolean operator (meaning 'or')
+context = value1 | context = value2
+(context = value1) | context = value2
+context = value1 | (context = value2)
+(context = value1) | (context = value2)
+
+
+# single-pair parenthetical combinations
+# simple expression, no boolean operator (implies 'and' semantics)
+context = value context = value
+(context = value) context = value
+context = value (context = value)
+(context = value) (context = value)
+
+
+
+# double-pair parenthetical combinations
+# simple expression, '|' boolean operator (meaning 'or')
+((context = value1 | context = value2))
+((context = value1) | context = value2)
+((context = value1)) | context = value2
+(context = value1) | (context = value2)
+(context = value1 | (context = value2))
+context = value1 | ((context = value2))
+
+# double-pair parenthetical combinations
+# simple expression, no boolean operator (implies 'and' semantics)
+((context = value1 context = value2))
+((context = value1) context = value2)
+((context = value1)) context = value2
+(context = value1) (context = value2)
+(context = value1 (context = value2))
+context = value1 ((context = value2))
+
+# simple terms
+hello
+hello world
+"hello world" 'foo bar'
+'hello world' "foo bar"
+hello | world
+context=value | world
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test-assist-color-number.txt b/modules/enterprise/server/itests-2/src/test/resources/test-assist-color-number.txt
new file mode 100644
index 0000000..6ad90cc
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test-assist-color-number.txt
@@ -0,0 +1,46 @@
+
+color[ number
+c
+color[
+n
+number
+r
+color[ number
+lo
+color[
+number
+number!= number!== number= number==
+be
+number
+number==
+number=="two" number=="four" number=="twenty-two" number=="twenty-four" number=="forty-two"
+number==t
+number=="two" number=="twenty-two" number=="twenty-four" number=="forty-two"
+number==fo
+number=="four" number=="twenty-four" number=="forty-two"
+color
+color[
+color[
+color[primary] color[other]
+color[p
+color[primary]
+color[o
+color[other]
+color[r
+color[primary] color[other]
+color[primary
+color[primary]
+color[primary]
+color[primary]!= color[primary]!== color[primary]= color[primary]==
+color[primary]=
+color[primary]="red" color[primary]="green" color[primary]="blue"
+color[primary]=e
+color[primary]="red" color[primary]="green" color[primary]="blue"
+color[primary]=d
+color[primary]="red"
+color[primary]=g
+color[primary]="green"
+color[primary]=b
+color[primary]="blue"
+color[primary]=r
+color[primary]="red" color[primary]="green"
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test-ldap.properties b/modules/enterprise/server/itests-2/src/test/resources/test-ldap.properties
new file mode 100644
index 0000000..3316083
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test-ldap.properties
@@ -0,0 +1,2 @@
+rhq.test.ldap.url=${rhq.test.ldap.url}
+rhq.test.ldap.LDAPFactory=${rhq.test.ldap.LDAPFactory}
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test-scheduler.properties b/modules/enterprise/server/itests-2/src/test/resources/test-scheduler.properties
new file mode 100644
index 0000000..2ecec78
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test-scheduler.properties
@@ -0,0 +1,29 @@
+# QUARTZ CONFIGURATION FOR OUR UNIT TESTS
+# our test timeout will be fast, 5 seconds
+rhq.server.operation-timeout = 5
+
+# scheduler factory config
+org.quartz.scheduler.instanceName = RHQScheduler
+org.quartz.scheduler.instanceId = AUTO
+
+# thread pool config
+org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
+org.quartz.threadPool.threadCount = 25
+org.quartz.threadPool.threadPriority = 5
+
+# database config - note the use of POSTGRES for tests
+org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreCMT
+org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
+# tests don't need this
+org.quartz.jobStore.isClustered = false
+org.quartz.jobStore.clusterCheckinInterval = 600000
+# make this a small non-zero time (in ms) so the scheduler (almost) never sleeps for more predictable test timing
+org.quartz.scheduler.idleWaitTime = 10
+org.quartz.jobStore.tablePrefix = RHQ_QRTZ_
+org.quartz.jobStore.useProperties = true
+org.quartz.jobStore.dataSource = RHQDS
+org.quartz.dataSource.RHQDS.jndiURL = java:jboss/datasources/RHQDS
+org.quartz.dataSource.RHQDS.maxConnections = 10
+org.quartz.jobStore.nonManagedTXDataSource = NoTxRHQDS
+org.quartz.dataSource.NoTxRHQDS.jndiURL = java:jboss/datasources/NoTxRHQDS
+org.quartz.dataSource.NoTxRHQDS.maxConnections = 10
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/all_no_tx_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/all_no_tx_ds.xml
new file mode 100644
index 0000000..34a3977
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/all_no_tx_ds.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<datasources>
+ <no-tx-datasource>
+ <jndi-name>jndiName</jndi-name>
+ <use-java-context/>
+ <connection-url>jdbc:hsqldb:hsql://localhost:1701</connection-url>
+
+ <!-- The driver class -->
+ <driver-class>org.hsqldb.jdbcDriver</driver-class>
+
+ <!-- The login and password -->
+ <user-name>sa</user-name>
+ <password>bob</password>
+
+ <!--example of how to specify class that determines if exception means connection should be destroyed-->
+ <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.DummyExceptionSorter</exception-sorter-class-name>
+
+
+ <application-managed-security/>
+ <security-domain>domain</security-domain>
+ <security-domain-and-application>domain2</security-domain-and-application>
+
+ <!-- this will be run before a managed connection is removed from the pool for use by a client-->
+ <check-valid-connection-sql>select * from something</check-valid-connection-sql>
+
+ <!-- The minimum connections in a pool/sub-pool. Pools are lazily constructed on first use -->
+ <min-pool-size>5</min-pool-size>
+
+ <!-- The maximum connections in a pool/sub-pool -->
+ <max-pool-size>20</max-pool-size>
+
+ <connection-property name="test">testvalue</connection-property>
+ <connection-property name="test2">testvalue2</connection-property>
+
+ <!-- The time before an unused connection is destroyed -->
+ <!-- NOTE: This is the check period. It will be destroyed somewhere between 1x and 2x this timeout after last use -->
+ <!-- TEMPORARY FIX! - Disable idle connection removal, HSQLDB has a problem with not reaping threads on closed connections -->
+ <idle-timeout-minutes>0</idle-timeout-minutes>
+
+ <!-- sql to call when connection is created -->
+ <new-connection-sql>some arbitrary sql</new-connection-sql>
+
+ <blocking-timeout-millis>5000</blocking-timeout-millis>
+ <!-- sql to call on an existing pooled connection when it is obtained from pool -->
+ <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
+ -->
+
+ <!-- example of how to specify a class that determines a connection is valid before it is handed out from the pool-->
+ <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.DummyValidConnectionChecker</valid-connection-checker-class-name>
+
+
+ <!-- Whether to check all statements are closed when the connection is returned to the pool,
+ this is a debugging feature that should be turned off in production -->
+ <track-statements/>
+
+ <prepared-statement-cache-size>15</prepared-statement-cache-size>
+
+ <!-- Use the getConnection(user, pw) for logins
+ <application-managed-security/>
+ -->
+
+ <!-- Use the security domain defined in conf/login-config.xml
+ <security-domain>HsqlDbRealm</security-domain>
+ -->
+
+ <!-- Use the security domain defined in conf/login-config.xml or the
+ getConnection(user, pw) for logins. The security domain takes precedence.
+ <security-domain-and-application>HsqlDbRealm</security-domain-and-application>
+ -->
+
+ <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+ <metadata>
+ <type-mapping>Hypersonic SQL</type-mapping>
+ </metadata>
+
+ <!-- This mbean can be used when using in process persistent hypersonic -->
+ <depends>jboss:service=Hypersonic,database=localDB</depends>
+ </no-tx-datasource>
+
+ <mbean code="org.jboss.jdbc.HypersonicDatabase"
+ name="jboss:service=Hypersonic">
+ <attribute name="Port">1701</attribute>
+ <attribute name="Silent">true</attribute>
+ <attribute name="Database">default</attribute>
+ <attribute name="Trace">false</attribute>
+ <attribute name="No_system_exit">true</attribute>
+ </mbean>
+
+
+
+ <mbean code="org.jboss.jdbc.HypersonicDatabase"
+ name="jboss:service=Hypersonic,database=localDB">
+ <attribute name="Database">localDB</attribute>
+ <attribute name="InProcessMode">true</attribute>
+ </mbean>
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/app_auth_type_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/app_auth_type_ds.xml
new file mode 100644
index 0000000..d9fa3f0
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/app_auth_type_ds.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<datasources>
+ <no-tx-datasource>
+ <jndi-name>jndiName</jndi-name>
+ <application-managed-security/>
+ <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+ <metadata>
+ <type-mapping>Hypersonic SQL</type-mapping>
+ </metadata>
+
+ <!-- This mbean can be used when using in process persistent hypersonic -->
+ <depends>jboss:service=Hypersonic,database=localDB</depends>
+ </no-tx-datasource>
+
+ <mbean code="org.jboss.jdbc.HypersonicDatabase"
+ name="jboss:service=Hypersonic">
+ <attribute name="Port">1701</attribute>
+ <attribute name="Silent">true</attribute>
+ <attribute name="Database">default</attribute>
+ <attribute name="Trace">false</attribute>
+ <attribute name="No_system_exit">true</attribute>
+ </mbean>
+
+
+
+ <mbean code="org.jboss.jdbc.HypersonicDatabase"
+ name="jboss:service=Hypersonic,database=localDB">
+ <attribute name="Database">localDB</attribute>
+ <attribute name="InProcessMode">true</attribute>
+ </mbean>
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/bad.xsl b/modules/enterprise/server/itests-2/src/test/resources/test/bad.xsl
new file mode 100644
index 0000000..2aac602
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/bad.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+can't have this here
+
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/container_and_app_auth_type_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/container_and_app_auth_type_ds.xml
new file mode 100644
index 0000000..b85e14c
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/container_and_app_auth_type_ds.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<datasources>
+ <no-tx-datasource>
+ <jndi-name>jndiName</jndi-name>
+ <security-domain-and-application>domain2</security-domain-and-application>
+ <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+ <metadata>
+ <type-mapping>Hypersonic SQL</type-mapping>
+ </metadata>
+
+ <!-- This mbean can be used when using in process persistent hypersonic -->
+ <depends>jboss:service=Hypersonic,database=localDB</depends>
+ </no-tx-datasource>
+
+ <mbean code="org.jboss.jdbc.HypersonicDatabase"
+ name="jboss:service=Hypersonic">
+ <attribute name="Port">1701</attribute>
+ <attribute name="Silent">true</attribute>
+ <attribute name="Database">default</attribute>
+ <attribute name="Trace">false</attribute>
+ <attribute name="No_system_exit">true</attribute>
+ </mbean>
+
+
+
+ <mbean code="org.jboss.jdbc.HypersonicDatabase"
+ name="jboss:service=Hypersonic,database=localDB">
+ <attribute name="Database">localDB</attribute>
+ <attribute name="InProcessMode">true</attribute>
+ </mbean>
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/container_auth_type_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/container_auth_type_ds.xml
new file mode 100644
index 0000000..a16b7d0
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/container_auth_type_ds.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<datasources>
+ <no-tx-datasource>
+ <jndi-name>jndiName</jndi-name>
+ <security-domain>domain</security-domain>
+ <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+ <metadata>
+ <type-mapping>Hypersonic SQL</type-mapping>
+ </metadata>
+
+ <!-- This mbean can be used when using in process persistent hypersonic -->
+ <depends>jboss:service=Hypersonic,database=localDB</depends>
+ </no-tx-datasource>
+
+ <mbean code="org.jboss.jdbc.HypersonicDatabase"
+ name="jboss:service=Hypersonic">
+ <attribute name="Port">1701</attribute>
+ <attribute name="Silent">true</attribute>
+ <attribute name="Database">default</attribute>
+ <attribute name="Trace">false</attribute>
+ <attribute name="No_system_exit">true</attribute>
+ </mbean>
+
+
+
+ <mbean code="org.jboss.jdbc.HypersonicDatabase"
+ name="jboss:service=Hypersonic,database=localDB">
+ <attribute name="Database">localDB</attribute>
+ <attribute name="InProcessMode">true</attribute>
+ </mbean>
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.0-feb-2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.0-feb-2.xml
new file mode 100644
index 0000000..be13c82
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.0-feb-2.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- 1.0-feb.xml -->
+<plugin version="1.0" name="DeployTest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:xmlns:rhq-plugin"/>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.0-feb.xml b/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.0-feb.xml
new file mode 100644
index 0000000..be13c82
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.0-feb.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- 1.0-feb.xml -->
+<plugin version="1.0" name="DeployTest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:xmlns:rhq-plugin"/>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.0-june.xml b/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.0-june.xml
new file mode 100644
index 0000000..8c383ef
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.0-june.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- 1.0-june.xml -->
+<plugin version="1.0" name="DeployTest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:xmlns:rhq-plugin"/>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.1-feb.xml b/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.1-feb.xml
new file mode 100644
index 0000000..d81c493
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.1-feb.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- 1.1-feb.xml -->
+<plugin version="1.1" name="DeployTest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:xmlns:rhq-plugin"/>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.1-june.xml b/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.1-june.xml
new file mode 100644
index 0000000..4195af9
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/deployment/1.1-june.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- 1.1-june.xml -->
+<plugin version="1.1" name="DeployTest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:xmlns:rhq-plugin"/>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/generic_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/generic_ds.xml
new file mode 100644
index 0000000..b6dd079
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/generic_ds.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- Generic datasource configuration showing all possibilities -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<!-- $Id: generic_ds.xml 695 2005-09-17 00:43:05Z ccrouch $ -->
+
+
+<datasources>
+ <local-tx-datasource>
+ <jndi-name>GenericDS</jndi-name>
+ <connection-url>[jdbc: url for use with Driver class]</connection-url>
+ <driver-class>[fully qualified class name of java.sql.Driver implementation]</driver-class>
+ <user-name>x</user-name>
+ <password>y</password>
+ <!-- you can include connection properties that will get passed in
+ the DriverManager.getConnection(props) call-->
+ <!-- look at your Driver docs to see what these might be -->
+ <connection-property name="char.encoding">UTF-8</connection-property>
+ <transaction-isolation>TRANSACTION_SERIALIZABLE</transaction-isolation>
+
+ <!--pooling parameters-->
+ <min-pool-size>5</min-pool-size>
+ <max-pool-size>100</max-pool-size>
+ <blocking-timeout-millis>5000</blocking-timeout-millis>
+ <idle-timeout-minutes>15</idle-timeout-minutes>
+ <!-- sql to call when connection is created -->
+ <new-connection-sql>select * from user where name=$</new-connection-sql>
+
+
+ <!-- sql to call on an existing pooled connection when it is obtained from pool -->
+ <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
+
+
+
+ <!-- pooling criteria. USE AT MOST ONE-->
+ <!-- If you don't use JAAS login modules or explicit login
+ getConnection(usr,pw) but rely on user/pw specified above,
+ don't specify anything here -->
+
+ <!-- If you supply the usr/pw from a JAAS login module
+ <security-domain>MyRealm</security-domain>
+-->
+
+ <!-- if your app supplies the usr/pw explicitly getConnection(usr, pw) -->
+ <application-managed-security/>
+
+ <!--Anonymous depends elements are copied verbatim into the ConnectionManager mbean config-->
+ <depends>myapp.service:service=DoSomethingService</depends>
+
+ </local-tx-datasource>
+
+ <!-- you can include regular mbean configurations like this one -->
+ <mbean code="org.jboss.tm.XidFactory"
+ name="jboss:service=XidFactory">
+ <attribute name="Pad">true</attribute>
+ </mbean>
+
+
+
+
+
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/hsqldb_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/hsqldb_ds.xml
new file mode 100644
index 0000000..d96a740
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/hsqldb_ds.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- The Hypersonic embedded database JCA connection factory config
+$Id: hsqldb_ds.xml 695 2005-09-17 00:43:05Z ccrouch $ -->
+
+
+<datasources>
+ <local-tx-datasource>
+
+ <!-- The jndi name of the DataSource, it is prefixed with java:/ -->
+ <!-- Datasources are not available outside the virtual machine -->
+ <jndi-name>DefaultDS</jndi-name>
+ <use-java-context/>
+ <!-- for tcp connection, allowing other processes to use the hsqldb
+ database. This requires the org.jboss.jdbc.HypersonicDatabase mbean.
+ <connection-url>jdbc:hsqldb:hsql://localhost:1701</connection-url>
+-->
+ <!-- for totally in-memory db, not saved when jboss stops.
+ The org.jboss.jdbc.HypersonicDatabase mbean necessary
+ <connection-url>jdbc:hsqldb:.</connection-url>
+-->
+ <!-- for in-process persistent db, saved when jboss stops. The
+ org.jboss.jdbc.HypersonicDatabase mbean is necessary for properly db shutdown
+-->
+ <connection-url>jdbc:hsqldb:${jboss.server.data.dir}${/}hypersonic${/}localDB</connection-url>
+
+ <!-- The driver class -->
+ <driver-class>org.hsqldb.jdbcDriver</driver-class>
+
+ <!-- The login and password -->
+ <user-name>sa</user-name>
+ <password></password>
+
+ <!--example of how to specify class that determines if exception means connection should be destroyed-->
+ <!--exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.DummyExceptionSorter</exception-sorter-class-name-->
+
+ <!-- this will be run before a managed connection is removed from the pool for use by a client-->
+ <!--<check-valid-connection-sql>select * from something</check-valid-connection-sql> -->
+
+ <!-- The minimum connections in a pool/sub-pool. Pools are lazily constructed on first use -->
+ <min-pool-size>5</min-pool-size>
+
+ <!-- The maximum connections in a pool/sub-pool -->
+ <max-pool-size>20</max-pool-size>
+
+ <!-- The time before an unused connection is destroyed -->
+ <!-- NOTE: This is the check period. It will be destroyed somewhere between 1x and 2x this timeout after last use -->
+ <!-- TEMPORARY FIX! - Disable idle connection removal, HSQLDB has a problem with not reaping threads on closed connections -->
+ <idle-timeout-minutes>0</idle-timeout-minutes>
+
+ <!-- sql to call when connection is created
+ <new-connection-sql>some arbitrary sql</new-connection-sql>
+ -->
+
+ <!-- sql to call on an existing pooled connection when it is obtained from pool
+ <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
+ -->
+
+ <!-- example of how to specify a class that determines a connection is valid before it is handed out from the pool
+ <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.DummyValidConnectionChecker</valid-connection-checker-class-name>
+ -->
+
+ <!-- Whether to check all statements are closed when the connection is returned to the pool,
+ this is a debugging feature that should be turned off in production -->
+ <track-statements/>
+
+ <!-- Use the getConnection(user, pw) for logins
+ <application-managed-security/>
+ -->
+
+ <!-- Use the security domain defined in conf/login-config.xml -->
+ <security-domain>HsqlDbRealm</security-domain>
+
+ <!-- Use the security domain defined in conf/login-config.xml or the
+ getConnection(user, pw) for logins. The security domain takes precedence.
+ <security-domain-and-application>HsqlDbRealm</security-domain-and-application>
+ -->
+
+ <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+ <metadata>
+ <type-mapping>Hypersonic SQL</type-mapping>
+ </metadata>
+
+ <!-- This mbean can be used when using in process persistent hypersonic -->
+ <depends>jboss:service=Hypersonic,database=localDB</depends>
+ </local-tx-datasource>
+
+ <!-- This mbean should be used only when using tcp connections. Uncomment
+ when the tcp based connection-url is used.
+ <mbean code="org.jboss.jdbc.HypersonicDatabase"
+ name="jboss:service=Hypersonic">
+ <attribute name="Port">1701</attribute>
+ <attribute name="Silent">true</attribute>
+ <attribute name="Database">default</attribute>
+ <attribute name="Trace">false</attribute>
+ <attribute name="No_system_exit">true</attribute>
+ </mbean>
+ -->
+
+ <!-- This mbean can be used when using in process persistent db -->
+ <mbean code="org.jboss.jdbc.HypersonicDatabase"
+ name="jboss:service=Hypersonic,database=localDB">
+ <attribute name="Database">localDB</attribute>
+ <attribute name="InProcessMode">true</attribute>
+ </mbean>
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/hsqldb_encrypted_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/hsqldb_encrypted_ds.xml
new file mode 100644
index 0000000..9a2e38d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/hsqldb_encrypted_ds.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- The Hypersonic embedded database JCA connection factory config
+that illustrates the use of the JaasSecurityDomainIdentityLoginModule
+to use encrypted password in the data source configuration.
+
+$Id: hsqldb_encrypted_ds.xml 695 2005-09-17 00:43:05Z ccrouch $ -->
+
+
+<datasources>
+ <local-tx-datasource>
+
+ <!-- The jndi name of the DataSource, it is prefixed with java:/ -->
+ <!-- Datasources are not available outside the virtual machine -->
+ <jndi-name>DefaultDS</jndi-name>
+
+ <!-- for tcp connection, allowing other processes to use the hsqldb
+ database. This requires the org.jboss.jdbc.HypersonicDatabase mbean.
+ <connection-url>jdbc:hsqldb:hsql://localhost:1701</connection-url>
+ -->
+ <!-- for totally in-memory db, not saved when jboss stops.
+ The org.jboss.jdbc.HypersonicDatabase mbean necessary
+ <connection-url>jdbc:hsqldb:.</connection-url>
+ -->
+ <!-- for in-process persistent db, saved when jboss stops. The
+ org.jboss.jdbc.HypersonicDatabase mbean is necessary for properly db shutdown
+ -->
+ <connection-url>jdbc:hsqldb:${jboss.server.data.dir}${/}hypersonic${/}localDB</connection-url>
+
+ <!-- The driver class -->
+ <driver-class>org.hsqldb.jdbcDriver</driver-class>
+
+ <!--example of how to specify class that determines if exception means connection should be destroyed-->
+ <!--exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.DummyExceptionSorter</exception-sorter-class-name-->
+
+ <!-- this will be run before a managed connection is removed from the pool for use by a client-->
+ <!--<check-valid-connection-sql>select * from something</check-valid-connection-sql> -->
+
+ <!-- The minimum connections in a pool/sub-pool. Pools are lazily constructed on first use -->
+ <min-pool-size>5</min-pool-size>
+
+ <!-- The maximum connections in a pool/sub-pool -->
+ <max-pool-size>20</max-pool-size>
+
+ <!-- The time before an unused connection is destroyed -->
+ <!-- NOTE: This is the check period. It will be destroyed somewhere between 1x and 2x this timeout after last use -->
+ <!-- TEMPORARY FIX! - Disable idle connection removal, HSQLDB has a problem with not reaping threads on closed connections -->
+ <idle-timeout-minutes>0</idle-timeout-minutes>
+
+ <!-- sql to call when connection is created
+ <new-connection-sql>some arbitrary sql</new-connection-sql>
+ -->
+
+ <!-- sql to call on an existing pooled connection when it is obtained from pool
+ <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
+ -->
+
+ <!-- example of how to specify a class that determines a connection is valid before it is handed out from the pool -->
+ <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.DummyValidConnectionChecker</valid-connection-checker-class-name>
+
+
+ <!-- Whether to check all statements are closed when the connection is returned to the pool,
+ this is a debugging feature that should be turned off in production -->
+ <track-statements/>
+
+ <!-- Use the getConnection(user, pw) for logins
+ <application-managed-security/>
+ -->
+
+ <!-- Use the security domain defined in conf/login-config.xml -->
+ <security-domain>EncryptedHsqlDbRealm</security-domain>
+
+ <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+ <metadata>
+ <type-mapping>Hypersonic SQL</type-mapping>
+ </metadata>
+
+ <!-- This mbean can be used when using in process persistent hypersonic -->
+ <depends>jboss:service=Hypersonic,database=localDB</depends>
+ </local-tx-datasource>
+
+ <!-- The JaasSecurityDomain used for encryption. Use the name
+ "jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword"
+ as the value of the JaasSecurityDomainIdentityLoginModule
+ jaasSecurityDomain login module option in the EncryptedHsqlDbRealm
+ login-config.xml section. Typically this service config should be in
+ the conf/jboss-service.xml descriptor.
+ The opaque master.password file could be created using:
+ java -cp jbosssx.jar org.jboss.security.plugins.FilePassword 12345678 17 master server.password
+
+ The corresponding login-config.xml would look like:
+ <application-policy name = "EncryptedHsqlDbRealm">
+ <authentication>
+ <login-module code = "org.jboss.resource.security.JaasSecurityDomainIdentityLoginModule"
+ flag = "required">
+ <module-option name = "username">sa</module-option>
+ <module-option name = "password">E5gtGMKcXPP</module-option>
+ <module-option name = "managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=DefaultDS</module-option>
+ <module-option name = "jaasSecurityDomain">jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword</module-option>
+ </login-module>
+ </authentication>
+ </application-policy>
+ where the encrypted password was generated using:
+ java -cp jbosssx.jar org.jboss.security.plugins.PBEUtils abcdefgh 13 master ''
+ Encoded password: E5gtGMKcXPP
+ -->
+ <mbean code="org.jboss.security.plugins.JaasSecurityDomain"
+ name="jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword">
+ <constructor>
+ <arg type="java.lang.String" value="ServerMasterPassword"/>
+ </constructor>
+ <!-- The opaque master password file used to decrypt the encrypted
+ database password key -->
+ <attribute name="KeyStorePass">{CLASS}org.jboss.security.plugins.FilePassword:${jboss.server.home.dir}/conf/server.password</attribute>
+ <attribute name="Salt">abcdefgh</attribute>
+ <attribute name="IterationCount">13</attribute>
+ </mbean>
+
+ <!-- This mbean can be used when using in process persistent db -->
+ <mbean code="org.jboss.jdbc.HypersonicDatabase"
+ name="jboss:service=Hypersonic,database=localDB">
+ <attribute name="Database">localDB</attribute>
+ <attribute name="InProcessMode">true</attribute>
+ </mbean>
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/informix_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/informix_ds.xml
new file mode 100644
index 0000000..95e314a
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/informix_ds.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- JBoss Server Configuration -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<!-- $Id: informix_ds.xml 954 2005-11-02 21:56:42Z ccrouch $ -->
+
+
+<datasources>
+ <local-tx-datasource>
+ <jndi-name>InformixDS</jndi-name>
+ <use-java-context>true</use-java-context>
+ <connection-url>jdbc:informix-sqli://myhost.mydomain.com:1557/mydb:INFORMIXSERVER=myserver</connection-url>
+ <driver-class>com.informix.jdbc.IfxDriver</driver-class>
+ <user-name>x</user-name>
+ <password>y</password>
+ <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.InformixExceptionSorter</exception-sorter-class-name>
+ <!-- sql to call when connection is created
+ <new-connection-sql>some arbitrary sql</new-connection-sql>
+ -->
+ <!-- sql to call on an existing pooled connection when it is obtained from pool
+ <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
+ -->
+ <transaction-isolation/>
+
+ <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+ <metadata>
+ <type-mapping>InformixDB</type-mapping>
+ </metadata>
+ </local-tx-datasource>
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/alerts/type-with-metric.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/alerts/type-with-metric.xml
new file mode 100644
index 0000000..1af82a9
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/alerts/type-with-metric.xml
@@ -0,0 +1,14 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Type with Metric Test Plugin" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <platform name="TypeWithMetrics">
+ <metric property="testMetric"
+ displayName="testMetric"
+ dataType="measurement"
+ measurementType="dynamic">
+ </metric>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/BZ_573034_v1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/BZ_573034_v1.xml
new file mode 100644
index 0000000..85de1cf
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/BZ_573034_v1.xml
@@ -0,0 +1,12 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Bug 573034 Test Plugin" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="TestServer">
+ <plugin-configuration>
+ <c:simple-property name="testProperty" required="true" default="default"/>
+ </plugin-configuration>
+ </server>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/BZ_573034_v2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/BZ_573034_v2.xml
new file mode 100644
index 0000000..15b8d74
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/BZ_573034_v2.xml
@@ -0,0 +1,12 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Bug 573034 Test Plugin" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <server name="TestServer">
+ <plugin-configuration>
+ <c:simple-property name="testProperty"/>
+ <c:simple-property name="testPropertyWithDefault" required="true" default="default"/>
+ </plugin-configuration>
+ </server>
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/addDeleteTemplate1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/addDeleteTemplate1.xml
new file mode 100644
index 0000000..bea3eef
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/addDeleteTemplate1.xml
@@ -0,0 +1,14 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform7">
+
+ <resource-configuration>
+ <c:simple-property name="hello" default="world"/>
+ </resource-configuration>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/addDeleteTemplate2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/addDeleteTemplate2.xml
new file mode 100644
index 0000000..47653a7
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/addDeleteTemplate2.xml
@@ -0,0 +1,17 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform7">
+
+ <resource-configuration>
+ <c:simple-property name="hello" default="world"/>
+ <c:template name="additional" description="An additional template to be persisted etc.">
+ <c:simple-property name="second_one" default="Bart"/>
+ </c:template>
+ </resource-configuration>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/addDeleteTemplate3.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/addDeleteTemplate3.xml
new file mode 100644
index 0000000..e57a2ab
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/addDeleteTemplate3.xml
@@ -0,0 +1,17 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="3.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform7">
+
+ <resource-configuration>
+ <c:simple-property name="hello" default="world"/>
+ <c:template name="additional" description="An additional template to be persisted etc.">
+ <c:simple-property name="second_one" default="Bart Simpson"/>
+ </c:template>
+ </resource-configuration>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/constraint.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/constraint.xml
new file mode 100644
index 0000000..9c6cbe3
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/constraint.xml
@@ -0,0 +1,24 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="constraintPlatform">
+ <resource-configuration>
+ <c:simple-property name="secureJnpPort"
+ type="integer"
+ defaultValue="1234"
+ displayName="Port to access JMX over ssl" >
+ <c:constraint>
+ <c:integer-constraint minimum="0"/>
+ </c:constraint>
+ <c:constraint>
+ <c:integer-constraint maximum="5"/>
+ <c:float-constraint minimum="3.0"/>
+ <c:regex-constraint expression="foo"/>
+ </c:constraint>
+ </c:simple-property>
+ </resource-configuration>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/constraintMinMax.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/constraintMinMax.xml
new file mode 100644
index 0000000..2653ee3
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/constraintMinMax.xml
@@ -0,0 +1,17 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="constraintPlatform">
+ <resource-configuration>
+ <c:simple-property name="secureJnpPort" type="integer">
+ <c:constraint>
+ <c:integer-constraint minimum="5" maximum="0"/>
+ <c:float-constraint minimum="5" maximum="0"/>
+ </c:constraint>
+ </c:simple-property>
+ </resource-configuration>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupDeleted-v1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupDeleted-v1.xml
new file mode 100644
index 0000000..4e3ef1d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupDeleted-v1.xml
@@ -0,0 +1,28 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="groupDeletedPlatform">
+ <resource-configuration>
+ <c:simple-property name="foobar" type="longString" description="blah blah blah"/>
+ <c:group name="advanced" displayName="Advanced">
+ <c:simple-property name="security-domain-and-application"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Security Domain"
+ required="false">
+ <c:description>Indicates Subjects from security domain are used to distinguish connections in
+ this pool.
+ </c:description>
+ <c:defaultValueDescription>If nothing is specified, the default will be to use a single pool of
+ equivalent connections.
+ </c:defaultValueDescription>
+ </c:simple-property>
+ </c:group>
+ </resource-configuration>
+ </platform>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupDeleted-v2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupDeleted-v2.xml
new file mode 100644
index 0000000..755ee5c
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupDeleted-v2.xml
@@ -0,0 +1,14 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="groupDeletedPlatform">
+ <resource-configuration>
+ <c:simple-property name="foobar" type="longString" description="blah blah blah"/>
+ </resource-configuration>
+ </platform>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v1.xml
new file mode 100644
index 0000000..b5daf46
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v1.xml
@@ -0,0 +1,27 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="groupPropDeletedPlatform">
+ <resource-configuration>
+ <c:group name="advanced" displayName="Advanced">
+ <c:simple-property name="security-domain-and-application"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Security Domain"
+ required="false">
+ <c:description>Indicates Subjects from security domain are used to distinguish connections in
+ this pool.
+ </c:description>
+ <c:defaultValueDescription>If nothing is specified, the default will be to use a single pool of
+ equivalent connections.
+ </c:defaultValueDescription>
+ </c:simple-property>
+ </c:group>
+ </resource-configuration>
+ </platform>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v2.xml
new file mode 100644
index 0000000..3c16420
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v2.xml
@@ -0,0 +1,28 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="groupPropDeletedPlatform">
+ <resource-configuration>
+ <c:group name="advanced" displayName="Advanced">
+ <c:simple-property name="application-managed-security"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="Application Managed Security"
+ required="false">
+ <c:description>Specifying this element indicates that connections in the pool should be
+ distinguished
+ by application code supplied parameters, such as from getConnection(user, pw). This requires
+ that you set a security domain which will populate a security-domain-and-application tag. If it
+ is missing
+ this resource will not be created or saved.
+ </c:description>
+ </c:simple-property>
+ </c:group>
+ </resource-configuration>
+ </platform>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v3.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v3.xml
new file mode 100644
index 0000000..4360c2b
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v3.xml
@@ -0,0 +1,315 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="3"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="groupDeletedPlatform">
+ <resource-configuration>
+ <c:simple-property name="foobar" type="longString" description="blah blah blah"/>
+ <c:group name="advanced" displayName="Advanced">
+
+ <c:simple-property name="security-domain-and-application"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Security Domain"
+ required="false">
+ <c:description>Indicates Subjects from security domain are used to distinguish connections in
+ this pool.
+ </c:description>
+ <c:defaultValueDescription>If nothing is specified, the default will be to use a single pool of
+ equivalent connections.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="adapter-display-name"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Adapter Display Name"
+ required="false">
+ <c:description>
+ Adaper Display Name
+ </c:description>
+ </c:simple-property>
+
+ <c:simple-property name="depends"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Depends"
+ description="Any MBeans that this factory has a dependency with."
+ required="false"/>
+
+ <c:simple-property name="rar-name"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Rar Name"
+ description="Rar Name"
+ required="false"/>
+
+ <c:simple-property name="connection-definition"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Connection Definition"
+ description="Connection Definition"
+ required="false"/>
+
+ <c:simple-property name="jmx-invoker-name"
+ type="string"
+ activationPolicy="immediate"
+ displayName="JMX Invoker Name"
+ description="Name of the JMX Invoker"
+ required="false"/>
+
+ <c:simple-property name="statistics-formatter"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Statistics Formatter"
+ description="Class to format Statistics"
+ required="false"/>
+
+ <!-- TODO Figure out the correct usage in connection factories I think it is more complex than just a string
+ <c:simple-property name="type-mapping"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Type Mappings"
+ required="false"/>-->
+
+ <c:simple-property name="use-java-context"
+ displayName="Use Java Context"
+ description="Indicates if the JNDI name should be prefixed with java:."
+ type="boolean"
+ required="false">
+ <c:property-options>
+ <c:option name="True" value="true"/>
+ <c:option name="False" value="false"/>
+ </c:property-options>
+ <c:defaultValueDescription>If nothing is specified, the default of true will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="local-transaction"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="Local Transaction"
+ required="false">
+ <c:description>Whether on not to use local transactions.</c:description>
+ <c:property-options>
+ <c:option name="True" value="true"/>
+ <c:option name="False" value="false"/>
+ </c:property-options>
+ <c:defaultValueDescription>If nothing is specified, the default of false will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="xa-transaction"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="XA Transaction"
+ required="false">
+ <c:description>Whether on not to use XA transactions.</c:description>
+ <c:property-options>
+ <c:option name="True" value="true"/>
+ <c:option name="False" value="false"/>
+ </c:property-options>
+ <c:defaultValueDescription>If nothing is specified, the default of false will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="no-tx-separate-pools"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="No Tx Separate Pools"
+ required="false">
+ <c:description>Whether or not to use separate pools.</c:description>
+ <c:property-options>
+ <c:option name="True" value="true"/>
+ <c:option name="False" value="false"/>
+ </c:property-options>
+ <c:defaultValueDescription>If nothing is specified, the default of true will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="track-connection-by-tx"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="Track Connection By Transaction"
+ required="false">
+ <c:description>Whether the connection should be locked into the transaction.</c:description>
+ <c:property-options>
+ <c:option name="True" value="true"/>
+ <c:option name="False" value="false"/>
+ </c:property-options>
+ </c:simple-property>
+
+ <c:simple-property name="isSameRM-override-value"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="isSameRM Override Value"
+ required="false">
+ <c:description>Allows one to unconditionally set whether the
+ javax.transaction.xa.XAResource.isSameRMXAResource returns true or false. The default is not
+ to override the return value.
+ </c:description>
+ <c:property-options>
+ <c:option name="True" value="true"/>
+ <c:option name="False" value="false"/>
+ </c:property-options>
+ <c:defaultValueDescription>If nothing is specified, the default of false will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="use-strict-min"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="Use Strict Minimum"
+ required="false">
+ <c:description>Whether on not to use strict minumum.</c:description>
+ <c:property-options>
+ <c:option name="True" value="true"/>
+ <c:option name="False" value="false"/>
+ </c:property-options>
+ <c:defaultValueDescription>If nothing is specified, the default of false will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="prefill"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="Prefill"
+ description="Prefill the Pool with Connection objects, or lazy load objects in the pool" required="false">
+ <c:description>Whether or not to use prefill.</c:description>
+ <c:property-options>
+ <c:option name="True" value="true"/>
+ <c:option name="False" value="false"/>
+ </c:property-options>
+ <c:defaultValueDescription>If nothing is specified, the default of false will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="validate-on-match"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="Validate On Match"
+ required="false">
+ <c:description>Whether on not to use validate on match.</c:description>
+ <c:property-options>
+ <c:option name="True" value="true"/>
+ <c:option name="False" value="false"/>
+ </c:property-options>
+ <c:defaultValueDescription>If nothing is specified, the default of false will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="background-validation"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="Background Validation"
+ required="false">
+ <c:description>Whether on not to use background validation.</c:description>
+ <c:property-options>
+ <c:option name="True" value="true"/>
+ <c:option name="False" value="false"/>
+ </c:property-options>
+ <c:defaultValueDescription>If nothing is specified, the default of false will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="background-validation-minutes"
+ displayName="Background Validation Minutes"
+ units="minutes"
+ activationPolicy="immediate"
+ type="integer"
+ required="false">
+ <c:description>
+ Indicates the maximum time in minutes to validate the Connection in the background.
+ </c:description>
+ <c:constraint>
+ <c:integer-constraint minimum="0"/>
+ </c:constraint>
+ </c:simple-property>
+
+ <c:simple-property name="blocking-timeout-millis"
+ displayName="Blocking Timeout in Milliseconds"
+ units="milliseconds"
+ activationPolicy="immediate"
+ type="integer"
+ required="false">
+ <c:description>
+ Indicates the maximum time in milliseconds to block while waiting for a connection before throwing
+ an exception. Note that this blocks only while waiting for a permit for a connection, and will never
+ throw an exception if creating a new connection takes an inordinately long time. If nothing is specified
+ the default of 30000 milliseconds is used.
+ </c:description>
+ <c:constraint>
+ <c:integer-constraint minimum="0"/>
+ </c:constraint>
+ </c:simple-property>
+
+ <c:simple-property name="idle-timeout-minutes"
+ type="integer"
+ activationPolicy="immediate"
+ displayName="Idle Timeout"
+ units="minutes"
+ required="false">
+ <c:description>Maximum time in minutes a connection can be idle before it is closed.
+ </c:description>
+ <c:constraint>
+ <c:integer-constraint minimum="0"/>
+ </c:constraint>
+ </c:simple-property>
+
+ <!-- XA ONLY-->
+ <c:simple-property name="xa-resource-timeout"
+ type="integer"
+ activationPolicy="immediate"
+ displayName="XA Resource Timeout"
+ units="minutes"
+ required="false">
+ <c:description>Maximum time in minutes an XA Resource can be idle before it is removed.
+ </c:description>
+ <c:constraint>
+ <c:integer-constraint minimum="0"/>
+ </c:constraint>
+ </c:simple-property>
+ <!-- XA ONLY-->
+
+ <c:simple-property name="new-connection-sql"
+ displayName="New Connection SQL"
+ type="string"
+ required="false"
+ description="Specify an SQL statement to execute whenever a connection is added to
+ the connection pool."/>
+
+ <c:simple-property name="check-valid-connection-sql"
+ displayName="Check Valid Connection SQL"
+ type="string"
+ required="false"
+ description="Specify an SQL statement to check validity of a pool connection.
+ This may be called when managed connection is taken from pool for use."/>
+
+ <c:list-property name="config-property"
+ displayName="Config Property"
+ description="Configuration Properties"
+ required="false">
+ <c:map-property name="property-values">
+ <c:simple-property name="config-property-name"
+ displayName="Name"
+ description="Name of the Configuration Property"
+ required="true"/>
+ <c:simple-property name="config-property-type"
+ displayName="Type"
+ description="Type of the Configuration Property"
+ required="true"/>
+ <c:simple-property name="config-property-value"
+ displayName="Value"
+ description="Value of the Configuration Property"
+ required="true"/>
+ </c:map-property>
+ </c:list-property>
+
+ </c:group>
+ </resource-configuration>
+ </platform>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v4.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v4.xml
new file mode 100644
index 0000000..6da4878
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropDeleted-v4.xml
@@ -0,0 +1,275 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="4"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="groupDeletedPlatform">
+ <resource-configuration>
+ <c:simple-property name="foobar" type="longString" description="blah blah blah"/>
+ <c:group name="advanced" displayName="Advanced">
+
+ <c:simple-property name="application-managed-security"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="Application Managed Security"
+ required="false">
+ <c:description>Specifying this element indicates that connections in the pool should be distinguished
+ by application code supplied parameters, such as from getConnection(user, pw). This requires
+ that you set a security domain which will populate a security-domain-and-application tag. If it is missing
+ this resource will not be created or saved.</c:description>
+ </c:simple-property>
+
+ <c:simple-property name="security-domain"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Security Domain/Security Domain and Application"
+ required="false">
+ <c:description>Indicates Subjects from security domain are used to distinguish connections in
+ this pool. If Application Managed Security is set to true, then this will create a security-domain
+ tag. If it is set to false or unset, then this property will populate a security-domain-and-application
+ tag.
+ </c:description>
+ <c:defaultValueDescription>If nothing is specified, the default will be to use a single pool of
+ equivalent connections.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="adapter-display-name"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Adapter Display Name"
+ description="used to identify the RAR deployment matching the display-name in the ra.xml"
+ required="false">
+ </c:simple-property>
+
+ <!-- @TODO bring back when ui can do List of Simples
+ <c:list-property name="depends"
+ displayName="Depends"
+ description="The depends element specifies the JMX ObjectName string of a service that
+ the connection manager services depend on. The connection manager service will
+ not be started until the dependent services have been started."
+ required="false">
+ <c:simple-property name="dependObjectName"
+ type="string"
+ activationPolicy="immediate"
+ displayName="ObjectName"
+ required="false"/>
+ </c:list-property>-->
+
+ <c:simple-property name="depends"
+ displayName="Depends"
+ description="The depends element specifies the JMX ObjectName string of a service that
+ the connection manager services depend on. The connection manager service will
+ not be started until the dependent services have been started."
+ required="false"
+ type="string"
+ activationPolicy="immediate"
+ />
+
+ <c:simple-property name="rar-name"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Rar Name"
+ description="This is the name of the RAR file that contains the definition for the
+ resource we want to provide. For nested RAR files, the name would look like
+ myapplication.ear#my.rar."
+ required="true"/>
+
+ <c:simple-property name="connection-definition"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Connection Definition"
+ description="This is the connection factory interface class. It should match the
+ connectionfactory-interface in the ra.xml file."
+ required="true"/>
+
+ <c:simple-property name="type-mapping"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Type Mappings"
+ description="This element declares a default type mapping for this datasource. The
+ type mapping should match a type-mapping/name element from standardjbosscmp-jdbc.xml."
+ required="false"/>
+
+ <c:simple-property name="use-java-context"
+ displayName="Use Java Context"
+ description="Indicates if the JNDI name should be prefixed with java:."
+ type="boolean"
+ required="false">
+ <c:defaultValueDescription>If nothing is specified, the default of true will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="transaction-type"
+ type="string"
+ displayName="Transaction Type"
+ default="true"
+ description="Whether to use local or xa transactions. If nothing is specified, the default of local will be used."
+ required="false">
+ <c:property-options>
+ <c:option value="Local Transaction"/>
+ <c:option value="XA Transaction"/>
+ </c:property-options>
+ </c:simple-property>
+
+ <!--<c:simple-property name="local-transaction"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="Local Transaction"
+ required="false">
+ <c:description>Whether on not to use local transactions.</c:description>
+ <c:defaultValueDescription>If nothing is specified, the default of false will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="xa-transaction"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="XA Transaction"
+ required="false">
+ <c:description>Whether on not to use XA transactions.</c:description>
+ <c:defaultValueDescription>If nothing is specified, the default of false will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>-->
+
+ <c:simple-property name="no-tx-separate-pools"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="No Tx Separate Pools"
+ required="false">
+ <c:description>The presence of this element indicates that two connection pools are required to
+ isolate connections used with JTA transaction from those used without a JTA transaction.
+ The pools are lazily constructed on first use. Its use case is for Oracle
+ (and possibly other vendors) XA implementations that don't like using an XA connection with
+ and without a JTA transaction.</c:description>
+ <c:defaultValueDescription>If nothing is specified, the default of true will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="track-connection-by-tx"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="Track Connection By Transaction"
+ required="false">
+ <c:description>Whether the connection should be locked into the transaction.</c:description>
+ </c:simple-property>
+
+ <c:simple-property name="isSameRM-override-value"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="isSameRM Override Value"
+ required="false">
+ <c:description>Allows one to unconditionally set whether the
+ javax.transaction.xa.XAResource.isSameRMXAResource returns true or false. The default is not
+ to override the return value.
+ </c:description>
+ <c:defaultValueDescription>If nothing is specified, the default of false will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="use-strict-min"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="Use Strict Minimum"
+ required="false">
+ <c:description>Whether on not to use strict minumum.</c:description>
+ <c:defaultValueDescription>If nothing is specified, the default of false will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="prefill"
+ type="boolean"
+ activationPolicy="immediate"
+ displayName="Prefill"
+ description="Prefill the Pool with Connection objects, or lazy load objects in the pool" required="false">
+ <c:description>Whether or not to use prefill.</c:description>
+ <c:defaultValueDescription>If nothing is specified, the default of false will be used.
+ </c:defaultValueDescription>
+ </c:simple-property>
+
+ <c:simple-property name="blocking-timeout-millis"
+ displayName="Blocking Timeout in Milliseconds"
+ units="milliseconds"
+ activationPolicy="immediate"
+ type="integer"
+ required="false">
+ <c:description>
+ Indicates the maximum time in milliseconds to block while waiting for a connection before throwing
+ an exception. Note that this blocks only while waiting for a permit for a connection, and will never
+ throw an exception if creating a new connection takes an inordinately long time. If nothing is specified
+ the default of 30000 milliseconds is used.
+ </c:description>
+ <c:constraint>
+ <c:integer-constraint minimum="0"/>
+ </c:constraint>
+ </c:simple-property>
+
+ <c:simple-property name="idle-timeout-minutes"
+ type="integer"
+ activationPolicy="immediate"
+ displayName="Idle Timeout"
+ units="minutes"
+ required="false">
+ <c:description>Maximum time in minutes a connection can be idle before it is closed.
+ </c:description>
+ <c:constraint>
+ <c:integer-constraint minimum="0"/>
+ </c:constraint>
+ </c:simple-property>
+
+ <!-- XA ONLY-->
+ <c:simple-property name="xa-resource-timeout"
+ type="integer"
+ activationPolicy="immediate"
+ displayName="XA Resource Timeout"
+ units="minutes"
+ required="false">
+ <c:description>Maximum time in minutes an XA Resource can be idle before it is removed.
+ </c:description>
+ <c:constraint>
+ <c:integer-constraint minimum="0"/>
+ </c:constraint>
+ </c:simple-property>
+ <!-- XA ONLY-->
+
+ <c:simple-property name="new-connection-sql"
+ displayName="New Connection SQL"
+ type="string"
+ required="false"
+ description="Specify an SQL statement to execute whenever a connection is added to
+ the connection pool."/>
+
+ <c:simple-property name="check-valid-connection-sql"
+ displayName="Check Valid Connection SQL"
+ type="string"
+ required="false"
+ description="Specify an SQL statement to check validity of a pool connection.
+ This may be called when managed connection is taken from pool for use."/>
+
+ <c:list-property name="config-property"
+ displayName="Config Property"
+ description="Configuration Properties"
+ required="false">
+ <c:map-property name="property-values">
+ <c:simple-property name="config-property-name"
+ displayName="Name"
+ description="Name of the Configuration Property"
+ required="true"/>
+ <c:simple-property name="config-property-type"
+ displayName="Type"
+ description="Type of the Configuration Property"
+ required="true"/>
+ <c:simple-property name="config-property-value"
+ displayName="Value"
+ description="Value of the Configuration Property"
+ required="true"/>
+ </c:map-property>
+ </c:list-property>
+
+ </c:group>
+ </resource-configuration>
+ </platform>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropMoved-v1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropMoved-v1.xml
new file mode 100644
index 0000000..2c73c28
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropMoved-v1.xml
@@ -0,0 +1,27 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="groupPropMovedPlatform">
+ <resource-configuration>
+ <c:group name="advanced" displayName="Advanced">
+ <c:simple-property name="security-domain-and-application"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Security Domain"
+ required="false">
+ <c:description>Indicates Subjects from security domain are used to distinguish connections in
+ this pool.
+ </c:description>
+ <c:defaultValueDescription>If nothing is specified, the default will be to use a single pool of
+ equivalent connections.
+ </c:defaultValueDescription>
+ </c:simple-property>
+ </c:group>
+ </resource-configuration>
+ </platform>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropMoved-v2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropMoved-v2.xml
new file mode 100644
index 0000000..4b7588a
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/groupPropMoved-v2.xml
@@ -0,0 +1,27 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="groupPropMovedPlatform">
+ <resource-configuration>
+ <c:group name="simple" displayName="Simple">
+ <c:simple-property name="security-domain-and-application"
+ type="string"
+ activationPolicy="immediate"
+ displayName="Security Domain"
+ required="false">
+ <c:description>Indicates Subjects from security domain are used to distinguish connections in
+ this pool.
+ </c:description>
+ <c:defaultValueDescription>If nothing is specified, the default will be to use a single pool of
+ equivalent connections.
+ </c:defaultValueDescription>
+ </c:simple-property>
+ </c:group>
+ </resource-configuration>
+ </platform>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyChanging-v1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyChanging-v1.xml
new file mode 100644
index 0000000..7c137eb
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyChanging-v1.xml
@@ -0,0 +1,39 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform7">
+
+ <resource-configuration>
+ <c:map-property name="one">
+ <c:simple-property name="simple">
+ <c:description>The Simpsons</c:description>
+ </c:simple-property>
+ </c:map-property>
+ <c:map-property name="two">
+ <c:simple-property name="simple">
+ <c:description>The Simpsons</c:description>
+ </c:simple-property>
+ </c:map-property>
+ <c:list-property name="three">
+ <c:simple-property name="simple">
+ <c:description>The Simpsons</c:description>
+ </c:simple-property>
+ </c:list-property>
+ <c:list-property name="four">
+ <c:simple-property name="simple">
+ <c:description>The Simpsons</c:description>
+ </c:simple-property>
+ </c:list-property>
+ <c:simple-property name="five">
+ <c:description>The Simpsons</c:description>
+ </c:simple-property>
+ <c:simple-property name="six">
+ <c:description>The Simpsons</c:description>
+ </c:simple-property>
+ </resource-configuration>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyChanging-v2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyChanging-v2.xml
new file mode 100644
index 0000000..442d64b
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyChanging-v2.xml
@@ -0,0 +1,44 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform7">
+
+ <resource-configuration>
+
+ <!-- one and two have been map-properties -->
+
+ <c:list-property name="one">
+ <c:simple-property name="simple">
+ <c:description>The Simpsons</c:description>
+ </c:simple-property>
+ </c:list-property>
+ <c:simple-property name="two">
+ <c:description>The Simpsons</c:description>
+ </c:simple-property>
+
+ <!-- three and four have been list-properties -->
+
+ <c:map-property name="three">
+ <c:simple-property name="simple">
+ <c:description>The Simpsons</c:description>
+ </c:simple-property>
+ </c:map-property>
+ <c:simple-property name="four">
+ <c:description>The Simpsons</c:description>
+ </c:simple-property>
+
+ <!-- five and six have been simple-properties -->
+
+ <c:map-property name="five">
+ <c:description>The Simpsons</c:description>
+ </c:map-property>
+ <c:list-property name="six">
+ <c:description>The Simpsons</c:description>
+ </c:list-property>
+ </resource-configuration>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyList-simple.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyList-simple.xml
new file mode 100644
index 0000000..b64cbee
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyList-simple.xml
@@ -0,0 +1,16 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform">
+ <resource-configuration>
+ <c:list-property name="a"
+ description="Yada !"
+ min="4"
+ max="6" />
+ </resource-configuration>
+
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyList-v1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyList-v1.xml
new file mode 100644
index 0000000..aebbbac
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyList-v1.xml
@@ -0,0 +1,46 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform6">
+
+ <resource-configuration>
+ <c:list-property name="myList1">
+ <c:description>Just a simple list</c:description>
+ <c:simple-property name="foo"/>
+ </c:list-property>
+ <c:list-property name="myList2">
+ <c:list-property name="embeddedList">
+ <c:simple-property name="foo"/>
+ </c:list-property>
+ </c:list-property>
+ <c:list-property name="myList3">
+ <c:simple-property name="baz"/>
+ </c:list-property>
+ <c:list-property name="rec1" min="1" max="10">
+ <c:list-property name="rec2" min="2" max="20">
+ <c:list-property name="rec3" min="3" max="30">
+ <c:list-property name="rec4" min="4" max="40">
+ <c:simple-property name="rec5">
+ <c:description>Deeply nested</c:description>
+ <c:property-options>
+ <c:option value="a"/>
+ <c:option value="b"/>
+ <c:option value="c"/>
+ <c:option value="d"/>
+ </c:property-options>
+ <c:constraint>
+ <c:integer-constraint maximum="5" minimum="2"/>
+ </c:constraint>
+ </c:simple-property>
+ </c:list-property>
+ </c:list-property>
+ </c:list-property>
+ </c:list-property>
+ </resource-configuration>
+
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyList-v2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyList-v2.xml
new file mode 100644
index 0000000..23c2100
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyList-v2.xml
@@ -0,0 +1,61 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform6">
+
+ <resource-configuration>
+ <!-- list1 went away -->
+
+ <!-- list2 stays as is -->
+ <c:list-property name="myList2">
+ <c:list-property name="embeddedList">
+ <c:simple-property name="foo"/>
+ </c:list-property>
+ </c:list-property>
+
+ <!-- list3 changes its content to a list property -->
+ <c:list-property name="myList3">
+ <c:list-property name="baz">
+ <c:description>myList3:baz</c:description>
+ <c:simple-property name="Hugo"/>
+ </c:list-property>
+ </c:list-property>
+
+ <!-- myList4 is new -->
+ <c:list-property name="myList4">
+ <c:description>Just a simple list</c:description>
+ <c:simple-property name="foo"/>
+ </c:list-property>
+
+ <!-- rec3 changes to rec3+ and the simple property gets new options, description and constraint -->
+ <c:list-property name="rec1">
+ <c:list-property name="rec2" min="12" max="200">
+ <c:list-property name="rec3+" min="13" max="300">
+ <c:list-property name="rec4" min="14" max="400">
+ <c:simple-property name="rec5">
+ <c:description>Nested deeply</c:description>
+ <c:property-options>
+ <c:option value="b"/>
+ <c:option value="c"/>
+ <c:option value="d"/>
+ <c:option value="x"/>
+ <c:option value="z"/>
+ </c:property-options>
+ <c:constraint>
+ <c:integer-constraint maximum="10" minimum="-2"/>
+ <c:float-constraint minimum="10" maximum="5"/>
+ </c:constraint>
+ </c:simple-property>
+ </c:list-property>
+ </c:list-property>
+ </c:list-property>
+ </c:list-property>
+
+ </resource-configuration>
+
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyMap-v1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyMap-v1.xml
new file mode 100644
index 0000000..047a0a7
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyMap-v1.xml
@@ -0,0 +1,35 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform7">
+
+ <resource-configuration>
+ <c:map-property name="map1">
+ </c:map-property>
+ <c:map-property name="map2" required="false">
+ </c:map-property>
+ <c:map-property name="map3" required="true">
+ </c:map-property>
+ <c:map-property name="map4">
+ <c:map-property name="map4:2">
+ <c:map-property name="map4:2:3">
+ <c:simple-property name="simple">
+ <c:description>The Simpsons</c:description>
+ </c:simple-property>
+ </c:map-property>
+ </c:map-property>
+ </c:map-property>
+ <c:map-property name="map5">
+ <c:simple-property name="hugo">
+ <c:description>foo</c:description>
+ </c:simple-property>
+ </c:map-property>
+
+ </resource-configuration>
+
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyMap-v2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyMap-v2.xml
new file mode 100644
index 0000000..d370778
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/propertyMap-v2.xml
@@ -0,0 +1,49 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform7">
+
+ <resource-configuration>
+ <!-- map1 goes away -->
+
+ <!-- map2 stays as is -->
+ <c:map-property name="map2" required="false">
+ </c:map-property>
+
+ <!-- map3 changes required status -->
+ <c:map-property name="map3" required="false">
+ </c:map-property>
+
+ <!-- map4 changes some things-->
+ <c:map-property name="map4">
+ <c:map-property name="map4:2+">
+ <c:map-property name="map4:2:3">
+ <c:list-property name="list">
+ <c:description>The Simpsons</c:description>
+ </c:list-property>
+ <c:simple-property name="simple2">
+ <c:description>The movie</c:description>
+ </c:simple-property>
+ </c:map-property>
+ </c:map-property>
+ </c:map-property>
+
+ <!-- trick one: map1 used to be a map-property in v1 -->
+ <c:simple-property name="map1">
+ </c:simple-property>
+
+ <!-- description of included simple prop changed -->
+ <c:map-property name="map5">
+ <c:simple-property name="hugo">
+ <c:description>bar</c:description>
+ </c:simple-property>
+ </c:map-property>
+
+ </resource-configuration>
+
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/update5-v1_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/update5-v1_0.xml
new file mode 100644
index 0000000..036e44e
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/update5-v1_0.xml
@@ -0,0 +1,84 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform5">
+ <server name="testServer1">
+ <plugin-configuration>
+ <c:group name="connection" displayName="Connection Info">
+ <c:simple-property name="namingURL"
+ displayName="Naming Provider URL"
+ description="the JNP URL with which to connect to the JBoss Application Server instance" />
+ <c:simple-property name="principal" required="false" />
+ <c:simple-property name="credentials" required="false" />
+ <c:simple-property name="configurationPath"
+ displayName="Configuration Path" type="directory"
+ description="The path to the configuration directory under which this instance operates." />
+ </c:group>
+ <c:group name="control" displayName="Controls system">
+ <c:simple-property name="programScript"
+ displayName="Program Script" type="file"
+ description="the full path to the script or executable used to start this instance" />
+ <c:simple-property name="configurationSet"
+ displayName="Configuration Set"
+ description="the name of the server configuration, e.g. minimal, default, all"
+ required="false" />
+ <c:simple-property name="bindingAddress"
+ displayName="Binding Address"
+ description="the host or IP address used by all JBoss services as the binding address"
+ required="false" />
+ </c:group>
+ <c:group name="tuning" displayName="Controls system">
+ <c:simple-property name="rampUpTime" type="file"
+ description="the full path to the script or executable used to start this instance" />
+ <c:simple-property name="steadyTime"
+ displayName="Configuration Set"
+ description="the name of the server configuration, e.g. minimal, default, all"
+ required="false" />
+ <c:simple-property name="rampDownTime"
+ displayName="Binding Address"
+ description="the host or IP address used by all JBoss services as the binding address"
+ readOnly="true"
+ summary="false"
+ required="false" />
+ </c:group>
+ </plugin-configuration>
+
+ <!--
+ - Now Process scans
+ -->
+ <process-scan name="JBoss4" query="foo" />
+ <process-scan name="JBoss5" query="bar" />
+ <process-scan name="JBoss6" query="baz" />
+
+
+
+
+
+ <resource-configuration>
+ <c:simple-property name="threadPoolSize" type="integer" displayName="Thread Pool Size" />
+ <c:simple-property name="jnpPort" type="integer" displayName="Port to access JMX" >
+ <c:property-options>
+ <c:option name="option1" value="1"/>
+ <c:option name="option2" value="2"/>
+ <c:option name="option3" value="3"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="secureJnpPort" type="integer" displayName="Port to access JMX over ssl" >
+ <c:constraint>
+ <c:integer-constraint minimum="0"/>
+ </c:constraint>
+ <c:constraint>
+ <c:integer-constraint maximum="5"/>
+ <c:float-constraint minimum="3.0"/>
+ <c:regex-constraint expression="foo"/>
+ </c:constraint>
+ </c:simple-property>
+ </resource-configuration>
+
+ </server>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/update5-v2_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/update5-v2_0.xml
new file mode 100644
index 0000000..8db93dd
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/update5-v2_0.xml
@@ -0,0 +1,96 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform5">
+ <server name="testServer1">
+ <plugin-configuration>
+ <!-- group connection is gone -->
+
+ <!-- control stays as is -->
+ <c:group name="control" displayName="Controls system">
+ <c:simple-property name="programScript"
+ displayName="Program Script" type="file"
+ description="the full path to the script or executable used to start this instance" />
+ <c:simple-property name="configurationSet"
+ displayName="Configuration Set"
+ description="the name of the server configuration, e.g. minimal, default, all"
+ required="false" />
+ <c:simple-property name="bindingAddress"
+ displayName="Binding Address"
+ description="the host or IP address used by all JBoss services as the binding address"
+ required="false" />
+ </c:group>
+
+ <!-- tuning as one property less and rampDownTime is now required-->
+ <c:group name="tuning" displayName="Controls system">
+ <c:simple-property name="rampUpTime" type="file"
+ description="the full path to the script or executable used to start this instance" />
+ <c:simple-property name="steadyTime"
+ displayName="Configuration Set"
+ description="the name of the server configuration, e.g. minimal, default, all"
+ required="false" />
+ <c:simple-property name="rampDownTime"
+ displayName="Binding Address"
+ description="the host or IP address used by all JBoss services as the binding address"
+ readOnly="false"
+ summary="true"
+ required="true" />
+ </c:group>
+
+ <!-- group fun is new -->
+ <c:group name="fun" displayName="Just for fun">
+ <c:simple-property name="funRampUpTime" type="file"
+ description="None given" />
+ </c:group>
+
+ </plugin-configuration>
+
+
+ <!--
+ - Now Process scans
+ -->
+
+ <!-- JBoss4 is gone -->
+
+ <!-- JBoss5 stays as is -->
+ <process-scan name="JBoss5" query="bar" />
+
+ <!-- JBoss6 has a different query -->
+ <process-scan name="JBoss6" query="hello world" />
+
+ <!-- Hibernate is new -->
+ <process-scan name="Hibernate" query="yada" />
+
+
+ <resource-configuration>
+ <!-- thread pool size is gone -->
+
+ <!-- jnpPort stays as is, but options change -->
+ <c:simple-property name="jnpPort" type="integer" displayName="Port to access JMX" >
+ <c:property-options>
+ <c:option name="option2" value="2"/>
+ <c:option name="option3" value="changed"/>
+ <c:option name="newOption4" value="4"/>
+ <c:option name="newOption5" value="5"/>
+ </c:property-options>
+ </c:simple-property>
+
+ <!-- secureJnpPort changes type and constraints and default value-->
+ <c:simple-property name="secureJnpPort" type="integer" displayName="Port to access JMX over ssl">
+ <c:constraint>
+ <c:float-constraint maximum="10"/>
+ <c:float-constraint minimum="3.0"/>
+ <c:regex-constraint expression="bar"/>
+ </c:constraint>
+ </c:simple-property>
+
+ <!-- memory size is new -->
+ <c:simple-property name="memorySize" type="integer" displayName="Size of some memory" />
+ </resource-configuration>
+ </server>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/updateDefaultTemplate1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/updateDefaultTemplate1.xml
new file mode 100644
index 0000000..0183c27
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/updateDefaultTemplate1.xml
@@ -0,0 +1,14 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform7">
+
+ <resource-configuration>
+ <c:simple-property name="six" default="foo"/>
+ </resource-configuration>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/updateDefaultTemplate2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/updateDefaultTemplate2.xml
new file mode 100644
index 0000000..702de08
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/configuration/updateDefaultTemplate2.xml
@@ -0,0 +1,14 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform7">
+
+ <resource-configuration>
+ <c:simple-property name="six" default="bar"/>
+ </resource-configuration>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/content-source-update-v1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/content-source-update-v1.xml
new file mode 100644
index 0000000..3c9537c
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/content-source-update-v1.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<content-plugin name="TestPlugin"
+ xmlns="urn:xmlns:rhq-serverplugin.content"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <!-- #1 -->
+ <contentSourceType name="testCSPHT1"
+ displayName="displayName1"
+ description="description1"
+ lazyLoad="false"
+ apiClass="org.abc.ApiClass1">
+
+ <configuration>
+ <c:simple-property name="prop1" type="directory" required="true" />
+ </configuration>
+
+ </contentSourceType>
+
+ <!-- missing #3 -->
+
+ <!-- #2 -->
+ <contentSourceType name="testCSPHT2"
+ displayName="displayName2"
+ description="description2"
+ lazyLoad="false"
+ apiClass="org.abc.ApiClass2">
+
+ <configuration>
+ <c:simple-property name="prop2" type="integer" required="false" />
+ </configuration>
+
+ </contentSourceType>
+
+ <!-- #4.1 -->
+ <contentSourceType name="testCSPHT4"
+ displayName="displayName4"
+ description="description4"
+ lazyLoad="true"
+ apiClass="org.abc.ApiClass4">
+
+ <configuration>
+ <c:simple-property name="prop4" type="file" required="false" />
+ </configuration>
+
+ </contentSourceType>
+
+</content-plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/content-source-update-v2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/content-source-update-v2.xml
new file mode 100644
index 0000000..eca6500
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/content-source-update-v2.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<content-plugin name="TestPlugin"
+ xmlns="urn:xmlns:rhq-serverplugin.content"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <!-- #1 -->
+ <contentSourceType name="testCSPHT1"
+ displayName="displayName1"
+ description="description1"
+ lazyLoad="false"
+ apiClass="org.abc.ApiClass1">
+
+ <configuration>
+ <c:simple-property name="prop1" type="directory" required="true" />
+ </configuration>
+
+ </contentSourceType>
+
+ <!-- missing #2 -->
+
+ <!-- #3 -->
+ <contentSourceType name="testCSPHT3"
+ displayName="displayName3"
+ description="description3"
+ lazyLoad="false"
+ apiClass="org.abc.ApiClass3">
+
+ <configuration>
+ <c:simple-property name="prop3" type="string" required="true" />
+ </configuration>
+
+ </contentSourceType>
+
+ <!-- #4.2 -->
+ <contentSourceType name="testCSPHT4"
+ displayName="displayName4changed"
+ description="description4changed"
+ lazyLoad="false"
+ apiClass="org.abc.ApiClass4changed">
+
+ <configuration>
+ <c:simple-property name="prop4_1" type="integer" required="false" />
+ <c:simple-property name="prop4_2" type="boolean" required="false" />
+ </configuration>
+
+ </contentSourceType>
+
+</content-plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/events/event1-1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/events/event1-1.xml
new file mode 100644
index 0000000..11f345e
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/events/event1-1.xml
@@ -0,0 +1,10 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <platform name="events">
+ <event name="hugo" description="One" displayName="HugoOne"/>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/events/event1-2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/events/event1-2.xml
new file mode 100644
index 0000000..f2bc857
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/events/event1-2.xml
@@ -0,0 +1,11 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <platform name="events">
+ <event name="hugo" description="Two" displayName="HugoTwo"/>
+ <event name="hans"/>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/measurementDeletion-v1_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/measurementDeletion-v1_0.xml
new file mode 100644
index 0000000..db954f5
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/measurementDeletion-v1_0.xml
@@ -0,0 +1,12 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <metric displayName="One" property="connectionCount1" displayType="detail" />
+ <metric displayName="Two" property="connectionCount2" displayType="detail" />
+ <metric displayName="Three" property="connectionCount3" displayType="detail" />
+ <metric displayName="Five" property="connectionCount5" displayType="detail" defaultInterval="30000" />
+ </server>
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/measurementDeletion-v2_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/measurementDeletion-v2_0.xml
new file mode 100644
index 0000000..721375a
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/measurementDeletion-v2_0.xml
@@ -0,0 +1,10 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update-v1_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update-v1_0.xml
new file mode 100644
index 0000000..6ba4994
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update-v1_0.xml
@@ -0,0 +1,14 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <metric displayName="One" property="connectionCount1" displayType="detail" />
+ <metric displayName="Two" property="connectionCount2" displayType="detail" />
+ <metric displayName="Three" property="connectionCount3" displayType="detail" />
+ <metric displayName="Five" property="connectionCount5" displayType="detail" defaultInterval="30000" />
+
+ </server>
+
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update-v2_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update-v2_0.xml
new file mode 100644
index 0000000..419e171
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update-v2_0.xml
@@ -0,0 +1,20 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <!-- one is gone -->
+
+ <!-- two stays as is-->
+ <metric displayName="Two" property="connectionCount2" displayType="detail" />
+ <!-- three is changed (display type) -->
+ <metric displayName="Three" property="connectionCount3" displayType="summary" />
+ <!-- four is new -->
+ <metric displayName="Four" property="connectionCount4" displayType="detail" />
+ <!-- five is changed as well (defaultInterval) -->
+ <metric displayName="Five" property="connectionCount5" displayType="detail" defaultInterval="50000" />
+
+ </server>
+
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update6-1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update6-1.xml
new file mode 100644
index 0000000..df4caf1
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update6-1.xml
@@ -0,0 +1,12 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <platform name="myPlatform7">
+ <server name="testServer1">
+ <metric displayName="One" property="connectionCount1" displayType="detail" />
+ </server>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update6-2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update6-2.xml
new file mode 100644
index 0000000..0c31c6d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update6-2.xml
@@ -0,0 +1,12 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <platform name="myPlatform7">
+ <server name="testServer2">
+ <metric displayName="One" property="connectionCount1" displayType="detail" />
+ </server>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update7-1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update7-1.xml
new file mode 100644
index 0000000..cac3941
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update7-1.xml
@@ -0,0 +1,10 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <platform name="myPlatform7">
+ <metric displayName="One" property="connectionCount1" displayType="detail" />
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update7-2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update7-2.xml
new file mode 100644
index 0000000..99d5659
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/measurement/update7-2.xml
@@ -0,0 +1,11 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <platform name="myPlatform7">
+ <metric displayName="One" property="connectionCount1" displayType="detail" />
+ <metric displayName="Two" property="connectionCount2" displayType="summary" />
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/natives/update5-v1_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/natives/update5-v1_0.xml
new file mode 100644
index 0000000..036e44e
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/natives/update5-v1_0.xml
@@ -0,0 +1,84 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform5">
+ <server name="testServer1">
+ <plugin-configuration>
+ <c:group name="connection" displayName="Connection Info">
+ <c:simple-property name="namingURL"
+ displayName="Naming Provider URL"
+ description="the JNP URL with which to connect to the JBoss Application Server instance" />
+ <c:simple-property name="principal" required="false" />
+ <c:simple-property name="credentials" required="false" />
+ <c:simple-property name="configurationPath"
+ displayName="Configuration Path" type="directory"
+ description="The path to the configuration directory under which this instance operates." />
+ </c:group>
+ <c:group name="control" displayName="Controls system">
+ <c:simple-property name="programScript"
+ displayName="Program Script" type="file"
+ description="the full path to the script or executable used to start this instance" />
+ <c:simple-property name="configurationSet"
+ displayName="Configuration Set"
+ description="the name of the server configuration, e.g. minimal, default, all"
+ required="false" />
+ <c:simple-property name="bindingAddress"
+ displayName="Binding Address"
+ description="the host or IP address used by all JBoss services as the binding address"
+ required="false" />
+ </c:group>
+ <c:group name="tuning" displayName="Controls system">
+ <c:simple-property name="rampUpTime" type="file"
+ description="the full path to the script or executable used to start this instance" />
+ <c:simple-property name="steadyTime"
+ displayName="Configuration Set"
+ description="the name of the server configuration, e.g. minimal, default, all"
+ required="false" />
+ <c:simple-property name="rampDownTime"
+ displayName="Binding Address"
+ description="the host or IP address used by all JBoss services as the binding address"
+ readOnly="true"
+ summary="false"
+ required="false" />
+ </c:group>
+ </plugin-configuration>
+
+ <!--
+ - Now Process scans
+ -->
+ <process-scan name="JBoss4" query="foo" />
+ <process-scan name="JBoss5" query="bar" />
+ <process-scan name="JBoss6" query="baz" />
+
+
+
+
+
+ <resource-configuration>
+ <c:simple-property name="threadPoolSize" type="integer" displayName="Thread Pool Size" />
+ <c:simple-property name="jnpPort" type="integer" displayName="Port to access JMX" >
+ <c:property-options>
+ <c:option name="option1" value="1"/>
+ <c:option name="option2" value="2"/>
+ <c:option name="option3" value="3"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="secureJnpPort" type="integer" displayName="Port to access JMX over ssl" >
+ <c:constraint>
+ <c:integer-constraint minimum="0"/>
+ </c:constraint>
+ <c:constraint>
+ <c:integer-constraint maximum="5"/>
+ <c:float-constraint minimum="3.0"/>
+ <c:regex-constraint expression="foo"/>
+ </c:constraint>
+ </c:simple-property>
+ </resource-configuration>
+
+ </server>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/natives/update5-v2_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/natives/update5-v2_0.xml
new file mode 100644
index 0000000..8db93dd
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/natives/update5-v2_0.xml
@@ -0,0 +1,96 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform5">
+ <server name="testServer1">
+ <plugin-configuration>
+ <!-- group connection is gone -->
+
+ <!-- control stays as is -->
+ <c:group name="control" displayName="Controls system">
+ <c:simple-property name="programScript"
+ displayName="Program Script" type="file"
+ description="the full path to the script or executable used to start this instance" />
+ <c:simple-property name="configurationSet"
+ displayName="Configuration Set"
+ description="the name of the server configuration, e.g. minimal, default, all"
+ required="false" />
+ <c:simple-property name="bindingAddress"
+ displayName="Binding Address"
+ description="the host or IP address used by all JBoss services as the binding address"
+ required="false" />
+ </c:group>
+
+ <!-- tuning as one property less and rampDownTime is now required-->
+ <c:group name="tuning" displayName="Controls system">
+ <c:simple-property name="rampUpTime" type="file"
+ description="the full path to the script or executable used to start this instance" />
+ <c:simple-property name="steadyTime"
+ displayName="Configuration Set"
+ description="the name of the server configuration, e.g. minimal, default, all"
+ required="false" />
+ <c:simple-property name="rampDownTime"
+ displayName="Binding Address"
+ description="the host or IP address used by all JBoss services as the binding address"
+ readOnly="false"
+ summary="true"
+ required="true" />
+ </c:group>
+
+ <!-- group fun is new -->
+ <c:group name="fun" displayName="Just for fun">
+ <c:simple-property name="funRampUpTime" type="file"
+ description="None given" />
+ </c:group>
+
+ </plugin-configuration>
+
+
+ <!--
+ - Now Process scans
+ -->
+
+ <!-- JBoss4 is gone -->
+
+ <!-- JBoss5 stays as is -->
+ <process-scan name="JBoss5" query="bar" />
+
+ <!-- JBoss6 has a different query -->
+ <process-scan name="JBoss6" query="hello world" />
+
+ <!-- Hibernate is new -->
+ <process-scan name="Hibernate" query="yada" />
+
+
+ <resource-configuration>
+ <!-- thread pool size is gone -->
+
+ <!-- jnpPort stays as is, but options change -->
+ <c:simple-property name="jnpPort" type="integer" displayName="Port to access JMX" >
+ <c:property-options>
+ <c:option name="option2" value="2"/>
+ <c:option name="option3" value="changed"/>
+ <c:option name="newOption4" value="4"/>
+ <c:option name="newOption5" value="5"/>
+ </c:property-options>
+ </c:simple-property>
+
+ <!-- secureJnpPort changes type and constraints and default value-->
+ <c:simple-property name="secureJnpPort" type="integer" displayName="Port to access JMX over ssl">
+ <c:constraint>
+ <c:float-constraint maximum="10"/>
+ <c:float-constraint minimum="3.0"/>
+ <c:regex-constraint expression="bar"/>
+ </c:constraint>
+ </c:simple-property>
+
+ <!-- memory size is new -->
+ <c:simple-property name="memorySize" type="integer" displayName="Size of some memory" />
+ </resource-configuration>
+ </server>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/noTypes.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/noTypes.xml
new file mode 100644
index 0000000..72bc8df
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/noTypes.xml
@@ -0,0 +1,8 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1000.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <!-- intentionally contains no types -->
+
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation1-1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation1-1.xml
new file mode 100644
index 0000000..4587815
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation1-1.xml
@@ -0,0 +1,11 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="ops">
+ <operation name="sleep"/>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation1-2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation1-2.xml
new file mode 100644
index 0000000..f32b862
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation1-2.xml
@@ -0,0 +1,27 @@
+<plugin name="ResourceMetaDataManagerBeanTest"
+ version="2.0"
+ displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="ops">
+ <operation name="sleep" />
+ <operation name="invokeSql" description="Execute arbitrary SQL">
+ <parameters>
+ <c:simple-property name="sql" />
+ <c:simple-property name="type" default="query">
+ <c:property-options>
+ <c:option value="query" name="query" />
+ <c:option value="update" name="update" />
+
+ </c:property-options>
+ </c:simple-property>
+ </parameters>
+ <results>
+ <c:simple-property name="result" />
+ <c:simple-property name="contents" />
+ </results>
+ </operation>
+ </platform>
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation2-1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation2-1.xml
new file mode 100644
index 0000000..c04bc55
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation2-1.xml
@@ -0,0 +1,17 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="ops">
+ <operation name="sleep"/>
+ <operation name="wakeup">
+ <parameters>
+ <c:simple-property name="time" />
+ </parameters>
+ </operation>
+ <operation name="getup"/>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation2-2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation2-2.xml
new file mode 100644
index 0000000..d28dabc
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation2-2.xml
@@ -0,0 +1,19 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="ops">
+ <operation name="wakeup">
+ <parameters>
+ <c:simple-property name="one" />
+ <c:simple-property name="two" />
+ </parameters>
+ </operation>
+ <operation name="getup"/>
+ <operation name="eat"/>
+ <operation name="goToWork"/>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation3-1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation3-1.xml
new file mode 100644
index 0000000..af34668
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation3-1.xml
@@ -0,0 +1,18 @@
+<plugin name="ResourceMetaDataManagerBeanTest"
+ version="1.0"
+ displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin" xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="ops">
+ <operation name="sleep" />
+ <operation name="wakeup">
+ <parameters>
+ <c:group name="testing">
+ <c:simple-property name="time" />
+ </c:group>
+ </parameters>
+ </operation>
+ <operation name="getup" />
+ </platform>
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation3-2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation3-2.xml
new file mode 100644
index 0000000..0589700
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/operation3-2.xml
@@ -0,0 +1,20 @@
+<plugin name="ResourceMetaDataManagerBeanTest"
+ version="2.0"
+ displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin" xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="ops">
+ <operation name="wakeup">
+ <parameters>
+ <c:group name="testing">
+ <c:simple-property name="one" />
+ <c:simple-property name="two" />
+ </c:group>
+ </parameters>
+ </operation>
+ <operation name="getup" />
+ <operation name="eat" />
+ <operation name="goToWork" />
+ </platform>
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/update3-v1_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/update3-v1_0.xml
new file mode 100644
index 0000000..658f24e
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/update3-v1_0.xml
@@ -0,0 +1,60 @@
+<plugin name="ResourceMetaDataManagerBeanTest"
+ version="1.0"
+ displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform3">
+
+ <operation name="restart"
+ description="Restarts the agent's comm layer and plugin container.">
+ </operation>
+
+ <operation name="shutdown"
+ description="Shuts down the agent's comm layer and plugin container.">
+ </operation>
+
+ <operation name="status"
+ description="Returns the current status of the system.">
+ <!--<parameters>
+ <notes>A note</notes>
+ </parameters>-->
+ </operation>
+
+ <content name="rpm" displayName="RPM File" category="deployable"
+ discoveryInterval="600000"
+ description="Red Hat installable package">
+ <configuration>
+ <c:simple-property name="version" displayName="Version" />
+ <c:simple-property name="build-date" displayName="Build Date" />
+ <c:simple-property name="url" displayName="URL" />
+ </configuration>
+ </content>
+
+ <content name="deb" displayName="DEB File" category="deployable"
+ discoveryInterval="600000"
+ description="Debian installable package">
+ <configuration>
+ <c:simple-property name="Version" />
+ <c:simple-property name="Filename" />
+ <c:simple-property name="Architecture" />
+ </configuration>
+ </content>
+
+ <content name="mpkg" displayName="Apple DMG File" category="deployable"
+ discoveryInterval="600000"
+ description="Apple installable packages">
+ <configuration>
+ <c:simple-property name="Version" />
+ <c:simple-property name="Filename" />
+ <c:simple-property name="Architecture" />
+ </configuration>
+ </content>
+
+
+
+
+ </platform>
+
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/update3-v2_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/update3-v2_0.xml
new file mode 100644
index 0000000..8a24c5d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/operation/update3-v2_0.xml
@@ -0,0 +1,67 @@
+<plugin name="ResourceMetaDataManagerBeanTest"
+ version="2.0"
+ displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform3">
+
+
+ <!-- Restart operation is gone -->
+
+ <!-- Shutdown stays as is -->
+ <operation name="shutdown"
+ description="Shuts down the agent's comm layer and plugin container.">
+ </operation>
+
+ <!-- status gets a new description and config definition -->
+ <operation name="status" description="Yadda!">
+ <!--<parameters>
+ <notes>Another note</notes>
+ </parameters>-->
+ </operation>
+
+ <!-- start is new -->
+ <operation name="start"
+ description="Start the show"/>
+
+
+ <!-- RPM content is gone -->
+
+ <!-- DEB stays as is -->
+ <content name="deb" displayName="DEB File" category="deployable"
+ discoveryInterval="600000"
+ description="Debian installable package">
+ <configuration>
+ <c:simple-property name="Version" />
+ <c:simple-property name="Filename" />
+ <c:simple-property name="Architecture" />
+ </configuration>
+ </content>
+
+ <!-- mpkg gets a different interval and configuration -->
+ <content name="mpkg" displayName="Apple DMG File" category="deployable"
+ discoveryInterval="300000"
+ description="Apple installable packages">
+ <configuration>
+ <c:simple-property name="Version" />
+ <c:simple-property name="Filename" />
+ </configuration>
+ </content>
+
+ <!-- UBU is new -->
+ <content name="ubu" displayName="Fantasy file format" category="deployable"
+ discoveryInterval="12345"
+ description="Fantasy ubuntu installer">
+ <configuration>
+ <c:simple-property name="Filesize" />
+ <c:simple-property name="Filename" />
+ </configuration>
+ </content>
+
+
+
+ </platform>
+
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/duplicateResourceType.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/duplicateResourceType.xml
new file mode 100644
index 0000000..5340b2e
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/duplicateResourceType.xml
@@ -0,0 +1,11 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="ops">
+ <server name="foo"/>
+ <server name="foo"/>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update2-v1_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update2-v1_0.xml
new file mode 100644
index 0000000..bb70c9b
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update2-v1_0.xml
@@ -0,0 +1,16 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <platform name="myPlatform">
+ <metric displayName="One" property="connectionCount1" displayType="detail" />
+ <service name="service1">
+ <metric displayName="Two" property="connectionCount2" displayType="detail" />
+ <service name="nestedOne">
+ <metric displayName="Three" property="failedConnections" displayType="summary"/>
+ </service>
+ </service>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update2-v2_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update2-v2_0.xml
new file mode 100644
index 0000000..91b63d9
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update2-v2_0.xml
@@ -0,0 +1,16 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <platform name="myPlatform">
+ <metric displayName="One" property="connectionCount1" displayType="summary" />
+ <service name="service1">
+ <metric displayName="Two" property="connectionCount2" displayType="detail" />
+ </service>
+ <service name="nestedOne">
+ <metric displayName="Three" property="failedConnections" displayType="summary"/>
+ </service>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update4-v1_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update4-v1_0.xml
new file mode 100644
index 0000000..614da65
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update4-v1_0.xml
@@ -0,0 +1,16 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <platform name="myPlatform4">
+ <server name="testServer1">
+ <metric displayName="One" property="connectionCount1" displayType="detail" />
+ </server>
+ <server name="testServer2">
+ <metric displayName="Two" property="connectionCount2" displayType="detail" />
+ <metric displayName="Three" property="connectionCount3" displayType="detail" />
+ <metric displayName="Five" property="connectionCount5" displayType="detail" defaultInterval="30000" />
+ </server>
+ </platform>
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update4-v2_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update4-v2_0.xml
new file mode 100644
index 0000000..e8b90b1
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/update4-v2_0.xml
@@ -0,0 +1,12 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <platform name="myPlatform4">
+ <server name="testServer1">
+ <metric displayName="One" property="connectionCount1" displayType="detail" />
+ </server>
+ </platform>
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/updateResourceTypeBundleTarget-v1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/updateResourceTypeBundleTarget-v1.xml
new file mode 100644
index 0000000..aa29ffd
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/updateResourceTypeBundleTarget-v1.xml
@@ -0,0 +1,27 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform1">
+ <server name="myTestServer1">
+ <plugin-configuration>
+ <c:simple-property name="prop1" />
+ </plugin-configuration>
+ <resource-configuration>
+ <c:simple-property name="resourceProp1" />
+ </resource-configuration>
+ <bundle-target>
+ <destination-base-dir name="firstDestBaseDir">
+ <value-context>pluginConfiguration</value-context>
+ <value-name>prop1</value-name>
+ </destination-base-dir>
+ <destination-base-dir name="secondDestBaseDir">
+ <value-context>fileSystem</value-context>
+ <value-name>/</value-name>
+ </destination-base-dir>
+ </bundle-target>
+ </server>
+ </platform>
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/updateResourceTypeBundleTarget-v2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/updateResourceTypeBundleTarget-v2.xml
new file mode 100644
index 0000000..c4f11ad
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource-type/updateResourceTypeBundleTarget-v2.xml
@@ -0,0 +1,23 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="myPlatform1">
+ <server name="myTestServer1">
+ <plugin-configuration>
+ <c:simple-property name="prop1" />
+ </plugin-configuration>
+ <resource-configuration>
+ <c:simple-property name="resourceProp1" />
+ </resource-configuration>
+ <bundle-target>
+ <destination-base-dir name="thirdDestBaseDir">
+ <value-context>resourceConfiguration</value-context>
+ <value-name>resourceProp1</value-name>
+ </destination-base-dir>
+ </bundle-target>
+ </server>
+ </platform>
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/illegal-subcat-1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/illegal-subcat-1.xml
new file mode 100644
index 0000000..e653736
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/illegal-subcat-1.xml
@@ -0,0 +1,15 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="one">
+ <subcategory name="one"/>
+ </subcategory>
+ </subcategories>
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-2children.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-2children.xml
new file mode 100644
index 0000000..4aa4064
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-2children.xml
@@ -0,0 +1,16 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="parent" displayName="Parent" description="The parent.">
+ <subcategory name="services" displayName="Services" description="Some services"/>
+ <subcategory name="applications" displayName="Apps" description="The apps."/>
+ </subcategory>
+ </subcategories>
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-grandchild.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-grandchild.xml
new file mode 100644
index 0000000..63afe40
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-grandchild.xml
@@ -0,0 +1,17 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="parent" displayName="Parent" description="The parent.">
+ <subcategory name="services" displayName="Services" description="Some services">
+ <subcategory name="applications" displayName="Apps" description="The apps."/>
+ </subcategory>
+ </subcategory>
+ </subcategories>
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-services-v1_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-services-v1_0.xml
new file mode 100644
index 0000000..91d6463
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-services-v1_0.xml
@@ -0,0 +1,21 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="parent" displayName="Parent" description="The parent.">
+ <subcategory name="services" displayName="Services" description="Some services"/>
+ <subcategory name="applications" displayName="Apps" description="The apps."/>
+ </subcategory>
+ </subcategories>
+
+ <service name="testService1" subCategory="services"/>
+ <service name="testService2" subCategory="services"/>
+ <service name="testApp1" subCategory="applications"/>
+
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-services-v2_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-services-v2_0.xml
new file mode 100644
index 0000000..93310c1
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-services-v2_0.xml
@@ -0,0 +1,19 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="parent" displayName="Parent" description="The parent.">
+ <subcategory name="applications2" displayName="Apps2" description="The apps2."/>
+ </subcategory>
+ </subcategories>
+
+ <service name="testService2" subCategory="applications2"/>
+ <service name="testApp1" subCategory="applications2"/>
+
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-v1_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-v1_0.xml
new file mode 100644
index 0000000..18c05ef
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-v1_0.xml
@@ -0,0 +1,15 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="parent" displayName="Parent" description="The parent.">
+ <subcategory name="applications" displayName="Apps" description="The apps."/>
+ </subcategory>
+ </subcategories>
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-v1_1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-v1_1.xml
new file mode 100644
index 0000000..0a13158
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-v1_1.xml
@@ -0,0 +1,15 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="parent" displayName="Parent" description="The parent.">
+ <subcategory name="applications" displayName="Apps2" description="The apps2."/>
+ </subcategory>
+ </subcategories>
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-v2_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-v2_0.xml
new file mode 100644
index 0000000..56563dc
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/nested-subcat-v2_0.xml
@@ -0,0 +1,15 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="parent" displayName="Parent" description="The parent.">
+ <subcategory name="services" displayName="Services" description="Some services"/>
+ </subcategory>
+ </subcategories>
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/no-subcat.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/no-subcat.xml
new file mode 100644
index 0000000..064753f
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/no-subcat.xml
@@ -0,0 +1,10 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v1_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v1_0.xml
new file mode 100644
index 0000000..c7d308e
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v1_0.xml
@@ -0,0 +1,13 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="applications" displayName="Apps" description="The apps."/>
+ </subcategories>
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v1_1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v1_1.xml
new file mode 100644
index 0000000..36d6acd
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v1_1.xml
@@ -0,0 +1,13 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="applications" displayName="Apps2" description="The apps2."/>
+ </subcategories>
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v2_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v2_0.xml
new file mode 100644
index 0000000..21a0134
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v2_0.xml
@@ -0,0 +1,13 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="services" displayName="Services" description="Some services"/>
+ </subcategories>
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v3_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v3_0.xml
new file mode 100644
index 0000000..05bca6a
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/one-subcat-v3_0.xml
@@ -0,0 +1,13 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="3.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="parent" displayName="Parent" description="The parent."/>
+ </subcategories>
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/services-v1_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/services-v1_0.xml
new file mode 100644
index 0000000..27908e4
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/services-v1_0.xml
@@ -0,0 +1,13 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <service name="testService1"/>
+ <service name="testService2"/>
+ <service name="testApp1"/>
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/services-v2_0.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/services-v2_0.xml
new file mode 100644
index 0000000..0440e33
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/services-v2_0.xml
@@ -0,0 +1,12 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <service name="testService2"/>
+ <service name="testApp1"/>
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/test-subcategories.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/test-subcategories.xml
new file mode 100644
index 0000000..95f27d8
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/test-subcategories.xml
@@ -0,0 +1,26 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <!-- The configuration for this server should not throw any errors. -->
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="applications" displayName="Apps" description="The apps."/>
+ </subcategories>
+ </server>
+
+
+ <server name="testServer2">
+ <subcategories>
+ <subcategory name="services" displayName="Services" description="Some datasources"/>
+ <subcategory name="resource">
+ <subcategory name="dataSource" displayName="DataSource" description="Some datasources"/>
+ <subcategory name="destinations" displayName="JMS Destinations" description="Some destinations"/>
+ </subcategory>
+ </subcategories>
+ </server>
+
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/test-subcategories2.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/test-subcategories2.xml
new file mode 100644
index 0000000..ec1e69d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/test-subcategories2.xml
@@ -0,0 +1,26 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <!-- The configuration for this server should not throw any errors. -->
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="applications" displayName="Apps2" description="The apps2."/>
+ </subcategories>
+ </server>
+
+
+ <server name="testServer2">
+ <subcategories>
+ <subcategory name="services2" displayName="Services" description="Some datasources"/>
+ <subcategory name="resource">
+ <subcategory name="dataSource" displayName="DataSource" description="Some datasources"/>
+ <subcategory name="destinations" displayName="JMS Destinations" description="Some destinations"/>
+ </subcategory>
+ </subcategories>
+ </server>
+
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/test-subcategories3.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/test-subcategories3.xml
new file mode 100644
index 0000000..505a361
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/test-subcategories3.xml
@@ -0,0 +1,33 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ version="3.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <!-- The configuration for this server should not throw any errors. -->
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="applications" displayName="Apps" description="The apps."/>
+ </subcategories>
+
+
+ <server name="testServer3"
+ subCategory="applications"
+ >
+ </server>
+
+ </server>
+
+ <server name="testServer2">
+ <subcategories>
+ <subcategory name="services" displayName="Services" description="Some datasources"/>
+ <subcategory name="resource">
+ <subcategory name="dataSource" displayName="DataSource" description="Some datasources"/>
+ <subcategory name="destinations" displayName="JMS Destinations" description="Some destinations"/>
+ </subcategory>
+ </subcategories>
+ </server>
+
+
+
+
+</plugin>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/two-subcat.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/two-subcat.xml
new file mode 100644
index 0000000..2f44202
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/two-subcat.xml
@@ -0,0 +1,13 @@
+<plugin name="ResourceMetaDataManagerBeanTest" displayName="Mock JBoss AS" package="org.rhq.plugins.mock.jboss"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="applications" displayName="Apps" description="The apps."/>
+ <subcategory name="services" displayName="Services" description="Some services"/>
+ </subcategories>
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/undefined-child-subcat-1.xml b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/undefined-child-subcat-1.xml
new file mode 100644
index 0000000..9870576
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/metadata/resource/undefined-child-subcat-1.xml
@@ -0,0 +1,21 @@
+<plugin name="ResourceMetaDataManagerBeanTest"
+ version="1.0"
+ displayName="Mock JBoss AS"
+ package="org.rhq.plugins.mock.jboss"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <server name="testServer1">
+ <subcategories>
+ <subcategory name="one"/>
+ <subcategory name="two"/>
+ </subcategories>
+
+ <service name="testService" subCategory="three">
+ <service name="testService2" subCategory="four"/>
+ </service>
+
+ </server>
+
+</plugin>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/minimal_hsqldb_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/minimal_hsqldb_ds.xml
new file mode 100644
index 0000000..4fb62d9
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/minimal_hsqldb_ds.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- The Hypersonic embedded database JCA connection factory config
+$Id: minimal_hsqldb_ds.xml 680 2005-09-14 01:52:58Z ccrouch $ -->
+
+
+<datasources>
+ <local-tx-datasource>
+
+ <!-- The jndi name of the DataSource, it is prefixed with java:/ -->
+ <!-- Datasources are not available outside the virtual machine -->
+ <jndi-name>DefaultDS</jndi-name>
+
+ <connection-url attrib="a" >jdbc:hsqldb:${jboss.server.data.dir}${/}hypersonic${/}localDB</connection-url>
+ <connection-property name="111">aaa</connection-property>
+ <connection-property name="222">bbb</connection-property>
+ <connection-property name="444">ddd</connection-property>
+ <user-name>jones</user-name>
+ </local-tx-datasource>
+
+ <mbean name="test">
+ <arg>addd</arg>
+ </mbean>
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/msaccess_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/msaccess_ds.xml
new file mode 100644
index 0000000..5f03e7d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/msaccess_ds.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- JBoss Server Configuration -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<!-- $Id: msaccess_ds.xml 695 2005-09-17 00:43:05Z ccrouch $ -->
+<!-- ==================================================================== -->
+<!-- This uses the sun jdbc-odbc driver, so don't expect miracles -->
+<!-- Thanks to Alan Moor, who warns... -->
+<!-- Remember, though, never trust critical data, or data that you can't -->
+<!-- afford to lose, or data that you need quick access to, or data that -->
+<!-- needs to be secure, to Microsoft Access. -->
+<!-- ===================================================================== -->
+
+
+<datasources>
+ <no-tx-datasource>
+ <jndi-name>MSAccessDS</jndi-name>
+ <use-java-context>false</use-java-context>
+ <!-- format of URL is "jdbc:odbc:DSNNAME" -->
+ <connection-url>jdbc:odbc:INsightDSN</connection-url>
+ <driver-class>sun.jdbc.odbc.JdbcOdbcDriver</driver-class>
+ <user-name>x</user-name>
+ <password>y</password>
+ <security-domain-and-application>DbRealm</security-domain-and-application>
+ <prepared-statement-cache-size>10</prepared-statement-cache-size>
+ </no-tx-datasource>
+
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/no_auth_type_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/no_auth_type_ds.xml
new file mode 100644
index 0000000..3437a97
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/no_auth_type_ds.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<datasources>
+ <no-tx-datasource>
+ <jndi-name>jndiName</jndi-name>
+
+ <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+ <metadata>
+ <type-mapping>Hypersonic SQL</type-mapping>
+ </metadata>
+
+ <!-- This mbean can be used when using in process persistent hypersonic -->
+ <depends>jboss:service=Hypersonic,database=localDB</depends>
+ </no-tx-datasource>
+
+ <mbean code="org.jboss.jdbc.HypersonicDatabase"
+ name="jboss:service=Hypersonic">
+ <attribute name="Port">1701</attribute>
+ <attribute name="Silent">true</attribute>
+ <attribute name="Database">default</attribute>
+ <attribute name="Trace">false</attribute>
+ <attribute name="No_system_exit">true</attribute>
+ </mbean>
+
+
+
+ <mbean code="org.jboss.jdbc.HypersonicDatabase"
+ name="jboss:service=Hypersonic,database=localDB">
+ <attribute name="Database">localDB</attribute>
+ <attribute name="InProcessMode">true</attribute>
+ </mbean>
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_2_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_2_ds.xml
new file mode 100644
index 0000000..8ec633a
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_2_ds.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- JBoss Server Configuration -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<!-- $Id: oracle_xa_2_ds.xml 954 2005-11-02 21:56:42Z ccrouch $ -->
+
+<!-- ===================================================================== -->
+<!-- ATTENTION: DO NOT FORGET TO SET Pad=true IN transaction-service.xml -->
+<!-- ===================================================================== -->
+
+<datasources>
+ <xa-datasource>
+ <jndi-name>XAOracleDS2</jndi-name>
+ <isSameRM-override-value/>
+ <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
+ <xa-datasource-property name="URL">
+ jdbc:oracle:oci8:@tc</xa-datasource-property>
+ <xa-datasource-property name="User">scott</xa-datasource-property>
+ <xa-datasource-property name="Password">tiger</xa-datasource-property>
+ <!-- Uses the pingDatabase method to check a connection is still valid before handing it out from the pool -->
+ <!--valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name-->
+ <!-- Checks the Oracle error codes and messages for fatal errors -->
+ <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
+ <!-- Oracles XA datasource cannot reuse a connection outside a transaction once enlisted in a global transaction and vice-versa -->
+ <no-tx-separate-pools/>
+ <track-statements>false</track-statements>
+ <track-connection-by-tx>true</track-connection-by-tx>
+
+ <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+ <metadata>
+ <type-mapping>Oracle9i</type-mapping>
+ </metadata>
+ </xa-datasource>
+
+ <mbean code="org.jboss.resource.adapter.jdbc.vendor.OracleXAExceptionFormatter"
+ name="jboss.jca:service=OracleXAExceptionFormatter">
+ <depends optional-attribute-name="TransactionManagerService">jboss:service=TransactionManager</depends>
+ </mbean>
+
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_3_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_3_ds.xml
new file mode 100644
index 0000000..7a3d90d
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_3_ds.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- JBoss Server Configuration -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<!-- $Id: oracle_xa_3_ds.xml 942 2005-11-02 05:46:41Z ccrouch $ -->
+
+<!-- ===================================================================== -->
+<!-- ATTENTION: DO NOT FORGET TO SET Pad=true IN transaction-service.xml -->
+<!-- ===================================================================== -->
+
+<datasources>
+ <xa-datasource>
+ <jndi-name>XAOracleDS3</jndi-name>
+ <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
+ <xa-datasource-property name="URL">
+ jdbc:oracle:oci8:@tc</xa-datasource-property>
+ <xa-datasource-property name="User">scott</xa-datasource-property>
+ <xa-datasource-property name="Password">tiger</xa-datasource-property>
+ <!-- Uses the pingDatabase method to check a connection is still valid before handing it out from the pool -->
+ <!--valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name-->
+ <!-- Checks the Oracle error codes and messages for fatal errors -->
+ <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
+ <!-- Oracles XA datasource cannot reuse a connection outside a transaction once enlisted in a global transaction and vice-versa -->
+ <no-tx-separate-pools>false</no-tx-separate-pools>
+ <track-statements>nowarn</track-statements>
+ <track-connection-by-tx>false</track-connection-by-tx>
+
+ <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+ <metadata>
+ <type-mapping>Oracle9i</type-mapping>
+ </metadata>
+ </xa-datasource>
+
+ <mbean code="org.jboss.resource.adapter.jdbc.vendor.OracleXAExceptionFormatter"
+ name="jboss.jca:service=OracleXAExceptionFormatter">
+ <depends optional-attribute-name="TransactionManagerService">jboss:service=TransactionManager</depends>
+ </mbean>
+
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_4_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_4_ds.xml
new file mode 100644
index 0000000..c83ecf7
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_4_ds.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- JBoss Server Configuration -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<!-- $Id: oracle_xa_4_ds.xml 942 2005-11-02 05:46:41Z ccrouch $ -->
+
+<!-- ===================================================================== -->
+<!-- ATTENTION: DO NOT FORGET TO SET Pad=true IN transaction-service.xml -->
+<!-- ===================================================================== -->
+
+<datasources>
+ <xa-datasource>
+ <jndi-name>XAOracleDS4</jndi-name>
+ <isSameRM-override-value>false</isSameRM-override-value>
+ <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
+ <xa-datasource-property name="URL">
+ jdbc:oracle:oci8:@tc</xa-datasource-property>
+ <xa-datasource-property name="User">scott</xa-datasource-property>
+ <xa-datasource-property name="Password">tiger</xa-datasource-property>
+ <!-- Uses the pingDatabase method to check a connection is still valid before handing it out from the pool -->
+ <!--valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name-->
+ <!-- Checks the Oracle error codes and messages for fatal errors -->
+ <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
+
+
+
+ <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+ <metadata>
+ <type-mapping>Oracle9i</type-mapping>
+ </metadata>
+ </xa-datasource>
+
+ <mbean code="org.jboss.resource.adapter.jdbc.vendor.OracleXAExceptionFormatter"
+ name="jboss.jca:service=OracleXAExceptionFormatter">
+ <depends optional-attribute-name="TransactionManagerService">jboss:service=TransactionManager</depends>
+ </mbean>
+
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_5_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_5_ds.xml
new file mode 100644
index 0000000..12c1970
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_5_ds.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- JBoss Server Configuration -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<!-- $Id: oracle_xa_5_ds.xml 1151 2006-01-18 02:54:28Z ccrouch $ -->
+
+<!-- ===================================================================== -->
+<!-- ATTENTION: DO NOT FORGET TO SET Pad=true IN transaction-service.xml -->
+<!-- ===================================================================== -->
+
+<datasources>
+ <xa-datasource>
+ <jndi-name>XAOracleDS</jndi-name>
+ <isSameRM-override-value>false</isSameRM-override-value>
+ <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
+ <!-- Uses the pingDatabase method to check a connection is still valid before handing it out from the pool -->
+ <!--valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name-->
+ <!-- Checks the Oracle error codes and messages for fatal errors -->
+ <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
+ <!-- Oracles XA datasource cannot reuse a connection outside a transaction once enlisted in a global transaction and vice-versa -->
+ <no-tx-separate-pools/>
+
+ <track-connection-by-tx/>
+
+ <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+ <metadata>
+ <type-mapping>Oracle9i</type-mapping>
+ </metadata>
+ </xa-datasource>
+
+ <mbean code="org.jboss.resource.adapter.jdbc.vendor.OracleXAExceptionFormatter"
+ name="jboss.jca:service=OracleXAExceptionFormatter">
+ <depends optional-attribute-name="TransactionManagerService">jboss:service=TransactionManager</depends>
+ </mbean>
+
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_ds.xml
new file mode 100644
index 0000000..3a755fa
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/oracle_xa_ds.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- JBoss Server Configuration -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<!-- $Id: oracle_xa_ds.xml 942 2005-11-02 05:46:41Z ccrouch $ -->
+
+<!-- ===================================================================== -->
+<!-- ATTENTION: DO NOT FORGET TO SET Pad=true IN transaction-service.xml -->
+<!-- ===================================================================== -->
+
+<datasources>
+ <xa-datasource>
+ <jndi-name>XAOracleDS</jndi-name>
+ <isSameRM-override-value>false</isSameRM-override-value>
+ <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
+ <xa-datasource-property name="URL">
+ jdbc:oracle:oci8:@tc</xa-datasource-property>
+ <xa-datasource-property name="User">scott</xa-datasource-property>
+ <xa-datasource-property name="Password">tiger</xa-datasource-property>
+ <!-- Uses the pingDatabase method to check a connection is still valid before handing it out from the pool -->
+ <!--valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name-->
+ <!-- Checks the Oracle error codes and messages for fatal errors -->
+ <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
+ <!-- Oracles XA datasource cannot reuse a connection outside a transaction once enlisted in a global transaction and vice-versa -->
+ <no-tx-separate-pools/>
+
+ <track-connection-by-tx/>
+
+ <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+ <metadata>
+ <type-mapping>Oracle9i</type-mapping>
+ </metadata>
+ </xa-datasource>
+
+ <mbean code="org.jboss.resource.adapter.jdbc.vendor.OracleXAExceptionFormatter"
+ name="jboss.jca:service=OracleXAExceptionFormatter">
+ <depends optional-attribute-name="TransactionManagerService">jboss:service=TransactionManager</depends>
+ </mbean>
+
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/too_many_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/test/too_many_ds.xml
new file mode 100644
index 0000000..aa1ee56
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/too_many_ds.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- Generic datasource configuration showing all possibilities -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<!-- $Id: too_many_ds.xml 695 2005-09-17 00:43:05Z ccrouch $ -->
+
+
+<datasources>
+ <local-tx-datasource>
+ <jndi-name>GenericDS</jndi-name>
+ <connection-url>[jdbc: url for use with Driver class]</connection-url>
+ <driver-class>[fully qualified class name of java.sql.Driver implementation]</driver-class>
+ <user-name>x</user-name>
+ <password>y</password>
+ <!-- you can include connection properties that will get passed in
+ the DriverManager.getConnection(props) call-->
+ <!-- look at your Driver docs to see what these might be -->
+ <connection-property name="char.encoding">UTF-8</connection-property>
+ <transaction-isolation>TRANSACTION_SERIALIZABLE</transaction-isolation>
+
+ <!--pooling parameters-->
+ <min-pool-size>5</min-pool-size>
+ <max-pool-size>100</max-pool-size>
+ <blocking-timeout-millis>5000</blocking-timeout-millis>
+ <idle-timeout-minutes>15</idle-timeout-minutes>
+ <!-- sql to call when connection is created -->
+ <new-connection-sql>select * from user where name=$</new-connection-sql>
+
+
+ <!-- sql to call on an existing pooled connection when it is obtained from pool -->
+ <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
+
+
+
+ <!-- pooling criteria. USE AT MOST ONE-->
+ <!-- If you don't use JAAS login modules or explicit login
+ getConnection(usr,pw) but rely on user/pw specified above,
+ don't specify anything here -->
+
+ <!-- If you supply the usr/pw from a JAAS login module
+ <security-domain>MyRealm</security-domain>
+-->
+
+ <!-- if your app supplies the usr/pw explicitly getConnection(usr, pw) -->
+ <application-managed-security/>
+
+ <!--Anonymous depends elements are copied verbatim into the ConnectionManager mbean config-->
+ <depends>myapp.service:service=DoSomethingService</depends>
+
+ </local-tx-datasource>
+
+ <!-- you can include regular mbean configurations like this one -->
+ <mbean code="org.jboss.tm.XidFactory"
+ name="jboss:service=XidFactory">
+ <attribute name="Pad">true</attribute>
+ </mbean>
+
+
+ <!-- Here's an xa example -->
+ <xa-datasource>
+ <jndi-name>GenericXADS</jndi-name>
+ <xa-datasource-class>[fully qualified name of class implementing javax.sql.XADataSource goes here]</xa-datasource-class>
+ <xa-datasource-property name="SomeProperty">SomePropertyValue</xa-datasource-property>
+ <xa-datasource-property name="SomeOtherProperty">SomeOtherValue</xa-datasource-property>
+
+ <user-name>x</user-name>
+ <password>y</password>
+ <transaction-isolation>TRANSACTION_SERIALIZABLE</transaction-isolation>
+
+
+
+ <!--pooling parameters-->
+ <min-pool-size>5</min-pool-size>
+ <max-pool-size>100</max-pool-size>
+ <blocking-timeout-millis>5000</blocking-timeout-millis>
+ <idle-timeout-minutes>15</idle-timeout-minutes>
+ <!-- sql to call when connection is created
+ <new-connection-sql>some arbitrary sql</new-connection-sql>
+ -->
+
+ <!-- sql to call on an existing pooled connection when it is obtained from pool
+ <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
+ -->
+
+
+ <!-- pooling criteria. USE AT MOST ONE-->
+ <!-- If you don't use JAAS login modules or explicit login
+ getConnection(usr,pw) but rely on user/pw specified above,
+ don't specify anything here -->
+
+ <!-- If you supply the usr/pw from a JAAS login module -->
+ <security-domain/>
+
+ <!-- if your app supplies the usr/pw explicitly getConnection(usr, pw) -->
+ <application-managed-security/>
+
+ </xa-datasource>
+
+
+
+
+</datasources>
diff --git a/modules/enterprise/server/itests-2/src/test/resources/test/xpath_processor_test.xml b/modules/enterprise/server/itests-2/src/test/resources/test/xpath_processor_test.xml
new file mode 100644
index 0000000..0b23849
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/test/xpath_processor_test.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xpathproc>
+ <test1></test1>
+ <test2/>
+ <!-- <test3/> -->
+ <test4>4</test4>
+ <test5>
+ 5
+ </test5>
+ <test6><!-- test -->6</test6>
+ <test7>
+ YYY
+ <!-- test -->
+ 7
+ </test7>
+
+ <test8>
+ 8
+ <!-- test -->
+ ZZZ
+ </test8>
+
+ <test9>
+
+ <!-- test -->
+ 9
+ </test9>
+
+ <test10 name="test10">10</test10>
+
+ <test11 name="test11">
+ 11</test11>
+
+ <test12 name="test12"><!-- test -->12</test12>
+
+ <test13 name="test13
+ ">13</test13>
+
+ <test14> </test14>
+
+</xpathproc>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/transform/template_ds.xml b/modules/enterprise/server/itests-2/src/test/resources/transform/template_ds.xml
new file mode 100644
index 0000000..5b35f56
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/transform/template_ds.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- DataSource configuration file created by JBoss Operations Network-->
+<datasources>
+<dummy/>
+</datasources>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/transform/transform.xsl b/modules/enterprise/server/itests-2/src/test/resources/transform/transform.xsl
new file mode 100644
index 0000000..fb9cc79
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/transform/transform.xsl
@@ -0,0 +1,514 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:str="http://exslt.org/strings"
+ extension-element-prefixes="str" >
+
+ <xsl:output
+ method="xml"
+ indent="yes"
+ encoding="UTF-8"
+ />
+
+ <!-- if a parameter is not passed in, then it will be set to the
+ value of the variable UNCHANGED -->
+ <xsl:variable name="UNCHANGED" select="'~UNCHANGED~'"/>
+
+ <xsl:param name="jndiName" select="$UNCHANGED"/>
+ <xsl:param name="userName" select="$UNCHANGED"/>
+ <xsl:param name="connectionProperty" select="$UNCHANGED"/>
+ <xsl:param name="XADataSourceProperty" select="$UNCHANGED"/>
+ <xsl:param name="connectionUrl" select="$UNCHANGED"/>
+ <xsl:param name="minPoolSize" select="$UNCHANGED"/>
+ <xsl:param name="maxPoolSize" select="$UNCHANGED"/>
+ <xsl:param name="transactionIsolation" select="$UNCHANGED"/>
+ <xsl:param name="validConnectionChecker" select="$UNCHANGED"/>
+ <xsl:param name="useJavaContext" select="$UNCHANGED"/>
+ <xsl:param name="domainAndApplicationSecurity" select="$UNCHANGED"/>
+ <xsl:param name="applicationManagedSecurity" select="$UNCHANGED"/>
+ <xsl:param name="securityDomain" select="$UNCHANGED"/>
+ <xsl:param name="newConnectionSQL" select="$UNCHANGED"/>
+ <xsl:param name="exceptionSorter" select="$UNCHANGED"/>
+ <xsl:param name="password" select="$UNCHANGED"/>
+ <xsl:param name="trackStatements" select="$UNCHANGED"/>
+ <xsl:param name="checkValidConnectionSQL" select="$UNCHANGED"/>
+ <xsl:param name="driverClass" select="$UNCHANGED"/>
+ <xsl:param name="XADataSourceClass" select="$UNCHANGED"/>
+ <xsl:param name="blockingTimeout" select="$UNCHANGED"/>
+ <xsl:param name="preparedStatementCacheSize" select="$UNCHANGED"/>
+ <xsl:param name="idleTimeout" select="$UNCHANGED"/>
+ <xsl:param name="noTxSeparatePools" select="$UNCHANGED"/>
+ <xsl:param name="isSameRMOverrideValue" select="$UNCHANGED"/>
+ <xsl:param name="trackConnectionByTx" select="$UNCHANGED"/>
+
+ <!-- supply defaults for testing -->
+ <xsl:param name="datasourceType">test-type</xsl:param>
+ <xsl:param name="nameValueSeparator">||</xsl:param>
+ <xsl:param name="elementSeparator">|^|</xsl:param>
+
+ <!-- TODO support multiple datasources inside a file -->
+
+ <xsl:template match="/datasources">
+ <datasources>
+ <xsl:apply-templates />
+ </datasources>
+ </xsl:template>
+
+
+ <xsl:template match="local-tx-datasource|xa-datasource|no-tx-datasource|dummy">
+ <xsl:element name="{$datasourceType}">
+
+ <!-- These should be ordered as specified in the DTD -->
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="jndi-name"/>
+ <xsl:with-param name="elementName" select="'jndi-name'"/>
+ <xsl:with-param name="parameterValue" select="$jndiName"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="connection-url"/>
+ <xsl:with-param name="elementName" select="'connection-url'"/>
+ <xsl:with-param name="parameterValue" select="$connectionUrl"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="min-pool-size"/>
+ <xsl:with-param name="elementName" select="'min-pool-size'"/>
+ <xsl:with-param name="parameterValue" select="$minPoolSize"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="max-pool-size"/>
+ <xsl:with-param name="elementName" select="'max-pool-size'"/>
+ <xsl:with-param name="parameterValue" select="$maxPoolSize"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="user-name"/>
+ <xsl:with-param name="elementName" select="'user-name'"/>
+ <xsl:with-param name="parameterValue" select="$userName"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="transaction-isolation"/>
+ <xsl:with-param name="elementName" select="'transaction-isolation'"/>
+ <xsl:with-param name="parameterValue" select="$transactionIsolation"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="valid-connection-checker-class-name"/>
+ <xsl:with-param name="elementName" select="'valid-connection-checker-class-name'"/>
+ <xsl:with-param name="parameterValue" select="$validConnectionChecker"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="use-java-context"/>
+ <xsl:with-param name="elementName" select="'use-java-context'"/>
+ <xsl:with-param name="parameterValue" select="$useJavaContext"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="security-domain-and-application"/>
+ <xsl:with-param name="elementName" select="'security-domain-and-application'"/>
+ <xsl:with-param name="parameterValue" select="$domainAndApplicationSecurity"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addEmptyElementIfSpecifiedTrueAndNotPresent">
+ <xsl:with-param name="element" select="application-managed-security"/>
+ <xsl:with-param name="elementName" select="'application-managed-security'"/>
+ <xsl:with-param name="parameterValue" select="$applicationManagedSecurity"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="security-domain"/>
+ <xsl:with-param name="elementName" select="'security-domain'"/>
+ <xsl:with-param name="parameterValue" select="$securityDomain"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="new-connection-sql"/>
+ <xsl:with-param name="elementName" select="'new-connection-sql'"/>
+ <xsl:with-param name="parameterValue" select="$newConnectionSQL"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="exception-sorter-class-name"/>
+ <xsl:with-param name="elementName" select="'exception-sorter-class-name'"/>
+ <xsl:with-param name="parameterValue" select="$exceptionSorter"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="password"/>
+ <xsl:with-param name="elementName" select="'password'"/>
+ <xsl:with-param name="parameterValue" select="$password"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="track-statements"/>
+ <xsl:with-param name="elementName" select="'track-statements'"/>
+ <xsl:with-param name="parameterValue" select="$trackStatements"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="check-valid-connection-sql"/>
+ <xsl:with-param name="elementName" select="'check-valid-connection-sql'"/>
+ <xsl:with-param name="parameterValue" select="$checkValidConnectionSQL"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="driver-class"/>
+ <xsl:with-param name="elementName" select="'driver-class'"/>
+ <xsl:with-param name="parameterValue" select="$driverClass"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="xa-datasource-class"/>
+ <xsl:with-param name="elementName" select="'xa-datasource-class'"/>
+ <xsl:with-param name="parameterValue" select="$XADataSourceClass"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="blocking-timeout-millis"/>
+ <xsl:with-param name="elementName" select="'blocking-timeout-millis'"/>
+ <xsl:with-param name="parameterValue" select="$blockingTimeout"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="prepared-statement-cache-size"/>
+ <xsl:with-param name="elementName" select="'prepared-statement-cache-size'"/>
+ <xsl:with-param name="parameterValue" select="$preparedStatementCacheSize"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="idle-timeout-minutes"/>
+ <xsl:with-param name="elementName" select="'idle-timeout-minutes'"/>
+ <xsl:with-param name="parameterValue" select="$idleTimeout"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="no-tx-separate-pools"/>
+ <xsl:with-param name="elementName" select="'no-tx-separate-pools'"/>
+ <xsl:with-param name="parameterValue" select="$noTxSeparatePools"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="isSameRM-override-value"/>
+ <xsl:with-param name="elementName" select="'isSameRM-override-value'"/>
+ <xsl:with-param name="parameterValue" select="$isSameRMOverrideValue"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:with-param name="element" select="track-connection-by-tx"/>
+ <xsl:with-param name="elementName" select="'track-connection-by-tx'"/>
+ <xsl:with-param name="parameterValue" select="$trackConnectionByTx"/>
+ </xsl:call-template>
+
+ <!-- don't attempt to add elements if this property hasn't changed -->
+ <xsl:if test="$connectionProperty != $UNCHANGED">
+ <xsl:variable name="currentConnectionProperties" select="connection-property" />
+ <xsl:for-each select="str:split($connectionProperty, $elementSeparator)">
+ <xsl:variable name="newNameAttribute" select="substring-before(., $nameValueSeparator)" />
+ <!-- if there isn't an existing connection-property element with the
+ specified name attribute then go ahead and add one
+ -->
+ <xsl:if test="not($currentConnectionProperties[@name = $newNameAttribute])">
+ <xsl:call-template name="outputPropertyTemplate">
+ <xsl:with-param name="nameAttribute" select="$newNameAttribute"/>
+ <xsl:with-param name="elementName" select="'connection-property'"/>
+ <xsl:with-param name="propertyParameter" select="$connectionProperty"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:if>
+
+ <!-- don't attempt to add elements if this property hasn't changed -->
+ <xsl:if test="$XADataSourceProperty != $UNCHANGED">
+ <xsl:variable name="currentXADataSourceProperties" select="xa-datasource-property" />
+ <xsl:for-each select="str:split($XADataSourceProperty, $elementSeparator)">
+ <xsl:variable name="newNameAttribute" select="substring-before(., $nameValueSeparator)" />
+ <!-- if there isn't an existing xa-datasource-property element with the
+ specified name attribute then go ahead and add one
+ -->
+ <xsl:if test="not($currentXADataSourceProperties[@name = $newNameAttribute])">
+ <xsl:call-template name="outputPropertyTemplate">
+ <xsl:with-param name="nameAttribute" select="$newNameAttribute"/>
+ <xsl:with-param name="elementName" select="'xa-datasource-property'"/>
+ <xsl:with-param name="propertyParameter" select="$XADataSourceProperty"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:if>
+
+ <xsl:apply-templates />
+
+ </xsl:element>
+ </xsl:template>
+
+
+ <xsl:template match="jndi-name">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$jndiName"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="user-name">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$userName"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="connection-url">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$connectionUrl"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="min-pool-size">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$minPoolSize"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="max-pool-size">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$maxPoolSize"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="transaction-isolation">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$transactionIsolation"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="valid-connection-checker-class-name">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$validConnectionChecker"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="use-java-context">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$useJavaContext"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="security-domain-and-application">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$domainAndApplicationSecurity"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="application-managed-security">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$applicationManagedSecurity"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="security-domain">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$securityDomain"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="new-connection-sql">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$newConnectionSQL"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="exception-sorter-class-name">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$exceptionSorter"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="password">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$password"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="track-statements">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$trackStatements"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="check-valid-connection-sql">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$checkValidConnectionSQL"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="driver-class">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$driverClass"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="xa-datasource-class">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$XADataSourceClass"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="blocking-timeout-millis">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$blockingTimeout"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="prepared-statement-cache-size">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$preparedStatementCacheSize"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="idle-timeout-minutes">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$idleTimeout"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="no-tx-separate-pools">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$noTxSeparatePools"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="isSameRM-override-value">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$isSameRMOverrideValue"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="track-connection-by-tx">
+ <xsl:call-template name="addElementIfSpecified">
+ <xsl:with-param name="parameterValue" select="$trackConnectionByTx"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="connection-property">
+ <xsl:call-template name="updatePropertyMapTemplate">
+ <xsl:with-param name="propertyParameter" select="$connectionProperty"/>
+ <xsl:with-param name="elementName" select="'connection-property'"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="xa-datasource-property">
+ <xsl:call-template name="updatePropertyMapTemplate">
+ <xsl:with-param name="propertyParameter" select="$XADataSourceProperty"/>
+ <xsl:with-param name="elementName" select="'xa-datasource-property'"/>
+ </xsl:call-template>
+ </xsl:template>
+
+
+ <!-- OUTPUT TEMPLATES -->
+
+ <!-- if this property is one we want to set, via the specified parameter,
+ then update it, i.e. output the new element, otherwise delete it, i.e. don't output anything.
+ If the parameter is unchanged then just output the original property unchanged
+ -->
+ <xsl:template name="updatePropertyMapTemplate">
+ <xsl:param name="propertyParameter"/>
+ <xsl:param name="elementName"/>
+ <xsl:choose>
+ <xsl:when test="$propertyParameter = $UNCHANGED">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:when>
+ <xsl:when test="contains($propertyParameter, concat(@name,$nameValueSeparator))">
+ <xsl:call-template name="outputPropertyTemplate">
+ <xsl:with-param name="nameAttribute" select="@name"/>
+ <xsl:with-param name="elementName" select="$elementName"/>
+ <xsl:with-param name="propertyParameter" select="$propertyParameter"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!-- otherwise don't output anything -->
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- add a new property element -->
+ <xsl:template name="outputPropertyTemplate">
+ <xsl:param name="nameAttribute"/>
+ <xsl:param name="elementName"/>
+ <xsl:param name="propertyParameter"/>
+ <xsl:element name="{$elementName}">
+ <xsl:attribute name="name">
+ <xsl:value-of select="$nameAttribute" />
+ </xsl:attribute>
+ <xsl:value-of select="substring-before(
+ substring-after($propertyParameter, concat($nameAttribute, $nameValueSeparator)),
+ $elementSeparator)"/>
+ </xsl:element>
+ </xsl:template>
+
+
+ <!-- if the specified 'element' is not present and the 'parameterValue' isn't
+ empty then output an element called 'elementName' with the value of
+ 'parameterValue' -->
+ <xsl:template name="addElementIfSpecifiedAndNotPresent">
+ <xsl:param name="element"/>
+ <xsl:param name="elementName"/>
+ <xsl:param name="parameterValue"/>
+ <xsl:if test="not($element) and $parameterValue and $parameterValue != $UNCHANGED">
+ <xsl:call-template name="outputElement">
+ <xsl:with-param name="elementName" select="$elementName"/>
+ <xsl:with-param name="elementValue" select="$parameterValue"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- this template exists to support generating empty elements.
+ The parameterValue must be set to 'true' for the corresponding
+ empty element to be created
+ -->
+ <xsl:template name="addEmptyElementIfSpecifiedTrueAndNotPresent">
+ <xsl:param name="element"/>
+ <xsl:param name="elementName"/>
+ <xsl:param name="parameterValue"/>
+ <xsl:if test="not($element) and $parameterValue = 'true'">
+ <xsl:call-template name="outputElement">
+ <xsl:with-param name="elementName" select="$elementName"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- if the parameter passed in hasn't been changed then output
+ the original elements, else if the parameter isn't empty then output
+ an element using it as the value -->
+ <xsl:template name="addElementIfSpecified">
+ <xsl:param name="parameterValue"/>
+ <xsl:choose>
+ <xsl:when test="$parameterValue = $UNCHANGED">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:when>
+ <xsl:when test="$parameterValue">
+ <xsl:call-template name="outputElement">
+ <xsl:with-param name="elementValue" select="$parameterValue"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!-- otherwise don't output anything -->
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- output an element with the specified name and value -->
+ <xsl:template name="outputElement">
+ <xsl:param name="elementName" select="name()"/>
+ <xsl:param name="elementValue"/>
+ <xsl:element name="{$elementName}">
+ <xsl:value-of select="$elementValue"/>
+ </xsl:element>
+ </xsl:template>
+
+
+ <!-- let everything we don't care about go through -->
+ <xsl:template match="@*|node()" >
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/validation/datasourceResources.properties b/modules/enterprise/server/itests-2/src/test/resources/validation/datasourceResources.properties
new file mode 100644
index 0000000..36464c4
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/validation/datasourceResources.properties
@@ -0,0 +1,142 @@
+# The error messages for the Validation Actions
+errors.required=The {0} field is required.
+errors.int=The {0} field should be an integer.
+errors.maxLength=The {0} fields is too long. Should only be {1} characters long.
+
+# The formatted names of the properties
+#datasource.jndiName.displayname=JNDI Name
+
+action.label.CreateDataSourceTemplate=Create a DataSource
+action.label.ReadDataSource=View this DataSource
+action.label.UpdateDataSource=Edit this DataSource
+action.label.CreateNoTxDataSource=Create No-Tx DataSource
+action.label.CreateLocalTxDataSource=Create Local-Tx DataSource
+action.label.CreateXADataSource=Create XA DataSource
+action.label.DeleteDataSource=Delete this DataSource
+action.label.CreateOracleLocalTxDataSource=Create Oracle Local-Tx DataSource
+action.label.CreateOracleXADataSource=Create Oracle XA DataSource
+action.label.CreateMySQLLocalTxDataSource=Create MySQL Local-Tx DataSource
+
+jndiName.label=JNDI Name
+jndiName.desc=The JNDI name under which the DataSource wrapper will be bound.
+
+connectionUrl.label=Connection URL
+connectionUrl.desc=The JDBC driver connection URL string
+
+driverClass.label=Driver Class
+driverClass.desc=The fully qualified name of the JDBC driver class.
+
+XADataSourceClass.label=XA DataSource Class
+XADataSourceClass.desc=The fully qualified name of the JDBC XA datasource class.
+
+userName.label=User Name
+userName.desc=The default username used when creating a new connection.
+
+password.label=Password
+password.desc=The default password used when creating a new connection.
+
+connectionProperty.label=Connection Properties
+connectionProperty.desc=Properties that will get passed in the DriverManager.getConnection(props) call. Look at your Driver docs to see what these might be. Each property should be on a separate line, with the name separated from the value by an equals sign (=).
+
+XADataSourceProperty.label=XA DataSource properties
+XADataSourceProperty.desc=Properties used to configure the XADataSource. Each property should be on a separate line, with the name separated from the value by an equals sign (=).
+
+minPoolSize.label=Minimum Pool Size
+minPoolSize.desc=Indicates the minimum number of connections a pool should hold. These are not created until a Subject is known from a request for a connection. If nothing is specified the default of 0 is used.
+
+maxPoolSize.label=Maximum Pool Size
+maxPoolSize.desc=Indicates the maximum number of connections for a pool. No more than this number of connections will be created in each sub-pool. If nothing is specified the default of 20 is used.
+
+
+# TODO need to consider adding action specification validation
+# so as to support the more complicated validation needed to check this stuff
+
+securityDomain.label=Security Domain
+securityDomain.desc=Indicates Subjects(from security domain) are used to distinguish connections in the pool. The content of the security domain is the name of the JAAS security manager that will handle authentication. This name correlates to the JAAS login-config.xml descriptor application-policy/name attribute. Must be specified if either Container Based or Container and Applicatin Based authentication types are specified.
+
+authenticationType.label=JCA Pool Type
+authenticationType.desc=JBossJCA uses a ManagedConnectionPool to perform the pooling. The ManagedConnectionPool is made up of subpools depending upon the strategy chosen and other pooling parameters. 'Container Based' means a pool per Subject, e.g. preconfigured or EJB/Web login subjects. 'Application Based' means use the connection properties from allocateConnection(). 'Container And Application Based' means a per Subject and connection property combination. The default is just to use a single pool of equivalent connections.
+authenticationType.options.label.0=Default
+authenticationType.options.label.1=Container Based
+authenticationType.options.label.2=Application Based
+authenticationType.options.label.3=Container and Application Based
+
+#applicationManagedSecurity.label=Application Managed Security
+#applicationManagedSecurity.desc=Application Managed Security
+
+#domainAndApplicationSecurity.label=Domain And Application Security
+#domainAndApplicationSecurity.desc=Domain And Application Security
+
+
+
+trackStatements.label=Track Statements
+trackStatements.desc=Whether to check for unclosed statements when a connection is returned to the pool and result sets are closed when a statement is closed/returned to the prepared statement cache. The default is Yes, but no warnings.
+trackStatements.options.label.0=Default
+trackStatements.options.label.1=No
+trackStatements.options.label.2=Yes
+trackStatements.options.label.3=Yes, but no warnings
+
+blockingTimeout.label=Blocking Timeout
+blockingTimeout.desc=Indicates the maximum time in milliseconds to block while waiting for a connection before throwing an exception. Note that this blocks only while waiting for a permit for a connection, and will never throw an exception if creating a new connection takes an inordinately long time. If nothing is specified the default of 30000 milliseconds is used.
+
+idleTimeout.label=Idle Timeout
+idleTimeout.desc=Indicates the maximum time in minutes a connection may be idle before being closed. The actual maximum time depends also on the IdleRemover scan time, which is 1/2 the smallest idle-timeout-minutes of any pool. If nothing is specified the default of 15 minutes is used.
+
+newConnectionSQL.label=New Connection SQL
+newConnectionSQL.desc=Specify an SQL statement to execute whenever a connection is added to the connection pool.
+
+checkValidConnectionSQL.label=Check Valid Connection SQL
+checkValidConnectionSQL.desc=Specify an SQL statement to check validity of a pool connection. This may be called when managed connection is taken from pool for use.
+
+validConnectionChecker.label=Valid Connection Checker
+validConnectionChecker.desc=An org.jboss.resource.adapter.jdbc.ValidConnectionChecker that provides a SQLException isValidConnection(Connection e) method to validate is a connection is valid. An exception means the connection is destroyed. This overrides the check-valid-connection-sql when present.
+
+exceptionSorter.label=Exception Sorter
+exceptionSorter.desc=An org.jboss.resource.adapter.jdbc.ExceptionSorter that provides a boolean isExceptionFatal(SQLException e) method to validate is an exception should be broadcast to all javax.resource.spi.ConnectionEventListener as a connectionErrorOccurred message.
+
+preparedStatementCacheSize.label=Prepared Statement Cache Size
+preparedStatementCacheSize.desc=The number of prepared statements per connection in an LRU cache.
+
+useJavaContext.label=Use Java Context
+useJavaContext.desc=Indicates if the JNDI name should be prefixed with java: which causes the DataSource to only be accessible from within the jboss server vm. The default is Yes.
+useJavaContext.options.label.0=Default
+useJavaContext.options.label.1=Yes
+useJavaContext.options.label.2=No
+
+transactionIsolation.label=Transaction Isolation
+transactionIsolation.desc=The Transaction Isolation level. The default setting is to use whichever isolation level is provided by default by the database.
+transactionIsolation.options.label.0=Default
+transactionIsolation.options.label.1=TRANSACTION NONE
+transactionIsolation.options.label.2=TRANSACTION READ COMMITTED
+transactionIsolation.options.label.3=TRANSACTION READ UNCOMMITTED
+transactionIsolation.options.label.4=TRANSACTION REPEATABLE READ
+transactionIsolation.options.label.5=TRANSACTION SERIALIZABLE
+
+noTxSeparatePools.label=No Tx Separate Pools
+noTxSeparatePools.desc=Whether to use separate pools for connections retrieved in a transaction and those retrieved outside a transaction. The default is Yes.
+noTxSeparatePools.options.label.0=Default
+noTxSeparatePools.options.label.1=Yes
+noTxSeparatePools.options.label.2=No
+
+
+trackConnectionByTx.label=Track Connection By Tx
+trackConnectionByTx.desc=Whether the connection should be "locked" to the transaction, returning it to the pool at the end of the transaction. The default is No.
+trackConnectionByTx.options.label.0=Default
+trackConnectionByTx.options.label.1=Yes
+trackConnectionByTx.options.label.2=No
+
+
+isSameRMOverrideValue.label=isSameRM Override Value
+isSameRMOverrideValue.desc=Allows one to unconditionally set whether the javax.transaction.xa.XAResource.isSameRM(XAResource) returns true or false. The default is not to override the return value.
+isSameRMOverrideValue.options.label.0=Default
+isSameRMOverrideValue.options.label.1=true
+isSameRMOverrideValue.options.label.2=false
+
+dataSourceTemplates.label=DataSource Templates
+dataSourceTemplates.desc=The DataSource types for which Create/Read templates are available
+dataSourceTemplates.options.label.0=Generic XA DataSource
+dataSourceTemplates.options.label.1=Generic Local Tx DataSource
+dataSourceTemplates.options.label.2=Generic No Tx DataSource
+dataSourceTemplates.options.label.3=MySQL Local Tx DataSource
+dataSourceTemplates.options.label.4=Oracle XA DataSource
+dataSourceTemplates.options.label.5=Oracle Local Tx DataSource
diff --git a/modules/enterprise/server/itests-2/src/test/resources/validation/datasource_validation.xml b/modules/enterprise/server/itests-2/src/test/resources/validation/datasource_validation.xml
new file mode 100644
index 0000000..3214c1a
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/validation/datasource_validation.xml
@@ -0,0 +1,159 @@
+<!DOCTYPE form-validation PUBLIC
+ "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN"
+ "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">
+
+<form-validation>
+
+ <formset>
+ <form name="SaveNoTxDataSource">
+ <field property="jndiName" depends="required">
+ <arg position="0" key="jndiName.label"/>
+ </field>
+ <field property="connectionUrl" depends="required">
+ <arg position="0" key="connectionUrl.label"/>
+ </field>
+ <field property="driverClass" depends="required">
+ <arg position="0" key="driverClass.label"/>
+ </field>
+ <field property="minPoolSize" depends="optionalInt">
+ <arg position="0" key="minPoolSize.label"/>
+ </field>
+ <field property="maxPoolSize" depends="optionalInt">
+ <arg position="0" key="maxPoolSize.label"/>
+ </field>
+ <field property="blockingTimeout" depends="optionalInt">
+ <arg position="0" key="blockingTimeout.label"/>
+ </field>
+ <field property="idleTimeout" depends="optionalInt">
+ <arg position="0" key="idleTimeout.label"/>
+ </field>
+ <field property="preparedStatementCacheSize" depends="optionalInt">
+ <arg position="0" key="preparedStatementCacheSize.label"/>
+ </field>
+ </form>
+ <form name="SaveLocalTxDataSource">
+ <field property="jndiName" depends="required">
+ <arg position="0" key="jndiName.label"/>
+ </field>
+ <field property="connectionUrl" depends="required">
+ <arg position="0" key="connectionUrl.label"/>
+ </field>
+ <field property="driverClass" depends="required">
+ <arg position="0" key="driverClass.label"/>
+ </field>
+ <field property="minPoolSize" depends="optionalInt">
+ <arg position="0" key="minPoolSize.label"/>
+ </field>
+ <field property="maxPoolSize" depends="optionalInt">
+ <arg position="0" key="maxPoolSize.label"/>
+ </field>
+ <field property="blockingTimeout" depends="optionalInt">
+ <arg position="0" key="blockingTimeout.label"/>
+ </field>
+ <field property="idleTimeout" depends="optionalInt">
+ <arg position="0" key="idleTimeout.label"/>
+ </field>
+ <field property="preparedStatementCacheSize" depends="optionalInt">
+ <arg position="0" key="preparedStatementCacheSize.label"/>
+ </field>
+ </form>
+ <form name="SaveXADataSource">
+ <field property="jndiName" depends="required">
+ <arg position="0" key="jndiName.label"/>
+ </field>
+ <field property="XADataSourceClass" depends="required">
+ <arg position="0" key="XADataSourceClass.label"/>
+ </field>
+ <field property="minPoolSize" depends="optionalInt">
+ <arg position="0" key="minPoolSize.label"/>
+ </field>
+ <field property="maxPoolSize" depends="optionalInt">
+ <arg position="0" key="maxPoolSize.label"/>
+ </field>
+ <field property="blockingTimeout" depends="optionalInt">
+ <arg position="0" key="blockingTimeout.label"/>
+ </field>
+ <field property="idleTimeout" depends="optionalInt">
+ <arg position="0" key="idleTimeout.label"/>
+ </field>
+ <field property="preparedStatementCacheSize" depends="optionalInt">
+ <arg position="0" key="preparedStatementCacheSize.label"/>
+ </field>
+ </form>
+ <form name="SaveNoTxDataSourceThenScan">
+ <field property="jndiName" depends="required">
+ <arg position="0" key="jndiName.label"/>
+ </field>
+ <field property="connectionUrl" depends="required">
+ <arg position="0" key="connectionUrl.label"/>
+ </field>
+ <field property="driverClass" depends="required">
+ <arg position="0" key="driverClass.label"/>
+ </field>
+ <field property="minPoolSize" depends="optionalInt">
+ <arg position="0" key="minPoolSize.label"/>
+ </field>
+ <field property="maxPoolSize" depends="optionalInt">
+ <arg position="0" key="maxPoolSize.label"/>
+ </field>
+ <field property="blockingTimeout" depends="optionalInt">
+ <arg position="0" key="blockingTimeout.label"/>
+ </field>
+ <field property="idleTimeout" depends="optionalInt">
+ <arg position="0" key="idleTimeout.label"/>
+ </field>
+ <field property="preparedStatementCacheSize" depends="optionalInt">
+ <arg position="0" key="preparedStatementCacheSize.label"/>
+ </field>
+ </form>
+ <form name="SaveLocalTxDataSourceThenScan">
+ <field property="jndiName" depends="required">
+ <arg position="0" key="jndiName.label"/>
+ </field>
+ <field property="connectionUrl" depends="required">
+ <arg position="0" key="connectionUrl.label"/>
+ </field>
+ <field property="driverClass" depends="required">
+ <arg position="0" key="driverClass.label"/>
+ </field>
+ <field property="minPoolSize" depends="optionalInt">
+ <arg position="0" key="minPoolSize.label"/>
+ </field>
+ <field property="maxPoolSize" depends="optionalInt">
+ <arg position="0" key="maxPoolSize.label"/>
+ </field>
+ <field property="blockingTimeout" depends="optionalInt">
+ <arg position="0" key="blockingTimeout.label"/>
+ </field>
+ <field property="idleTimeout" depends="optionalInt">
+ <arg position="0" key="idleTimeout.label"/>
+ </field>
+ <field property="preparedStatementCacheSize" depends="optionalInt">
+ <arg position="0" key="preparedStatementCacheSize.label"/>
+ </field>
+ </form>
+ <form name="SaveXADataSourceThenScan">
+ <field property="jndiName" depends="required">
+ <arg position="0" key="jndiName.label"/>
+ </field>
+ <field property="XADataSourceClass" depends="required">
+ <arg position="0" key="XADataSourceClass.label"/>
+ </field>
+ <field property="minPoolSize" depends="optionalInt">
+ <arg position="0" key="minPoolSize.label"/>
+ </field>
+ <field property="maxPoolSize" depends="optionalInt">
+ <arg position="0" key="maxPoolSize.label"/>
+ </field>
+ <field property="blockingTimeout" depends="optionalInt">
+ <arg position="0" key="blockingTimeout.label"/>
+ </field>
+ <field property="idleTimeout" depends="optionalInt">
+ <arg position="0" key="idleTimeout.label"/>
+ </field>
+ <field property="preparedStatementCacheSize" depends="optionalInt">
+ <arg position="0" key="preparedStatementCacheSize.label"/>
+ </field>
+ </form>
+ </formset>
+</form-validation>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/validation/default_validator_rules.xml b/modules/enterprise/server/itests-2/src/test/resources/validation/default_validator_rules.xml
new file mode 100644
index 0000000..9992659
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/validation/default_validator_rules.xml
@@ -0,0 +1,47 @@
+<!DOCTYPE form-validation PUBLIC
+ "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN"
+ "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">
+
+<form-validation>
+ <global>
+ <validator name="required"
+ classname="com.jboss.jbossnetwork.apl.validation.ActionArgumentsValidator"
+ method="validateRequired"
+ methodParams="java.lang.Object, org.apache.commons.validator.Field"
+ msg="errors.required"/>
+
+<!--
+ <validator name="maxLength"
+ classname="org.apache.commons.validator.GenericValidator"
+ method="maxLength"
+ methodParams="java.lang.String, int"
+ msg="errors.maxLength"/>
+-->
+ <validator name="optionalInt"
+ classname="com.jboss.jbossnetwork.apl.validation.ActionArgumentsValidator"
+ method="validateOptionalInt"
+ methodParams="java.lang.Object, org.apache.commons.validator.Field"
+ msg="errors.int"/>
+
+<!--
+ <validator name="int2"
+ classname="com.jboss.jbossnetwork.apl.validation.ActionArgumentsTypeValidator"
+ method="validateInt"
+ methodParams="java.lang.Object,org.apache.commons.validator.Field"
+ msg="errors.int"/>
+
+ THIS VALIDATOR STILL NEEDS MORE WORK TO BE REALLY USEFUL
+ <validator name="matchesTypeDefinition"
+ classname="com.jboss.jbossnetwork.apl.validation.ActionAttributeDefinitionValidator"
+ method="matchesTypeDefinition"
+ methodParams="java.lang.Object,org.apache.commons.validator.Field"
+ msg="errors.type"/>
+-->
+
+ <validator name="mapValue"
+ classname="com.jboss.jbossnetwork.apl.validation.ActionArgumentsValidator"
+ method="validateMapParameter"
+ methodParams="java.lang.Object, org.apache.commons.validator.Field"
+ msg="errors.mapValue"/>
+ </global>
+</form-validation>
\ No newline at end of file
diff --git a/modules/enterprise/server/itests-2/src/test/resources/velocity/local-datasource.vm b/modules/enterprise/server/itests-2/src/test/resources/velocity/local-datasource.vm
new file mode 100644
index 0000000..2f902a6
--- /dev/null
+++ b/modules/enterprise/server/itests-2/src/test/resources/velocity/local-datasource.vm
@@ -0,0 +1,8 @@
+This is a test DataSource
+
+#if ($jndi-name)
+<jndi-name>$jndi-name<jndi-name>
+#end
+#foreach( $key in $connection-properties.keySet() )
+<connection-property name="$key">$connection-properties.get($key)</connection-property>
+#end
diff --git a/modules/enterprise/server/itests/pom.xml b/modules/enterprise/server/itests/pom.xml
index 68425c80b..cda3b1a 100644
--- a/modules/enterprise/server/itests/pom.xml
+++ b/modules/enterprise/server/itests/pom.xml
@@ -22,7 +22,7 @@
<properties>
<rhq.server.datasource>java:/RHQDS</rhq.server.datasource>
<rhq.server.ds-mapping>PostgreSQL</rhq.server.ds-mapping>
- <jboss-embeddable-ejb3.version>1.0.0.Alpha9</jboss-embeddable-ejb3.version>
+ <!-- <jboss-embeddable-ejb3.version>1.0.0.Alpha9</jboss-embeddable-ejb3.version> -->
</properties>
<dependencies>
@@ -186,13 +186,15 @@
</exclusions>
</dependency>
+<!--
<dependency>
<groupId>jboss.jboss-embeddable-ejb3</groupId>
<artifactId>jboss-ejb3-all</artifactId>
<version>${jboss-embeddable-ejb3.version}</version>
<scope>test</scope>
</dependency>
-
+ -->
+
<!-- Shrinkwrap to build up test plugins etc. -->
<dependency>
<groupId>org.jboss.shrinkwrap</groupId>
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index 0eaa6d9..9d04c3e 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -26,14 +26,27 @@
</properties>
<dependencies>
-
+
<!-- Internal Deps -->
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-enterprise-comm</artifactId>
- <version>${project.version}</version>
- </dependency>
+ <!-- rhq-enterprise-comm pulls in the old version of jboss remoting. The old version of remoting
+ depends on jboss/jboss-common/1.2.1.GA/jboss-common-1.2.1.GA.jar, which includes on old
+ implementation of the org.jboss.logging package. Arquillian testing leverages AS7 modules
+ (xnio e.g.) that require the up to date logging impl. Since server jar depends on
+ rhq-enterprise-comm to run, and arquillian to test, place the current version jboss-logging
+ as a dependency before the rhq-comm dependency. This ensure the classpath is set up to use the
+ newer package impl. -->
+ <dependency>
+ <groupId>org.jboss.logging</groupId>
+ <artifactId>jboss-logging</artifactId>
+ <version>3.1.0.GA</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-comm</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.rhq</groupId>
@@ -108,6 +121,14 @@
<!-- Note, the test deps are intentionally placed above the other scoped deps because of classpath
reasons. Maven orders the [test] classpath in the order listed in the pom. -->
+
+
+ <dependency>
+ <groupId>org.jboss.as</groupId>
+ <artifactId>jboss-as-dist</artifactId>
+ <type>zip</type>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.jboss.spec</groupId>
@@ -160,20 +181,11 @@
<scope>test</scope>
</dependency>
-
-
- <dependency>
- <groupId>org.jboss.as</groupId>
- <artifactId>jboss-as-dist</artifactId>
- <type>zip</type>
- <scope>test</scope>
- </dependency>
-
<dependency>
<groupId>org.rhq</groupId>
<artifactId>test-utils</artifactId>
<version>${project.version}</version>
- <scope>test</scope>
+ <scope>test-compile</scope>
<exclusions>
<exclusion>
<groupId>org.testng</groupId>
@@ -181,7 +193,7 @@
</exclusion>
</exclusions>
</dependency>
-
+
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-domain</artifactId>
@@ -189,8 +201,8 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
-
- <dependency>
+
+ <dependency>
<groupId>${project.groupId}</groupId>
<artifactId>rhq-core-client-api</artifactId>
<version>${project.version}</version>
@@ -214,8 +226,9 @@
</exclusion>
</exclusions>
</dependency>
-
+
<!-- NOTE: The remaining test deps correspond to the classes contained in hibernate-all.jar and thirdparty-all.jar. -->
+<!--
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
@@ -249,7 +262,7 @@
<version>1.3</version>
<scope>test</scope>
</dependency>
-
+ -->
<!-- 3rd Party Deps -->
@@ -317,50 +330,58 @@
<version>1.1.4</version>
</dependency>
- <!-- required by RHQ server classes, as well as EJB3 Embedded -->
+ <!-- required by RHQ server classes, as well as EJB3 Embedded
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1-jboss</version>
<scope>provided</scope>
</dependency>
-
+-->
<dependency>
<groupId>gnu-getopt</groupId>
<artifactId>getopt</artifactId>
</dependency>
+
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<scope>provided</scope>
</dependency>
+ <!--
<dependency>
<groupId>i18nlog</groupId>
<artifactId>i18nlog</artifactId>
</dependency>
-
+ -->
+<!--
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>${javax.mail.api.version}</version>
- <scope>provided</scope> <!-- by JBossAS -->
+ <scope>provided</scope>
</dependency>
-
+ -->
+<!--
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
- <scope>provided</scope> <!-- by JBossAS -->
+ <scope>provided</scope>
</dependency>
-
+ -->
+
+ <!--
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
- <scope>provided</scope> <!-- by JBossAS -->
+ <scope>provided</scope>
</dependency>
+ -->
+
<dependency>
<groupId>jboss</groupId>
@@ -368,20 +389,21 @@
<scope>compile</scope>
</dependency>
+
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jboss-common-core</artifactId>
- <scope>provided</scope> <!-- by JBossAS -->
+ <scope>provided</scope>
</dependency>
- <!-- JBoss annotations like @TransactionTimeout -->
+ <!-- JBoss annotations like @TransactionTimeout -->
<dependency>
<groupId>org.jboss.ejb3</groupId>
<artifactId>jboss-ejb3-ext-api</artifactId>
- <version>2.0.0</version>
<scope>provided</scope>
</dependency>
-
+
+
<!-- annotations like @ExcludeDefaultInterceptors -->
<dependency>
<groupId>org.jboss.spec.javax.interceptor</groupId>
@@ -421,30 +443,34 @@
<scope>provided</scope>
</dependency>
- <!-- TODO: find out the AS7 equivalent -->
+ <!-- TODO: find out the AS7 equivalent
<dependency>
<groupId>jboss</groupId>
<artifactId>jboss-jmx</artifactId>
</dependency>
+ -->
- <!-- TODO: find out the AS7 equivalent -->
+ <!-- TODO: find out the AS7 equivalent
<dependency>
<groupId>jboss</groupId>
<artifactId>jboss-system</artifactId>
</dependency>
+ -->
- <!-- TODO: find out the AS7 equivalent -->
+ <!-- TODO: find out the AS7 equivalent
<dependency>
<groupId>jboss</groupId>
<artifactId>jbosssx</artifactId>
</dependency>
-
+ -->
+ <!--
<dependency>
<groupId>jboss</groupId>
<artifactId>jbpm</artifactId>
<version>3.1.1</version>
</dependency>
-
+ -->
+
<dependency>
<groupId>org.jboss.jbossts</groupId>
<artifactId>jbossjts</artifactId>
@@ -452,12 +478,14 @@
<scope>provided</scope>
</dependency>
- <!-- TODO: remove this - tests should all be moved under the test source tree -->
+
+ <!-- TODO: remove this - tests should all be moved under the test source tree
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
</dependency>
+ -->
<dependency>
<groupId>org.opensymphony.quartz</groupId>
@@ -572,12 +600,16 @@
<artifactId>snakeyaml</artifactId>
<version>1.8</version>
</dependency>
- <dependency>
+
+ <!--
+ <dependency>
<groupId>org.jboss.el</groupId>
<artifactId>jboss-el</artifactId>
<version>2.0.1.GA</version>
<scope>provided</scope>
</dependency>
+ -->
+
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
index b090c99..a38c069 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
@@ -207,11 +207,6 @@ import org.rhq.enterprise.server.test.TestLocal;
* @author Ian Springer
*/
public final class LookupUtil {
- private static boolean embeddedDeployment;
-
- static {
- embeddedDeployment = Boolean.valueOf(System.getProperty("embeddedDeployment", "false"));
- }
/**
* Prevent instantiation.
@@ -246,9 +241,6 @@ public final class LookupUtil {
try {
InitialContext context = new InitialContext();
String jndi = RHQConstants.TRANSACTION_MANAGER_JNDI_NAME;
- if (embeddedDeployment) {
- jndi = "java:/TransactionManager";
- }
TransactionManager tm = (TransactionManager) context.lookup(jndi);
context.close();
return tm;
@@ -644,7 +636,7 @@ public final class LookupUtil {
// Private Methods
private static String getLocalJNDIName(String beanName, String interfaceName) {
- return (embeddedDeployment ? "" : ("java:global/rhq/rhq-enterprise-server-ejb3/")) + beanName + "!" + interfaceName;
+ return "java:global/rhq/rhq-enterprise-server-ejb3/" + beanName + "!" + interfaceName;
}
private static <T> String getLocalJNDIName(@NotNull Class<? super T> beanClass) {
@@ -660,8 +652,8 @@ public final class LookupUtil {
*/
private static <T> String getRemoteJNDIName(@NotNull
Class<? super T> beanClass) {
- return (embeddedDeployment ? "" : ("java:global/rhq/rhq-enterprise-server-ejb3/")) + beanClass.getSimpleName()
- + "!" + beanClass.getName().replace("Bean", "Remote");
+ return ("java:global/rhq/rhq-enterprise-server-ejb3/" + beanClass.getSimpleName() + "!" + beanClass.getName()
+ .replace("Bean", "Remote"));
}
@SuppressWarnings("unchecked")
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
index a98c6de..f1ad06a 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
@@ -27,8 +27,6 @@ import java.util.Set;
import javax.persistence.EntityManager;
import org.apache.commons.lang.RandomStringUtils;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.rhq.core.domain.auth.Subject;
@@ -42,11 +40,11 @@ import org.rhq.core.domain.content.RepoRepoRelationship;
import org.rhq.core.domain.criteria.RepoCriteria;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
import org.rhq.enterprise.server.content.RepoException;
import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.content.metadata.ContentSourceMetadataManagerLocal;
-import org.rhq.enterprise.server.plugin.pc.content.TestContentServerPluginService;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -54,29 +52,37 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
private final static boolean ENABLED = true;
- private RepoManagerLocal repoManager;
- private ContentSourceManagerLocal contentSourceManager;
- private ContentSourceMetadataManagerLocal contentSourceMetadataManager;
+ //@Inject
+ protected RepoManagerLocal repoManager;
+
+ //@Inject
+ protected ContentSourceManagerLocal contentSourceManager;
+
+ //@Inject
+ protected ContentSourceMetadataManagerLocal contentSourceMetadataManager;
private Subject overlord;
- @BeforeMethod
- public void setupBeforeMethod() throws Exception {
+ //@Inject
+ protected SubjectManagerLocal subjectManager;
+
+ @Override
+ public void beforeMethod() throws Exception {
overlord = LookupUtil.getSubjectManager().getOverlord();
+ //overlord = subjectManager.getOverlord();
prepareScheduler();
repoManager = LookupUtil.getRepoManagerLocal();
contentSourceManager = LookupUtil.getContentSourceManager();
contentSourceMetadataManager = LookupUtil.getContentSourceMetadataManager();
- TestContentServerPluginService pluginService = new TestContentServerPluginService(this);
+ //TestContentServerPluginService pluginService = new TestContentServerPluginService(this);
getTransactionManager().begin();
-
}
- @AfterMethod
- public void tearDownAfterMethod() throws Exception {
+ @Override
+ public void afterMethod() throws Exception {
unprepareServerPluginService();
unprepareScheduler();
getTransactionManager().rollback();
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
index 4ae4692..c6977f2 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
@@ -62,11 +62,11 @@ public abstract class AbstractEJB3Test extends Arquillian {
@ArquillianResource
protected InitialContext initialContext;
- // We originally deployed the domain jar as a JavaArchive (JAR file). But this ran into problems because
+ // We originally deployed the jar as a JavaArchive (JAR file). But this ran into problems because
// of the dependent 3rd party jars. There isn't an obvious way to deploy the dependent jars of a jar.
// Also, AS7 makes it hard to put them in a globally accessibly /lib directory due to
// its classloader isolation and module approach. So, we now deploy an EnterpriseArchive (ear)
- // where the domain jar is deployed as a module and the 3rd party libraries are put in the ear's /lib.
+ // where the ejb jar is deployed as a module and the 3rd party libraries are put in the ear's /lib.
@Deployment
protected static EnterpriseArchive getBaseDeployment() {
@@ -85,30 +85,32 @@ public abstract class AbstractEJB3Test extends Arquillian {
dataSourceXml = "jbossas-oracle-ds.xml";
}
- // Create the domain jar which will subsequently be packaged in the ear deployment
- JavaArchive ejbJar = ShrinkWrap.create(JavaArchive.class, "rhq-core-domain-ejb3.jar") //
+ // Create the ejb jar which will subsequently be packaged in the ear deployment
+ JavaArchive ejbJar = ShrinkWrap.create(JavaArchive.class, "rhq-enterprise-server-ejb3.jar") //
.addAsManifestResource(dataSourceXml) // the datasource
.addAsManifestResource("ejb-jar.xml") // the empty ejb jar descriptor
.addAsManifestResource("test-persistence.xml", "persistence.xml") // the test persistence context
.addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml") // add CDI injection (needed by arquillian injection)
);
- // non-domain RHQ classes in use by domain test classes
+ // non-server-jar RHQ classes in use by server jar test classes
ejbJar.addClass(ThrowableUtil.class) //
.addClass(MessageDigestGenerator.class) //
.addClass(StreamUtil.class) //
.addClass(AssertUtils.class) //
.addClasses(PropertyMatcher.class, MatchResult.class, PropertyMatchException.class);
- // domain classes
+ // server jar classes
ejbJar = addClasses(ejbJar, new File("target/classes/org"), null);
+ // System.out.println("** The Deployment EJB JAR: " + ejbJar.toString(true) + "\n");
+
JavaArchive testClassesJar = ShrinkWrap.create(JavaArchive.class, "test-classes.jar");
testClassesJar = addClasses(testClassesJar, new File("target/test-classes/org"), null);
// create test ear
- EnterpriseArchive ear = ShrinkWrap.create(EnterpriseArchive.class, "test-domain.ear") //
- .addAsModule(ejbJar) // the domain jar under test
+ EnterpriseArchive ear = ShrinkWrap.create(EnterpriseArchive.class, "test-server.ear") //
+ .addAsModule(ejbJar) // the jar under test
.addAsLibrary(testClassesJar) // the actual test classes
.setApplicationXML("application.xml"); // the application xml declaring the ejb jar
@@ -136,16 +138,18 @@ public abstract class AbstractEJB3Test extends Arquillian {
MavenDependencyResolver resolver = DependencyResolvers.use(MavenDependencyResolver.class);
resolver.loadMetadataFromPom("pom.xml");
Collection<JavaArchive> dependencies = new HashSet<JavaArchive>();
- dependencies
- .addAll(resolver.artifact("commons-beanutils:commons-beanutils:1.8.2").resolveAs(JavaArchive.class));
- dependencies.addAll(resolver.artifact("commons-codec:commons-codec").resolveAs(JavaArchive.class));
- dependencies.addAll(resolver.artifact("commons-io:commons-io").resolveAs(JavaArchive.class));
- dependencies.addAll(resolver.artifact("org.unitils:unitils-testng:3.1").resolveAs(JavaArchive.class));
+ //dependencies
+ // .addAll(resolver.artifact("commons-beanutils:commons-beanutils:1.8.2").resolveAs(JavaArchive.class));
+ //dependencies.addAll(resolver.artifact("commons-codec:commons-codec").resolveAs(JavaArchive.class));
+ //dependencies.addAll(resolver.artifact("commons-io:commons-io").resolveAs(JavaArchive.class));
+ //dependencies.addAll(resolver.artifact("org.unitils:unitils-testng:3.1").resolveAs(JavaArchive.class));
+ //dependencies.addAll(resolver.artifact("org.rhq:rhq-core-domain").resolveAs(JavaArchive.class));
String[] excludeFilters = { "testng.*jdk" };
dependencies = exclude(dependencies, excludeFilters);
ear = ear.addAsLibraries(dependencies);
+ ear.addAsModule((resolver.artifact("org.rhq:rhq-core-domain").resolveAsFiles())[0], "rhq-core-domain-ejb3.jar");
System.out.println("** The Deployment EAR: " + ear.toString(true) + "\n");
@@ -207,8 +211,8 @@ public abstract class AbstractEJB3Test extends Arquillian {
} else if (fileName.endsWith(".class")) {
int dot = fileName.indexOf('.');
try {
- Class<?> clazz = Class.forName(packageName + "." + fileName.substring(0, dot));
- archive.addClasses(clazz);
+ //Class<?> clazz = Class.forName(packageName + "." + fileName.substring(0, dot));
+ archive.addClass(packageName + "." + fileName.substring(0, dot));
} catch (Exception e) {
System.out.println("WARN: Could not add class:" + e);
}
diff --git a/modules/enterprise/server/jar/src/test/resources/application.xml b/modules/enterprise/server/jar/src/test/resources/application.xml
new file mode 100644
index 0000000..5a1bc82
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/resources/application.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/application_1_4.xsd" version="1.4">
+ <description>RHQ enterprise server test EAR</description>
+ <display-name>RHQ</display-name>
+ <module>
+ <ejb>rhq-enterprise-server-ejb3.jar</ejb>
+ </module>
+ <module>
+ <ejb>rhq-core-domain-ejb3.jar</ejb>
+ </module>
+</application>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/resources/arquillian.xml b/modules/enterprise/server/jar/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..66f737a
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/resources/arquillian.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<arquillian
+ xmlns="http://jboss.org/schema/arquillian"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://jboss.org/schema/arquillian
+ http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
+
+ <!-- Change from using the default JMX protocol due to https://issues.jboss.org/browse/AS7-1696 -->
+ <defaultProtocol type="Servlet 3.0" />
+
+ <container
+ qualifier="RHQAS7"
+ default="true">
+
+ <configuration>
+ <property name="jbossHome">${jboss.unzip.location}</property>
+ </configuration>
+ </container>
+</arquillian>
diff --git a/modules/enterprise/server/jar/src/test/resources/ejb-jar.xml b/modules/enterprise/server/jar/src/test/resources/ejb-jar.xml
new file mode 100644
index 0000000..b3deb45
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/resources/ejb-jar.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
+ version="3.1">
+
+ <description>RHQ</description>
+ <display-name>RHQ</display-name>
+
+ <interceptors>
+ <interceptor>
+ <interceptor-class>org.rhq.enterprise.server.authz.RequiredPermissionsInterceptor</interceptor-class>
+ </interceptor>
+ <interceptor>
+ <interceptor-class>org.rhq.enterprise.server.common.TransactionInterruptInterceptor</interceptor-class>
+ </interceptor>
+ <interceptor>
+ <interceptor-class>org.rhq.enterprise.server.common.PerformanceMonitorInterceptor</interceptor-class>
+ </interceptor>
+ </interceptors>
+
+ <assembly-descriptor>
+
+ <!-- all our EJB3 SLSBs can define custom @RequiredPermissions annotations for authorization checks-->
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+ <interceptor-class>org.rhq.enterprise.server.authz.RequiredPermissionsInterceptor</interceptor-class>
+ </interceptor-binding>
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+ <interceptor-class>org.rhq.enterprise.server.common.TransactionInterruptInterceptor</interceptor-class>
+ </interceptor-binding>
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+ <interceptor-class>org.rhq.enterprise.server.common.PerformanceMonitorInterceptor</interceptor-class>
+ </interceptor-binding>
+
+ </assembly-descriptor>
+
+</ejb-jar>
diff --git a/modules/enterprise/server/jar/src/test/resources/embedded-jboss-beans.xml b/modules/enterprise/server/jar/src/test/resources/embedded-jboss-beans.xml
deleted file mode 100644
index 85e2fb3..0000000
--- a/modules/enterprise/server/jar/src/test/resources/embedded-jboss-beans.xml
+++ /dev/null
@@ -1,168 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
- xmlns="urn:jboss:bean-deployer:2.0">
-
- <!-- This installs a custom initial context factory builder into the JVM
- that will ensure that all the default InitialContexts are going to check
- for the permission to access the RHQ internals. -->
- <bean class="org.rhq.jndi.mbean.AccessCheckingInitialContextFactoryBuilderInstaller"
- name="AccessCheckingInitialContextFactoryBuilderInstaller">
- </bean>
-
-
- <bean name="Naming" class="org.jnp.server.SingletonNamingServer"/>
-
- <bean name="InitialContextProperties" class="java.util.Hashtable">
- <constructor>
- <parameter class="java.util.Map">
- <map keyClass="java.lang.String" valueClass="java.lang.String">
- <entry>
- <key>java.naming.factory.initial</key>
- <value>org.jnp.interfaces.LocalOnlyContextFactory</value>
- </entry>
- <entry>
- <key>java.naming.factory.url.pkgs</key>
- <value>org.jboss.naming:org.jnp.interfaces</value>
- </entry>
- </map>
- </parameter>
- </constructor>
- </bean>
-
- <bean name="java:comp/Initializer" class="org.jboss.ejb3.embedded.JavaCompInitializer">
- <property name="jndiProperties">
- <inject bean="InitialContextProperties"/>
- </property>
- </bean>
-
- <bean name="XidFactory" class="org.jboss.tm.XidFactoryImpl"/>
-
- <bean name="XidFactoryMBean" class="org.jboss.ejb3.embedded.XidFactoryMBean">
- <constructor>
- <parameter class="org.jboss.tm.XidFactoryBase">
- <inject bean="XidFactory"/>
- </parameter>
- </constructor>
- </bean>
-
- <bean name="TransactionManagerInitializer" class="org.jboss.tm.TransactionManagerInitializer">
- <property name="xidFactory">
- <inject bean="XidFactory"/>
- </property>
- <property name="initialContextProperties">
- <inject bean="InitialContextProperties"/>
- </property>
- </bean>
-
- <bean name="UserTransaction" class="org.jboss.ejb3.embedded.UserTransactionImpl">
- <demand>TransactionManagerInitializer</demand>
- </bean>
-
- <bean name="UserTransactionBinding" class="org.jboss.ejb3.embedded.JndiBinder">
- <property name="jndiProperties">
- <inject bean="InitialContextProperties"/>
- </property>
- <property name="target">
- <inject bean="UserTransaction"/>
- </property>
- <property name="bindTo">UserTransaction</property>
- <property name="serializable">false</property>
- </bean>
-
-
- <bean name="TransactionManager" class="java.lang.Object">
- <constructor factoryMethod="getTransactionManager">
- <factory bean="TransactionManagerInitializer"/>
- </constructor>
- </bean>
- <bean name="CachedConnectionManager" class="org.jboss.resource.connectionmanager.CachedConnectionManagerReference">
- <property name="transactionManager">
- <inject bean="TransactionManager"/>
- </property>
- </bean>
-
- <bean name="RHQDSBootstrap" class="org.jboss.resource.adapter.jdbc.local.LocalTxDataSource">
- <property name="driverClass">${rhq.test.ds.driver-class}</property>
- <property name="connectionURL">${rhq.test.ds.connection-url}</property>
- <property name="userName">${rhq.test.ds.user-name}</property>
- <property name="password">${rhq.test.ds.password}</property>
- <property name="jndiName">java:/RHQDS</property>
- <property name="minSize">0</property>
- <property name="maxSize">20</property>
- <property name="blockingTimeout">3000</property>
- <property name="idleTimeout">100000</property>
- <property name="transactionManager">
- <inject bean="TransactionManager"/>
- </property>
- <property name="cachedConnectionManager">
- <inject bean="CachedConnectionManager"/>
- </property>
- <property name="initialContextProperties">
- <inject bean="InitialContextProperties"/>
- </property>
- </bean>
-
- <bean name="RHQDS" class="java.lang.Object">
- <constructor factoryMethod="getDatasource">
- <factory bean="RHQDSBootstrap"/>
- </constructor>
- </bean>
-
- <!-- needed for Quartz' no-TX data source (even though this is a local-tx, seems like Quartz is still working) -->
- <bean name="NoTxRHQDSBootstrap" class="org.jboss.resource.adapter.jdbc.local.LocalTxDataSource">
- <property name="driverClass">${rhq.test.ds.driver-class}</property>
- <property name="connectionURL">${rhq.test.ds.connection-url}</property>
- <property name="userName">${rhq.test.ds.user-name}</property>
- <property name="password">${rhq.test.ds.password}</property>
- <property name="jndiName">java:/NoTxRHQDS</property>
- <property name="minSize">0</property>
- <property name="maxSize">10</property>
- <property name="blockingTimeout">1000</property>
- <property name="idleTimeout">100000</property>
- <property name="transactionManager">
- <inject bean="TransactionManager"/>
- </property>
- <property name="cachedConnectionManager">
- <inject bean="CachedConnectionManager"/>
- </property>
- <property name="initialContextProperties">
- <inject bean="InitialContextProperties"/>
- </property>
- </bean>
-
- <bean name="NoTxRHQDS" class="java.lang.Object">
- <constructor factoryMethod="getDatasource">
- <factory bean="NoTxRHQDSBootstrap"/>
- </constructor>
- </bean>
-
- <bean name="DefaultDSBootstrap" class="org.jboss.resource.adapter.jdbc.local.LocalTxDataSource">
- <property name="driverClass">org.hsqldb.jdbcDriver</property>
- <property name="connectionURL">jdbc:hsqldb:.</property>
- <!-- <property name="connectionURL">jdbc:hsqldb:./hypersonic/localDB</property> -->
- <property name="userName">sa</property>
- <property name="jndiName">java:/DefaultDS</property>
- <property name="minSize">0</property>
- <property name="maxSize">10</property>
- <property name="blockingTimeout">1000</property>
- <property name="idleTimeout">100000</property>
- <property name="transactionManager">
- <inject bean="TransactionManager"/>
- </property>
- <property name="cachedConnectionManager">
- <inject bean="CachedConnectionManager"/>
- </property>
- <property name="initialContextProperties">
- <inject bean="InitialContextProperties"/>
- </property>
- </bean>
-
- <bean name="DefaultDS" class="java.lang.Object">
- <constructor factoryMethod="getDatasource">
- <factory bean="DefaultDSBootstrap"/>
- </constructor>
- </bean>
-
-</deployment>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/resources/jbossas-oracle-ds.xml b/modules/enterprise/server/jar/src/test/resources/jbossas-oracle-ds.xml
new file mode 100644
index 0000000..8906dca
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/resources/jbossas-oracle-ds.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<datasources xmlns="http://www.jboss.org/ironjacamar/schema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.jboss.org/ironjacamar/schema http://docs.jboss.org/ironjacamar/schema/datasources_1_0.xsd">
+
+ <xa-datasource jndi-name="java:jboss/datasources/RHQDS" pool-name="RHQDS" enabled="true" use-java-context="true">
+
+ <xa-datasource-property name="URL">${rhq.test.ds.connection-url}</xa-datasource-property>
+ <xa-datasource-property name="ConnectionProperties">SetBigStringTryClob=true</xa-datasource-property>
+ <driver>oracle</driver>
+ <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
+ <xa-pool>
+ <min-pool-size>5</min-pool-size>
+ <max-pool-size>50</max-pool-size>
+ <is-same-rm-override>false</is-same-rm-override>
+ <no-tx-separate-pools />
+ </xa-pool>
+ <security>
+ <security-domain>RHQDSSecurityDomain</security-domain>
+ </security>
+ <validation>
+ <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker" />
+ <stale-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleStaleConnectionChecker" />
+ <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter" />
+ </validation>
+ <timeout>
+ <blocking-timeout-millis>30000</blocking-timeout-millis>
+ <idle-timeout-minutes>15</idle-timeout-minutes>
+ </timeout>
+ <statement>
+ <prepared-statement-cache-size>75</prepared-statement-cache-size>
+ </statement>
+ </xa-datasource>
+
+</datasources>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/resources/jbossas-postgres-ds.xml b/modules/enterprise/server/jar/src/test/resources/jbossas-postgres-ds.xml
new file mode 100644
index 0000000..23db62c
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/resources/jbossas-postgres-ds.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<datasources
+ xmlns="http://www.jboss.org/ironjacamar/schema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.jboss.org/ironjacamar/schema
+ http://docs.jboss.org/ironjacamar/schema/datasources_1_0.xsd">
+
+ <xa-datasource
+ jndi-name="java:jboss/datasources/RHQDS"
+ pool-name="RHQDS"
+ enabled="true"
+ use-java-context="true">
+
+ <xa-datasource-property name="DatabaseName">${rhq.test.ds.db-name}</xa-datasource-property>
+ <xa-datasource-property name="PortNumber">${rhq.test.ds.port}</xa-datasource-property>
+ <xa-datasource-property name="ServerName">${rhq.test.ds.server-name}</xa-datasource-property>
+ <driver>postgres</driver>
+ <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
+ <xa-pool>
+ <min-pool-size>5</min-pool-size>
+ <max-pool-size>50</max-pool-size>
+ </xa-pool>
+ <security>
+ <security-domain>RHQDSSecurityDomain</security-domain>
+ </security>
+ <validation>
+ <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker" />
+ <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter" />
+ </validation>
+ <timeout>
+ <blocking-timeout-millis>30000</blocking-timeout-millis>
+ <idle-timeout-minutes>15</idle-timeout-minutes>
+ </timeout>
+ <statement>
+ <prepared-statement-cache-size>75</prepared-statement-cache-size>
+ </statement>
+ </xa-datasource>
+
+</datasources>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/resources/jndi.properties b/modules/enterprise/server/jar/src/test/resources/jndi.properties
deleted file mode 100644
index 9225cef..0000000
--- a/modules/enterprise/server/jar/src/test/resources/jndi.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-java.naming.factory.initial=org.jnp.interfaces.LocalOnlyContextFactory
-java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/resources/obsolete/embedded-jboss-beans.xml b/modules/enterprise/server/jar/src/test/resources/obsolete/embedded-jboss-beans.xml
new file mode 100644
index 0000000..85e2fb3
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/resources/obsolete/embedded-jboss-beans.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
+ xmlns="urn:jboss:bean-deployer:2.0">
+
+ <!-- This installs a custom initial context factory builder into the JVM
+ that will ensure that all the default InitialContexts are going to check
+ for the permission to access the RHQ internals. -->
+ <bean class="org.rhq.jndi.mbean.AccessCheckingInitialContextFactoryBuilderInstaller"
+ name="AccessCheckingInitialContextFactoryBuilderInstaller">
+ </bean>
+
+
+ <bean name="Naming" class="org.jnp.server.SingletonNamingServer"/>
+
+ <bean name="InitialContextProperties" class="java.util.Hashtable">
+ <constructor>
+ <parameter class="java.util.Map">
+ <map keyClass="java.lang.String" valueClass="java.lang.String">
+ <entry>
+ <key>java.naming.factory.initial</key>
+ <value>org.jnp.interfaces.LocalOnlyContextFactory</value>
+ </entry>
+ <entry>
+ <key>java.naming.factory.url.pkgs</key>
+ <value>org.jboss.naming:org.jnp.interfaces</value>
+ </entry>
+ </map>
+ </parameter>
+ </constructor>
+ </bean>
+
+ <bean name="java:comp/Initializer" class="org.jboss.ejb3.embedded.JavaCompInitializer">
+ <property name="jndiProperties">
+ <inject bean="InitialContextProperties"/>
+ </property>
+ </bean>
+
+ <bean name="XidFactory" class="org.jboss.tm.XidFactoryImpl"/>
+
+ <bean name="XidFactoryMBean" class="org.jboss.ejb3.embedded.XidFactoryMBean">
+ <constructor>
+ <parameter class="org.jboss.tm.XidFactoryBase">
+ <inject bean="XidFactory"/>
+ </parameter>
+ </constructor>
+ </bean>
+
+ <bean name="TransactionManagerInitializer" class="org.jboss.tm.TransactionManagerInitializer">
+ <property name="xidFactory">
+ <inject bean="XidFactory"/>
+ </property>
+ <property name="initialContextProperties">
+ <inject bean="InitialContextProperties"/>
+ </property>
+ </bean>
+
+ <bean name="UserTransaction" class="org.jboss.ejb3.embedded.UserTransactionImpl">
+ <demand>TransactionManagerInitializer</demand>
+ </bean>
+
+ <bean name="UserTransactionBinding" class="org.jboss.ejb3.embedded.JndiBinder">
+ <property name="jndiProperties">
+ <inject bean="InitialContextProperties"/>
+ </property>
+ <property name="target">
+ <inject bean="UserTransaction"/>
+ </property>
+ <property name="bindTo">UserTransaction</property>
+ <property name="serializable">false</property>
+ </bean>
+
+
+ <bean name="TransactionManager" class="java.lang.Object">
+ <constructor factoryMethod="getTransactionManager">
+ <factory bean="TransactionManagerInitializer"/>
+ </constructor>
+ </bean>
+ <bean name="CachedConnectionManager" class="org.jboss.resource.connectionmanager.CachedConnectionManagerReference">
+ <property name="transactionManager">
+ <inject bean="TransactionManager"/>
+ </property>
+ </bean>
+
+ <bean name="RHQDSBootstrap" class="org.jboss.resource.adapter.jdbc.local.LocalTxDataSource">
+ <property name="driverClass">${rhq.test.ds.driver-class}</property>
+ <property name="connectionURL">${rhq.test.ds.connection-url}</property>
+ <property name="userName">${rhq.test.ds.user-name}</property>
+ <property name="password">${rhq.test.ds.password}</property>
+ <property name="jndiName">java:/RHQDS</property>
+ <property name="minSize">0</property>
+ <property name="maxSize">20</property>
+ <property name="blockingTimeout">3000</property>
+ <property name="idleTimeout">100000</property>
+ <property name="transactionManager">
+ <inject bean="TransactionManager"/>
+ </property>
+ <property name="cachedConnectionManager">
+ <inject bean="CachedConnectionManager"/>
+ </property>
+ <property name="initialContextProperties">
+ <inject bean="InitialContextProperties"/>
+ </property>
+ </bean>
+
+ <bean name="RHQDS" class="java.lang.Object">
+ <constructor factoryMethod="getDatasource">
+ <factory bean="RHQDSBootstrap"/>
+ </constructor>
+ </bean>
+
+ <!-- needed for Quartz' no-TX data source (even though this is a local-tx, seems like Quartz is still working) -->
+ <bean name="NoTxRHQDSBootstrap" class="org.jboss.resource.adapter.jdbc.local.LocalTxDataSource">
+ <property name="driverClass">${rhq.test.ds.driver-class}</property>
+ <property name="connectionURL">${rhq.test.ds.connection-url}</property>
+ <property name="userName">${rhq.test.ds.user-name}</property>
+ <property name="password">${rhq.test.ds.password}</property>
+ <property name="jndiName">java:/NoTxRHQDS</property>
+ <property name="minSize">0</property>
+ <property name="maxSize">10</property>
+ <property name="blockingTimeout">1000</property>
+ <property name="idleTimeout">100000</property>
+ <property name="transactionManager">
+ <inject bean="TransactionManager"/>
+ </property>
+ <property name="cachedConnectionManager">
+ <inject bean="CachedConnectionManager"/>
+ </property>
+ <property name="initialContextProperties">
+ <inject bean="InitialContextProperties"/>
+ </property>
+ </bean>
+
+ <bean name="NoTxRHQDS" class="java.lang.Object">
+ <constructor factoryMethod="getDatasource">
+ <factory bean="NoTxRHQDSBootstrap"/>
+ </constructor>
+ </bean>
+
+ <bean name="DefaultDSBootstrap" class="org.jboss.resource.adapter.jdbc.local.LocalTxDataSource">
+ <property name="driverClass">org.hsqldb.jdbcDriver</property>
+ <property name="connectionURL">jdbc:hsqldb:.</property>
+ <!-- <property name="connectionURL">jdbc:hsqldb:./hypersonic/localDB</property> -->
+ <property name="userName">sa</property>
+ <property name="jndiName">java:/DefaultDS</property>
+ <property name="minSize">0</property>
+ <property name="maxSize">10</property>
+ <property name="blockingTimeout">1000</property>
+ <property name="idleTimeout">100000</property>
+ <property name="transactionManager">
+ <inject bean="TransactionManager"/>
+ </property>
+ <property name="cachedConnectionManager">
+ <inject bean="CachedConnectionManager"/>
+ </property>
+ <property name="initialContextProperties">
+ <inject bean="InitialContextProperties"/>
+ </property>
+ </bean>
+
+ <bean name="DefaultDS" class="java.lang.Object">
+ <constructor factoryMethod="getDatasource">
+ <factory bean="DefaultDSBootstrap"/>
+ </constructor>
+ </bean>
+
+</deployment>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/resources/obsolete/testng.bak.xml b/modules/enterprise/server/jar/src/test/resources/obsolete/testng.bak.xml
new file mode 100644
index 0000000..1452edb
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/resources/obsolete/testng.bak.xml
@@ -0,0 +1,12 @@
+<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
+
+<suite name="EJB3 Testsuite" >
+ <test name="EJB3 tests" >
+ <groups>
+ <run>
+ <include name="integration.ejb3"/>
+ </run>
+ </groups>
+
+ </test>
+</suite>
diff --git a/modules/enterprise/server/jar/src/test/resources/test-persistence.xml b/modules/enterprise/server/jar/src/test/resources/test-persistence.xml
new file mode 100644
index 0000000..614b213
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/resources/test-persistence.xml
@@ -0,0 +1,53 @@
+<!--
+ ~ RHQ Management Platform
+ ~ Copyright (C) 2005-2012 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.
+-->
+
+<persistence
+ version="2.0"
+ xmlns="http://java.sun.com/xml/ns/persistence"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/persistence
+ http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
+ <persistence-unit name="rhq-test">
+ <jta-data-source>java:jboss/datasources/RHQDS</jta-data-source>
+
+ <properties>
+ <!-- This allows us to lookup the EMF by name prior to when Arquillian injects it, which is currently only in the @Test,
+ and not the @BeforeMethod (1.0.1.Final) -->
+ <property
+ name="jboss.entity.manager.factory.jndi.name"
+ value="java:jboss/RHQEntityManagerFactory" />
+
+
+ <!--
+ <property name="hibernate.show_sql" value="true" />
+ <property name="hibernate.format_sql" value="true" />
+ <property name="hibernate.use_sql_comments" value="true" />
+ -->
+
+ <property
+ name="hibernate.jdbc.batch_size"
+ value="30" />
+ <property
+ name="hibernate.cache.use_second_level_cache"
+ value="false" />
+
+ </properties>
+ </persistence-unit>
+</persistence>
diff --git a/modules/enterprise/server/jar/src/test/resources/testng.bak.xml b/modules/enterprise/server/jar/src/test/resources/testng.bak.xml
deleted file mode 100644
index 1452edb..0000000
--- a/modules/enterprise/server/jar/src/test/resources/testng.bak.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
-
-<suite name="EJB3 Testsuite" >
- <test name="EJB3 tests" >
- <groups>
- <run>
- <include name="integration.ejb3"/>
- </run>
- </groups>
-
- </test>
-</suite>
11 years, 6 months