modules/plugins/jboss-as-7/pom.xml | 1
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java | 68 ++
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/WebConnectorComponent.java | 55 +-
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/json/ResolveExpression.java | 32 +
modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml | 16
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/BaseComponentMetricReportTest.java | 251 ++++++++++
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/WebConnectorComponentTest.java | 118 ++++
7 files changed, 491 insertions(+), 50 deletions(-)
New commits:
commit 2b58edfae71b976970e24f1b9a05f258348a1aa1
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Mon Jun 24 10:38:14 2013 +0200
Bug 976291 - [as7] WebConnectorComponent throws ClassCastException when collecting _maxConnections metric on RHQ server
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 3b8d508..c81debb 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -615,6 +615,7 @@
<!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java</include>-->
+ <!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/WebConnectorComponentTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/ManagedServerTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java</include>-->
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java
index 2451728..2a60ec3 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* 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.
+ * 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.modules.plugins.jbossas7;
@@ -71,6 +71,7 @@ import org.rhq.modules.plugins.jbossas7.json.ReadAttribute;
import org.rhq.modules.plugins.jbossas7.json.ReadChildrenNames;
import org.rhq.modules.plugins.jbossas7.json.ReadResource;
import org.rhq.modules.plugins.jbossas7.json.Remove;
+import org.rhq.modules.plugins.jbossas7.json.ResolveExpression;
import org.rhq.modules.plugins.jbossas7.json.Result;
/**
@@ -81,8 +82,12 @@ import org.rhq.modules.plugins.jbossas7.json.Result;
public class BaseComponent<T extends ResourceComponent<?>> implements AS7Component<T>, MeasurementFacet,
ConfigurationFacet, DeleteResourceFacet, CreateChildResourceFacet, OperationFacet {
- private static final String INTERNAL = "_internal:";
- private static final int INTERNAL_SIZE = INTERNAL.length();
+ static final String INTERNAL = "_internal:";
+ static final int INTERNAL_SIZE = INTERNAL.length();
+ static final String EXPRESSION = "_expr:";
+ static final int EXPRESSION_SIZE = EXPRESSION.length();
+ static final String EXPRESSION_VALUE_KEY = "EXPRESSION_VALUE";
+
public static final String MANAGED_SERVER = "Managed Server";
final Log log = LogFactory.getLog(this.getClass());
@@ -170,12 +175,17 @@ public class BaseComponent<T extends ResourceComponent<?>> implements AS7Compone
// Metrics from the application server
String reqName = req.getName();
+ boolean resolveExpression = false;
+ if (reqName.startsWith(EXPRESSION)) {
+ resolveExpression = true;
+ reqName = reqName.substring(EXPRESSION_SIZE);
+ }
- ComplexRequest request = null;
+ ComplexRequest complexRequest = null;
Operation op;
if (reqName.contains(":")) {
- request = ComplexRequest.create(reqName);
- op = new ReadAttribute(address, request.getProp());
+ complexRequest = ComplexRequest.create(reqName);
+ op = new ReadAttribute(address, complexRequest.getProp());
} else {
op = new ReadAttribute(address, reqName); // TODO batching
}
@@ -195,32 +205,60 @@ public class BaseComponent<T extends ResourceComponent<?>> implements AS7Compone
if (val instanceof String && ((String) val).startsWith("JBAS018003")) // AS7 way of saying "no value available"
continue;
try {
- if (request != null) {
+ if (complexRequest != null) {
HashMap<String, Number> myValues = (HashMap<String, Number>) val;
for (String key : myValues.keySet()) {
- String sub = request.getSub();
+ String sub = complexRequest.getSub();
if (key.equals(sub)) {
- addMetric2Report(report, req, myValues.get(key));
+ addMetric2Report(report, req, myValues.get(key), resolveExpression);
}
}
} else {
- addMetric2Report(report, req, val);
+ addMetric2Report(report, req, val, resolveExpression);
}
} catch (NumberFormatException e) {
log.warn("Non numeric input for [" + req.getName() + "] : [" + val + "]");
}
} else if (req.getDataType() == DataType.TRAIT) {
- String realVal = getStringValue(val);
+ if (resolveExpression && val instanceof Map && ((Map) val).containsKey(EXPRESSION_VALUE_KEY)) {
+ String expression = (String) ((Map) val).get(EXPRESSION_VALUE_KEY);
+ ResolveExpression resolveExpressionOperation = new ResolveExpression(expression);
+ Result result = getASConnection().execute(resolveExpressionOperation);
+ if (!result.isSuccess()) {
+ if (log.isWarnEnabled()) {
+ log.warn("Skipping trait [" + req.getName()
+ + "] in measurement report. Could not resolve expression [" + expression
+ + "], failureDescription:" + result.getFailureDescription());
+ continue;
+ }
+ }
+ val = result.getResult();
+ }
- MeasurementDataTrait data = new MeasurementDataTrait(req, realVal);
+ MeasurementDataTrait data = new MeasurementDataTrait(req, getStringValue(val));
report.addData(data);
}
}
}
}
- private void addMetric2Report(MeasurementReport report, MeasurementScheduleRequest req, Object val) {
+ private void addMetric2Report(MeasurementReport report, MeasurementScheduleRequest req, Object val,
+ boolean resolveExpression) {
+ if (resolveExpression && val instanceof Map && ((Map) val).containsKey(EXPRESSION_VALUE_KEY)) {
+ String expression = (String) ((Map) val).get(EXPRESSION_VALUE_KEY);
+ ResolveExpression resolveExpressionOperation = new ResolveExpression(expression);
+ Result result = getASConnection().execute(resolveExpressionOperation);
+ if (!result.isSuccess()) {
+ if (log.isWarnEnabled()) {
+ log.warn("Skipping metric [" + req.getName()
+ + "] in measurement report. Could not resolve expression [" + expression
+ + "], failureDescription:" + result.getFailureDescription());
+ return;
+ }
+ }
+ val = result.getResult();
+ }
Double d = Double.parseDouble(getStringValue(val));
MeasurementDataNumeric data = new MeasurementDataNumeric(req, d);
report.addData(data);
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/WebConnectorComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/WebConnectorComponent.java
index 3af95fd..b3ac181 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/WebConnectorComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/WebConnectorComponent.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,13 +13,12 @@
* 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.
+ * 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.modules.plugins.jbossas7;
-import java.util.HashSet;
import java.util.Set;
import org.rhq.core.domain.configuration.Configuration;
@@ -37,32 +36,35 @@ import org.rhq.modules.plugins.jbossas7.json.Result;
* @author Heiko W. Rupp
*/
public class WebConnectorComponent extends BaseComponent<WebConnectorComponent> implements MeasurementFacet {
+ private static final String MAX_CONNECTIONS_METRIC_NAME = "_expr:max-connections";
+ private static final String MAX_CONNECTIONS_CONFIG_ATTRIBUTE = "max-connections:expr";
@Override
public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
- Set<MeasurementScheduleRequest> leftovers = new HashSet<MeasurementScheduleRequest>(metrics.size());
- for (MeasurementScheduleRequest request : metrics) {
- if (request.getName().equals("_maxConnections")) {
- ReadAttribute op = new ReadAttribute(getAddress(), "max-connections");
- Result res = getASConnection().execute(op);
- int val;
- if (res.isSuccess() && res.getResult() != null) {
- Object o = res.getResult(); // If the attribute was written as string, it stays string until :reload
- if (o instanceof String)
- val = Integer.valueOf((String) o);
- else
- val = (Integer) o;
- } else { // this is not set in the server, we need to compute it ourselves
- val = computeMaxConnections();
- }
+ super.getValues(report, metrics);
+ MeasurementScheduleRequest maxConnectionMetricRequest = getMaxConnectionMetricRequest(metrics);
+ if (maxConnectionMetricRequest != null && !hasMaxConnectionMetric(report)) {
+ report.addData(new MeasurementDataNumeric(maxConnectionMetricRequest, Double
+ .valueOf(computeMaxConnections())));
+ }
+ }
+
+ private MeasurementScheduleRequest getMaxConnectionMetricRequest(Set<MeasurementScheduleRequest> metrics) {
+ for (MeasurementScheduleRequest metric : metrics) {
+ if (MAX_CONNECTIONS_METRIC_NAME.equals(metric.getName())) {
+ return metric;
+ }
+ }
+ return null;
+ }
- MeasurementDataNumeric data = new MeasurementDataNumeric(request, (double) val);
- report.addData(data);
- } else {
- leftovers.add(request);
+ private boolean hasMaxConnectionMetric(MeasurementReport report) {
+ for (MeasurementDataNumeric metric : report.getNumericData()) {
+ if (MAX_CONNECTIONS_METRIC_NAME.equals(metric.getName())) {
+ return true;
}
}
- super.getValues(report, leftovers);
+ return false;
}
/**
@@ -74,10 +76,9 @@ public class WebConnectorComponent extends BaseComponent<WebConnectorComponent>
@Override
public Configuration loadResourceConfiguration() throws Exception {
Configuration configuration = super.loadResourceConfiguration();
- PropertySimple maxConnProp = configuration.getSimple("max-connections");
+ PropertySimple maxConnProp = configuration.getSimple(MAX_CONNECTIONS_CONFIG_ATTRIBUTE);
if (maxConnProp.getStringValue() == null) {
- int val = computeMaxConnections();
- maxConnProp.setIntegerValue(val);
+ maxConnProp.setIntegerValue(computeMaxConnections());
}
return configuration;
}
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/json/ResolveExpression.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/json/ResolveExpression.java
new file mode 100644
index 0000000..427c6d0
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/json/ResolveExpression.java
@@ -0,0 +1,32 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.modules.plugins.jbossas7.json;
+
+/**
+ * @author Thomas Segismont
+ */
+public class ResolveExpression extends Operation {
+
+ public ResolveExpression(String expression) {
+ super("resolve-expression", new Address());
+ addAdditionalProperty("expression", expression);
+ }
+
+}
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index e9449a5..162c3a1 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -2390,7 +2390,7 @@
<metric property="errorCount" measurementType="trendsup" displayType="summary" description="Number of error that occurs when processing requests by the connector."/>
<metric property="maxTime" units="milliseconds" description="Max time spent to process a requests."/>
<metric property="requestCount" measurementType="trendsup" displayType="summary" description="Number of the request processed by the connector."/>
- <metric property="_maxConnections" displayName="Max connections" description="Number of max connections this connector can handle (see configuration to set it)" defaultOn="true" defaultInterval="14400000"/>
+ <metric property="_expr:max-connections" displayName="Max connections" description="Number of max connections this connector can handle (see configuration to set it)" defaultOn="true" defaultInterval="14400000"/>
<resource-configuration>
<c:simple-property name="scheme" required="true" type="string" readOnly="true" description="The web connector scheme.">
@@ -2406,7 +2406,7 @@
<c:simple-property name="enabled" required="false" type="boolean" readOnly="true" defaultValue="true" description="Defines whether the connector should be started on startup. The default value is true."/>
<c:simple-property name="enable-lookups" required="false" type="boolean" readOnly="true" defaultValue="false" description="Enable DNS lookups for Servlet API. The default value is false."/>
<c:simple-property name="executor" required="false" type="string" readOnly="true" description="The name of the executor that should be used for the processing threads of this connector. If undefined defaults to using an internal pool."/>
- <c:simple-property name="max-connections" required="false" type="integer" readOnly="true" description="Amount of concurrent connections that can be processed by the connector with optimum performance. The default value depends on the connector used and the number of cpu cores (512*cores for HTTP, 32*cores for AJP)."/>
+ <c:simple-property name="max-connections:expr" displayName="Max connections" required="false" type="string" readOnly="true" description="Amount of concurrent connections that can be processed by the connector with optimum performance. The default value depends on the connector used and the number of cpu cores (512*cores for HTTP, 32*cores for AJP)."/>
<c:simple-property name="max-post-size" required="false" type="integer" readOnly="true" defaultValue="2097152" description="Maximum size in bytes of a POST request that can be parsed by the container. The default value is 2097152."/>
<c:simple-property name="max-save-post-size" required="false" type="integer" readOnly="true" defaultValue="4096" description="Maximum size in bytes of a POST request that will be saved during certain authentication schemes. The default value is 4096."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="A unique name for the connector."/>
@@ -2419,7 +2419,7 @@
</c:simple-property>
<c:simple-property name="proxy-name" required="false" type="string" readOnly="true" description="The host name that will be used when sending a redirect. The default value is null."/>
<c:simple-property name="proxy-port" required="false" type="integer" readOnly="true" description="The port that will be used when sending a redirect."/>
- <c:simple-property name="redirect-port" required="false" type="integer" readOnly="true" defaultValue="8433" description="The port for redirection to a secure connector. The default value is 8433."/>
+ <c:simple-property name="redirect-port:expr" displayName="Redirect Port" required="false" type="string" readOnly="true" defaultValue="8433" description="The port for redirection to a secure connector. The default value is 8433."/>
<c:simple-property name="secure" required="false" type="boolean" readOnly="true" defaultValue="false" description="Indicates if content sent or received by the connector is secured from the user perspective. The default value is false."/>
<c:simple-property name="virtual-server" required="false" type="string" readOnly="true" description="The list of virtual servers that can be accessed through this connector. The default is to allow all virtual servers."/>
@@ -5379,7 +5379,7 @@
<c:simple-property name="enabled" required="false" type="boolean" readOnly="false" defaultValue="true" description="Defines whether the connector should be started on startup. The default value is true."/>
<c:simple-property name="enable-lookups" required="false" type="boolean" readOnly="false" defaultValue="false" description="Enable DNS lookups for Servlet API. The default value is false."/>
<c:simple-property name="executor" required="false" type="string" readOnly="false" description="The name of the executor that should be used for the processing threads of this connector. If undefined defaults to using an internal pool."/>
- <c:simple-property name="max-connections" required="false" type="integer" readOnly="false" description="Amount of concurrent connections that can be processed by the connector with optimum performance. The default value depends on the connector used and the number of cpu cores (512*cores for HTTP, 32*cores for AJP)."/>
+ <c:simple-property name="max-connections:expr" displayName="Max connections" required="false" type="string" readOnly="false" description="Amount of concurrent connections that can be processed by the connector with optimum performance. The default value depends on the connector used and the number of cpu cores (512*cores for HTTP, 32*cores for AJP)."/>
<c:simple-property name="max-post-size" required="false" type="integer" readOnly="false" defaultValue="2097152" description="Maximum size in bytes of a POST request that can be parsed by the container. The default value is 2097152."/>
<c:simple-property name="max-save-post-size" required="false" type="integer" readOnly="false" defaultValue="4096" description="Maximum size in bytes of a POST request that will be saved during certain authentication schemes. The default value is 4096."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="A unique name for the connector."/>
@@ -5393,7 +5393,7 @@
</c:simple-property>
<c:simple-property name="proxy-name" required="false" type="string" readOnly="false" description="The host name that will be used when sending a redirect. The default value is null."/>
<c:simple-property name="proxy-port" required="false" type="integer" readOnly="false" description="The port that will be used when sending a redirect."/>
- <c:simple-property name="redirect-port" required="false" type="integer" readOnly="false" defaultValue="8433" description="The port for redirection to a secure connector. The default value is 8433."/>
+ <c:simple-property name="redirect-port:expr" displayName="Redirect Port" required="false" type="string" readOnly="false" defaultValue="8433" description="The port for redirection to a secure connector. The default value is 8433."/>
<c:simple-property name="secure" required="false" type="boolean" readOnly="false" defaultValue="false" description="Indicates if content sent or received by the connector is secured from the user perspective. The default value is false."/>
<c:simple-property name="virtual-server" required="false" type="string" readOnly="false" description="The list of virtual servers that can be accessed through this connector. The default is to allow all virtual servers."/>
@@ -7416,7 +7416,7 @@
<metric property="errorCount" measurementType="trendsup" displayType="summary" description="Number of error that occurs when processing requests by the connector."/>
<metric property="maxTime" units="milliseconds" description="Max time spent to process a requests."/>
<metric property="requestCount" measurementType="trendsup" displayType="summary" description="Number of the request processed by the connector."/>
- <metric property="_maxConnections" displayName="Max connections" description="Number of max connections this connector can handle (see configuration to set it)" defaultOn="true" defaultInterval="14400000"/>
+ <metric property="_expr:max-connections" displayName="Max connections" description="Number of max connections this connector can handle (see configuration to set it)" defaultOn="true" defaultInterval="14400000"/>
<resource-configuration>
<c:simple-property name="scheme" required="true" type="string" readOnly="false" description="The web connector scheme.">
@@ -7432,7 +7432,7 @@
<c:simple-property name="enabled" required="false" type="boolean" readOnly="false" defaultValue="true" description="Defines whether the connector should be started on startup. The default value is true."/>
<c:simple-property name="enable-lookups" required="false" type="boolean" readOnly="false" defaultValue="false" description="Enable DNS lookups for Servlet API. The default value is false."/>
<c:simple-property name="executor" required="false" type="string" readOnly="false" description="The name of the executor that should be used for the processing threads of this connector. If undefined defaults to using an internal pool."/>
- <c:simple-property name="max-connections" required="false" type="integer" readOnly="false" description="Amount of concurrent connections that can be processed by the connector with optimum performance. The default value depends on the connector used and the number of cpu cores (512*cores for HTTP, 32*cores for AJP)."/>
+ <c:simple-property name="max-connections:expr" displayName="Max connections" required="false" type="string" readOnly="false" description="Amount of concurrent connections that can be processed by the connector with optimum performance. The default value depends on the connector used and the number of cpu cores (512*cores for HTTP, 32*cores for AJP)."/>
<c:simple-property name="max-post-size" required="false" type="integer" readOnly="false" defaultValue="2097152" description="Maximum size in bytes of a POST request that can be parsed by the container. The default value is 2097152."/>
<c:simple-property name="max-save-post-size" required="false" type="integer" readOnly="false" defaultValue="4096" description="Maximum size in bytes of a POST request that will be saved during certain authentication schemes. The default value is 4096."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="A unique name for the connector."/>
@@ -7446,7 +7446,7 @@
</c:simple-property>
<c:simple-property name="proxy-name" required="false" type="string" readOnly="false" description="The host name that will be used when sending a redirect. The default value is null."/>
<c:simple-property name="proxy-port" required="false" type="integer" readOnly="false" description="The port that will be used when sending a redirect."/>
- <c:simple-property name="redirect-port" required="false" type="integer" readOnly="false" defaultValue="8433" description="The port for redirection to a secure connector. The default value is 8433."/>
+ <c:simple-property name="redirect-port:expr" displayName="Redirect Port" required="false" type="string" readOnly="false" defaultValue="8433" description="The port for redirection to a secure connector. The default value is 8433."/>
<c:simple-property name="secure" required="false" type="boolean" readOnly="false" defaultValue="false" description="Indicates if content sent or received by the connector is secured from the user perspective. The default value is false."/>
<c:simple-property name="virtual-server" required="false" type="string" readOnly="false" description="The list of virtual servers that can be accessed through this connector. The default is to allow all virtual servers."/>
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/BaseComponentMetricReportTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/BaseComponentMetricReportTest.java
new file mode 100644
index 0000000..9a48efa
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/BaseComponentMetricReportTest.java
@@ -0,0 +1,251 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.modules.plugins.jbossas7;
+
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.when;
+import static org.rhq.core.domain.measurement.DataType.MEASUREMENT;
+import static org.rhq.core.domain.measurement.DataType.TRAIT;
+import static org.rhq.modules.plugins.jbossas7.BaseComponent.EXPRESSION;
+import static org.rhq.modules.plugins.jbossas7.BaseComponent.EXPRESSION_VALUE_KEY;
+import static org.rhq.modules.plugins.jbossas7.BaseComponent.INTERNAL;
+import static org.rhq.modules.plugins.jbossas7.json.Result.SUCCESS;
+import static org.testng.Assert.assertEquals;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+import org.rhq.core.domain.measurement.MeasurementDataTrait;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.modules.plugins.jbossas7.json.Address;
+import org.rhq.modules.plugins.jbossas7.json.ReadAttribute;
+import org.rhq.modules.plugins.jbossas7.json.ResolveExpression;
+import org.rhq.modules.plugins.jbossas7.json.Result;
+
+/**
+ * @author Thomas Segismont
+ */
+public class BaseComponentMetricReportTest {
+
+ @Mock
+ private ASConnection asConnection;
+
+ private Address address;
+
+ private MeasurementReport report;
+
+ private Set<MeasurementScheduleRequest> requests;
+
+ private SampleComponent sampleComponent;
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ report = new MeasurementReport();
+ requests = new HashSet<MeasurementScheduleRequest>();
+ address = new Address("path");
+ sampleComponent = new SampleComponent();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown() throws Exception {
+
+ }
+
+ @Test
+ public void testInternalMetric() throws Exception {
+ int mgmtRequestsCount = 13;
+ for (int i = 0; i < mgmtRequestsCount; i++) {
+ PluginStats.getInstance().incrementRequestCount();
+ }
+ String requestName = INTERNAL + "mgmtRequests";
+ requests.add(newMeasurementRequest(requestName));
+
+ sampleComponent.getValues(report, requests);
+
+ Set<MeasurementDataNumeric> numericMetrics = report.getNumericData();
+ assertEquals(numericMetrics.size(), 1);
+ MeasurementDataNumeric numericMetric = numericMetrics.iterator().next();
+ assertEquals(numericMetric.getName(), requestName);
+ assertEquals(numericMetric.getValue(), (double) mgmtRequestsCount);
+ }
+
+ @Test
+ public void testSimpleMetric() throws Exception {
+ String requestName = "pipo";
+ requests.add(newMeasurementRequest(requestName));
+ double metricValue = 13d;
+
+ when(asConnection.execute(readAttribute(address, requestName))).thenReturn(result(metricValue));
+ sampleComponent.getValues(report, requests);
+
+ Set<MeasurementDataNumeric> numericMetrics = report.getNumericData();
+ assertEquals(numericMetrics.size(), 1);
+ MeasurementDataNumeric numericMetric = numericMetrics.iterator().next();
+ assertEquals(numericMetric.getName(), requestName);
+ assertEquals(numericMetric.getValue(), metricValue);
+ }
+
+ @Test
+ public void testSimpleMetricWithExpression() throws Exception {
+ String attributeName = "pipo";
+ String requestName = EXPRESSION + attributeName;
+ requests.add(newMeasurementRequest(requestName));
+ double metricValue = 13d;
+ String expressionValue = "${prop:14}";
+
+ when(asConnection.execute(readAttribute(address, attributeName))).thenReturn(
+ result(expression(expressionValue)));
+ when(asConnection.execute(resolveExpression(expressionValue))).thenReturn(result(metricValue));
+ sampleComponent.getValues(report, requests);
+
+ Set<MeasurementDataNumeric> numericMetrics = report.getNumericData();
+ assertEquals(numericMetrics.size(), 1);
+ MeasurementDataNumeric numericMetric = numericMetrics.iterator().next();
+ assertEquals(numericMetric.getName(), requestName);
+ assertEquals(numericMetric.getValue(), metricValue);
+ }
+
+ @Test
+ public void testSimpleTrait() throws Exception {
+ String requestName = "pipo";
+ requests.add(newTraitRequest(requestName));
+ String traitValue = "marseille";
+
+ when(asConnection.execute(readAttribute(address, requestName))).thenReturn(result(traitValue));
+ sampleComponent.getValues(report, requests);
+
+ Set<MeasurementDataTrait> traits = report.getTraitData();
+ assertEquals(traits.size(), 1);
+ MeasurementDataTrait trait = traits.iterator().next();
+ assertEquals(trait.getName(), requestName);
+ assertEquals(trait.getValue(), traitValue);
+ }
+
+ @Test
+ public void testSimpleTraitWithExpression() throws Exception {
+ String attributeName = "pipo";
+ String requestName = EXPRESSION + attributeName;
+ requests.add(newTraitRequest(requestName));
+ String traitValue = "marseille";
+ String expressionValue = "${prop:paris}";
+
+ when(asConnection.execute(readAttribute(address, attributeName))).thenReturn(
+ result(expression(expressionValue)));
+ when(asConnection.execute(resolveExpression(expressionValue))).thenReturn(result(traitValue));
+ sampleComponent.getValues(report, requests);
+
+ Set<MeasurementDataTrait> traits = report.getTraitData();
+ assertEquals(traits.size(), 1);
+ MeasurementDataTrait trait = traits.iterator().next();
+ assertEquals(trait.getName(), requestName);
+ assertEquals(trait.getValue(), traitValue);
+ }
+
+ private class SampleComponent extends BaseComponent {
+
+ private SampleComponent() {
+ }
+
+ @Override
+ public ASConnection getASConnection() {
+ return asConnection;
+ }
+ }
+
+ private static MeasurementScheduleRequest newMeasurementRequest(String requestName) {
+ return new MeasurementScheduleRequest(-1, requestName, -1, true, MEASUREMENT);
+ }
+
+ private static MeasurementScheduleRequest newTraitRequest(String requestName) {
+ return new MeasurementScheduleRequest(-1, requestName, -1, true, TRAIT);
+ }
+
+ private static Result result(Object value) {
+ Result result = new Result();
+ result.setOutcome(SUCCESS);
+ result.setResult(value);
+ return result;
+ }
+
+ private static ReadAttribute readAttribute(Address address, String requestName) {
+ return argThat(new IsReadAttribute(address, requestName));
+ }
+
+ private static Object expression(String expression) {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put(EXPRESSION_VALUE_KEY, expression);
+ return map;
+ }
+
+ private static ResolveExpression resolveExpression(String expressionValue) {
+ return argThat(new IsResolveExpression(expressionValue));
+ }
+
+ private static class IsReadAttribute extends ArgumentMatcher<ReadAttribute> {
+
+ private Address address;
+ private String attributeName;
+
+ private IsReadAttribute(Address address, String attributeName) {
+ this.address = address;
+ this.attributeName = attributeName;
+ }
+
+ @Override
+ public boolean matches(Object argument) {
+ if (!(argument instanceof ReadAttribute)) {
+ return false;
+ }
+ ReadAttribute readAttribute = (ReadAttribute) argument;
+ return address.getPath().equals(readAttribute.getAddress().getPath())
+ && attributeName.equals(readAttribute.getName());
+ }
+ }
+
+ private static class IsResolveExpression extends ArgumentMatcher<ResolveExpression> {
+
+ private String expressionValue;
+
+ private IsResolveExpression(String expressionValue) {
+ this.expressionValue = expressionValue;
+ }
+
+ @Override
+ public boolean matches(Object argument) {
+ if (!(argument instanceof ResolveExpression)) {
+ return false;
+ }
+ ResolveExpression resolveExpression = (ResolveExpression) argument;
+ return expressionValue.equals(resolveExpression.getAdditionalProperties().get("expression"));
+ }
+ }
+}
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/WebConnectorComponentTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/WebConnectorComponentTest.java
new file mode 100644
index 0000000..ca86d5e
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/WebConnectorComponentTest.java
@@ -0,0 +1,118 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.modules.plugins.jbossas7.itest.standalone;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.rhq.core.domain.resource.ResourceCategory.SERVICE;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.MeasurementData;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+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.pc.util.ComponentUtil;
+import org.rhq.core.pc.util.FacetLockType;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+import org.rhq.modules.plugins.jbossas7.itest.AbstractJBossAS7PluginTest;
+import org.rhq.test.arquillian.RunDiscovery;
+
+/**
+ * @author Thomas Segismont
+ */
+@Test(groups = { "integration", "pc", "standalone" }, singleThreaded = true)
+public class WebConnectorComponentTest extends AbstractJBossAS7PluginTest {
+ private static final String RESOURCE_TYPE_NAME = "Connector";
+ private static final String MAX_CONNECTIONS_METRIC_NAME = "_expr:max-connections";
+ private static final String MAX_CONNECTIONS_CONFIG_ATTRIBUTE = "max-connections:expr";
+
+ @Test(groups = "discovery")
+ @RunDiscovery(discoverServices = true, discoverServers = true)
+ public void firstDiscovery() throws Exception {
+ Resource platform = pluginContainer.getInventoryManager().getPlatform();
+ assertNotNull(platform);
+ assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
+ setMaxDiscoveryDepthOverride(10);
+ }
+
+ @Test(groups = "discovery")
+ @RunDiscovery(discoverServices = true, discoverServers = true)
+ public void secondDiscovery() throws Exception {
+ Set<Resource> webConnectorResources = getWebConnectorResources();
+ assertTrue(webConnectorResources != null && !webConnectorResources.isEmpty(), "Found no resources of type ["
+ + RESOURCE_TYPE_NAME + "]");
+ for (Resource webConnectorResource : webConnectorResources) {
+ assertEquals(webConnectorResource.getInventoryStatus(), InventoryStatus.COMMITTED);
+ }
+ }
+
+ private Set<Resource> getWebConnectorResources() {
+ ResourceType resourceType = new ResourceType(RESOURCE_TYPE_NAME, getPluginName(), SERVICE, null);
+ return pluginContainer.getInventoryManager().getResourcesWithType(resourceType);
+ }
+
+ @Test(dependsOnMethods = { "secondDiscovery" })
+ public void testGetMaxConnectionMetricHasPositiveValue() throws Exception {
+ Set<Resource> webConnectorResources = getWebConnectorResources();
+ for (Resource webConnectorResource : webConnectorResources) {
+ Set<MeasurementScheduleRequest> requests = new HashSet<MeasurementScheduleRequest>();
+ requests.add(newMeasurementRequest(MAX_CONNECTIONS_METRIC_NAME));
+ MeasurementReport report = new MeasurementReport();
+ ComponentUtil.getComponent(webConnectorResource.getId(), MeasurementFacet.class, FacetLockType.READ,
+ SECONDS.toMillis(30), true, false).getValues(report, requests);
+ Set<MeasurementDataNumeric> numericMetrics = report.getNumericData();
+ assertEquals(numericMetrics, 1);
+ MeasurementData measurementData = numericMetrics.iterator().next();
+ assertEquals(measurementData.getName(), MAX_CONNECTIONS_METRIC_NAME);
+ assertTrue(measurementData instanceof MeasurementDataNumeric);
+ MeasurementDataNumeric metric = (MeasurementDataNumeric) measurementData;
+ assertNotNull(metric.getValue());
+ assertTrue(metric.getValue() > 0);
+ }
+ }
+
+ @Test(dependsOnMethods = { "testGetMaxConnectionMetricHasPositiveValue" })
+ public void testMaxConnectionConfigPropertyHasValue() throws Exception {
+ Set<Resource> webConnectorResources = getWebConnectorResources();
+ for (Resource webConnectorResource : webConnectorResources) {
+ Configuration configuration = pluginContainer.getConfigurationManager().loadResourceConfiguration(
+ webConnectorResource.getId());
+ PropertySimple maxConnectionProperty = configuration.getSimple(MAX_CONNECTIONS_CONFIG_ATTRIBUTE);
+ assertNotNull(maxConnectionProperty);
+ assertNotNull(maxConnectionProperty.getStringValue());
+ }
+ }
+
+ private static MeasurementScheduleRequest newMeasurementRequest(String metricName) {
+ return new MeasurementScheduleRequest(-1, metricName, -1, true, DataType.MEASUREMENT);
+ }
+}