[rhq] Branch 'rhq-on-as7' - 2 commits - .classpath modules/enterprise
by mazz
.classpath | 3
modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java | 52 ++++++++--
modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/InstallerGWTServiceImpl.java | 5
modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/ServerInstallUtil.java | 19 +++
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/agentupdate/AgentUpdateServlet.java | 9 -
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/client/RemoteClientServlet.java | 3
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/AgentManagerBean.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java | 50 ++++-----
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java | 17 +--
9 files changed, 111 insertions(+), 49 deletions(-)
New commits:
commit 1af7165a8f9a6f0cd2e17bdb58579853dc038b3d
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Sep 7 17:45:54 2012 -0400
fix core server MBean to use the new AS7 mbeans
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/agentupdate/AgentUpdateServlet.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/agentupdate/AgentUpdateServlet.java
index c1fd411..cd64648 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/agentupdate/AgentUpdateServlet.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/agentupdate/AgentUpdateServlet.java
@@ -21,7 +21,6 @@ package org.rhq.enterprise.gui.agentupdate;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
@@ -30,9 +29,11 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.rhq.core.domain.cloud.Server.OperationMode;
+import org.rhq.core.domain.common.composite.SystemSetting;
+import org.rhq.core.domain.common.composite.SystemSettings;
import org.rhq.core.util.stream.StreamUtil;
-import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.core.AgentManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -170,9 +171,9 @@ public class AgentUpdateServlet extends HttpServlet {
private int getDownloadLimit() {
// if the server cloud was configured to disallow updates, return 0
- Properties systemConfig = LookupUtil.getSystemManager().getSystemConfiguration(
+ SystemSettings systemConfig = LookupUtil.getSystemManager().getSystemSettings(
LookupUtil.getSubjectManager().getOverlord());
- if (!Boolean.parseBoolean(systemConfig.getProperty(RHQConstants.EnableAgentAutoUpdate))) {
+ if (!Boolean.parseBoolean(systemConfig.get(SystemSetting.AGENT_AUTO_UPDATE_ENABLED.getInternalName()))) {
return 0;
}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/client/RemoteClientServlet.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/client/RemoteClientServlet.java
index 79c1452..b6edc07 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/client/RemoteClientServlet.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/client/RemoteClientServlet.java
@@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.rhq.core.domain.cloud.Server.OperationMode;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.stream.StreamUtil;
@@ -173,7 +174,7 @@ public class RemoteClientServlet extends HttpServlet {
private File getDownloadDir() throws Exception {
File serverHomeDir = LookupUtil.getCoreServer().getJBossServerHomeDir();
- File downloadDir = new File(serverHomeDir, "deploy/rhq.ear/rhq-downloads/rhq-client");
+ File downloadDir = new File(serverHomeDir, "deployments/rhq.ear/rhq-downloads/rhq-client");
if (!downloadDir.exists()) {
throw new FileNotFoundException("Missing remote client download directory at [" + downloadDir + "]");
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/AgentManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/AgentManagerBean.java
index 5a7d750..b7f7e42 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/AgentManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/AgentManagerBean.java
@@ -567,7 +567,7 @@ public class AgentManagerBean implements AgentManagerLocal {
@ExcludeDefaultInterceptors
public File getAgentDownloadDir() throws Exception {
File serverHomeDir = LookupUtil.getCoreServer().getJBossServerHomeDir();
- File agentDownloadDir = new File(serverHomeDir, "deploy/rhq.ear/rhq-downloads/rhq-agent");
+ File agentDownloadDir = new File(serverHomeDir, "deployments/rhq.ear/rhq-downloads/rhq-agent");
if (!agentDownloadDir.exists()) {
throw new FileNotFoundException("Missing agent downloads directory at [" + agentDownloadDir + "]");
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
index e6f6c8c..c14a549 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
@@ -21,20 +21,17 @@ package org.rhq.enterprise.server.core;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.management.ManagementFactory;
import java.util.Date;
import java.util.HashMap;
import java.util.Properties;
import javax.management.MBeanServer;
-import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.jboss.mx.util.MBeanServerLocator;
-import org.jboss.system.server.ServerConfig;
-
import org.rhq.core.domain.common.ProductInfo;
import org.rhq.core.util.ObjectNameFactory;
@@ -99,36 +96,25 @@ public class CoreServer implements CoreServerMBean {
}
public File getInstallDir() {
- MBeanServer mbs = getMBeanServer();
- ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
- Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
-
- File homeDir = ((ServerConfig) mbean).getHomeDir();
- return homeDir.getParentFile(); // jboss homedir is "rhq-install-dir/jbossas", so the install dir is .. from jbossas
+ // use logDir explicitly - NOT homeDir because AS could be installed elsewhere (e.g. via rpm)
+ // but our log dir is always under our own installation directory
+ File homeDir = new File(getServerEnvironmentAttribute("logDir"));
+ return homeDir.getParentFile(); // logDir is "rhq-install-dir/logs", so the install dir is .. from there
}
public File getJBossServerHomeDir() {
- MBeanServer mbs = getMBeanServer();
- ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
- Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
- File serverHomeDir = ((ServerConfig) mbean).getServerHomeDir();
- return serverHomeDir;
+ File baseDir = new File(getServerEnvironmentAttribute("baseDir"));
+ return baseDir;
}
public File getJBossServerDataDir() {
- MBeanServer mbs = getMBeanServer();
- ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
- Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
- File serverDataDir = ((ServerConfig) mbean).getServerDataDir();
- return serverDataDir;
+ File dataDir = new File(getServerEnvironmentAttribute("dataDir"));
+ return dataDir;
}
public File getJBossServerTempDir() {
- MBeanServer mbs = getMBeanServer();
- ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
- Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
- File serverTempDir = ((ServerConfig) mbean).getServerTempDir();
- return serverTempDir;
+ File tempDir = new File(getServerEnvironmentAttribute("tempDir"));
+ return tempDir;
}
public ProductInfo getProductInfo() {
@@ -177,7 +163,19 @@ public class CoreServer implements CoreServerMBean {
}
private MBeanServer getMBeanServer() {
- return MBeanServerLocator.locateJBoss();
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ return mbs;
+ }
+
+ private String getServerEnvironmentAttribute(String attributeName) {
+ try {
+ MBeanServer mbs = getMBeanServer();
+ ObjectName name = ObjectNameFactory.create("jboss.as:core-service=server-environment");
+ Object value = mbs.getAttribute(name, attributeName);
+ return (value != null) ? value.toString() : null;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
}
private Properties loadBuildProperties() {
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 05b3662..a4ab159 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
@@ -32,7 +32,6 @@ import javax.transaction.TransactionManager;
import org.jetbrains.annotations.NotNull;
import org.jboss.mx.util.MBeanProxyExt;
-import org.jboss.mx.util.MBeanServerLocator;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.alert.AlertConditionManagerBean;
@@ -607,12 +606,10 @@ public final class LookupUtil {
}
public static CoreServerMBean getCoreServer() {
- // The default MBean server for AS7 is the platform MBeanServer
- MBeanServer defaultMBeanServer = ManagementFactory.getPlatformMBeanServer();
CoreServerMBean rhqServer;
try {
- rhqServer = (CoreServerMBean) MBeanProxyExt.create(CoreServerMBean.class, CoreServerMBean.OBJECT_NAME,
- defaultMBeanServer);
+ MBeanServer mbs = getJBossMBeanServer();
+ rhqServer = (CoreServerMBean) MBeanProxyExt.create(CoreServerMBean.class, CoreServerMBean.OBJECT_NAME, mbs);
} catch (MalformedObjectNameException e) {
throw new RuntimeException(e);
}
@@ -620,19 +617,25 @@ public final class LookupUtil {
}
public static PluginDeploymentScannerMBean getPluginDeploymentScanner() {
- MBeanServer jBossMBeanServer = MBeanServerLocator.locateJBoss();
+ MBeanServer jBossMBeanServer = getJBossMBeanServer();
PluginDeploymentScannerMBean scanner = (PluginDeploymentScannerMBean) MBeanProxyExt.create(
PluginDeploymentScannerMBean.class, PluginDeploymentScannerMBean.OBJECT_NAME, jBossMBeanServer);
return scanner;
}
public static ServerPluginServiceManagement getServerPluginService() {
- MBeanServer jBossMBeanServer = MBeanServerLocator.locateJBoss();
+ MBeanServer jBossMBeanServer = getJBossMBeanServer();
ServerPluginServiceManagement service = (ServerPluginServiceManagement) MBeanProxyExt.create(
ServerPluginServiceManagement.class, ServerPluginServiceManagement.OBJECT_NAME, jBossMBeanServer);
return service;
}
+ private static MBeanServer getJBossMBeanServer() {
+ // The default MBean server for AS7 is the platform MBeanServer
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ return mbs;
+ }
+
//--------------------------------------------
// The TEST services
//--------------------------------------------
commit a0d63b45b26871d24303b95de47a642904c67c77
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Sep 7 17:33:50 2012 -0400
have installer configure the deployment scanner so it lengthens the deployment timeout
diff --git a/.classpath b/.classpath
index 0ab311c..89d8a42 100644
--- a/.classpath
+++ b/.classpath
@@ -48,7 +48,8 @@
<classpathentry kind="src" path="modules/enterprise/gui/coregui/target/generated-sources/gwt"/>
<classpathentry kind="src" path="modules/enterprise/gui/portal-war/src/main/java"/>
<classpathentry kind="src" path="modules/enterprise/gui/portal-war/src/test/java"/>
- <classpathentry kind="src" path="modules/enterprise/gui/installer-war/src/main/java"/>
+ <classpathentry kind="src" path="modules/enterprise/gui/installer/src/main/java"/>
+ <classpathentry kind="src" path="modules/enterprise/gui/installer/target/generated-sources/gwt"/>
<classpathentry kind="src" path="modules/enterprise/gui/content_http-war/src/main/java"/>
<classpathentry kind="src" path="modules/enterprise/server/client-api/src/main/java"/>
<classpathentry kind="src" path="modules/enterprise/remoting/client-api/src/main/java"/>
diff --git a/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java b/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
index 00d2f14..1729f95 100644
--- a/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
+++ b/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
@@ -25,7 +25,7 @@ import org.jboss.dmr.ModelNode;
/**
* Provides information to some core services.
- *
+ *
* @author John Mazzitelli
*/
public class CoreJBossASClient extends JBossASClient {
@@ -116,11 +116,47 @@ public class CoreJBossASClient extends JBossASClient {
relativeTo = syspropValue;
}
- File dir = new File(relativeTo, path);
+ final File dir = new File(relativeTo, path);
return dir.getAbsolutePath();
}
/**
+ * Sets the interval of the default deployment scanner. If the value is
+ * less than 1 millisecond, the scanner will scan only one time at server startup.
+ * @param millis number of milliseconds to periodically scan the deployment directory
+ * @throws Exception
+ */
+ public void setAppServerDefaultDeploymentScanInterval(long millis) throws Exception {
+ final String[] addressArr = { SUBSYSTEM, DEPLOYMENT_SCANNER, SCANNER, "default" };
+ final Address address = Address.root().add(addressArr);
+ final ModelNode req = createWriteAttributeRequest("scan-interval", Long.toString(millis), address);
+ final ModelNode response = execute(req);
+
+ if (!isSuccess(response)) {
+ throw new FailureException(response);
+ }
+ return;
+ }
+
+ /**
+ * Sets the deployment timeout of the default deployment scanner. If a deployment
+ * takes longer than this value, it will fail.
+ * @param secs number of seconds the app server will wait for a deployment to finish
+ * @throws Exception
+ */
+ public void setAppServerDefaultDeploymentTimeout(long secs) throws Exception {
+ final String[] addressArr = { SUBSYSTEM, DEPLOYMENT_SCANNER, SCANNER, "default" };
+ final Address address = Address.root().add(addressArr);
+ final ModelNode req = createWriteAttributeRequest("deployment-timeout", Long.toString(secs), address);
+ final ModelNode response = execute(req);
+
+ if (!isSuccess(response)) {
+ throw new FailureException(response);
+ }
+ return;
+ }
+
+ /**
* Set a runtime system property in the JVM that is managed by JBossAS.
*
* @param name
@@ -128,9 +164,9 @@ public class CoreJBossASClient extends JBossASClient {
* @throws Exception
*/
public void setSystemProperty(String name, String value) throws Exception {
- ModelNode request = createRequest(ADD, Address.root().add(SYSTEM_PROPERTY, name));
+ final ModelNode request = createRequest(ADD, Address.root().add(SYSTEM_PROPERTY, name));
request.get(VALUE).set(value);
- ModelNode response = execute(request);
+ final ModelNode response = execute(request);
if (!isSuccess(response)) {
throw new FailureException(response, "Failed to set system property [" + name + "]");
}
@@ -144,9 +180,9 @@ public class CoreJBossASClient extends JBossASClient {
* @throws Exception
*/
public void reload() throws Exception {
- ModelNode request = createRequest("reload", Address.root());
+ final ModelNode request = createRequest("reload", Address.root());
request.get("admin-only").set(false);
- ModelNode response = execute(request);
+ final ModelNode response = execute(request);
if (!isSuccess(response)) {
throw new FailureException(response);
}
@@ -177,9 +213,9 @@ public class CoreJBossASClient extends JBossASClient {
* @throws Exception
*/
public void shutdown(boolean restart) throws Exception {
- ModelNode request = createRequest("shutdown", Address.root());
+ final ModelNode request = createRequest("shutdown", Address.root());
request.get("restart").set(restart);
- ModelNode response = execute(request);
+ final ModelNode response = execute(request);
if (!isSuccess(response)) {
throw new FailureException(response);
}
diff --git a/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/InstallerGWTServiceImpl.java b/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/InstallerGWTServiceImpl.java
index 47a3306..ecda87c 100644
--- a/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/InstallerGWTServiceImpl.java
+++ b/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/InstallerGWTServiceImpl.java
@@ -316,10 +316,13 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
// create a keystore whose cert has a CN of this server's public endpoint address
ServerInstallUtil.createKeystore(serverDetails, getAppServerConfigDir());
+ // Make sure our deployment scanner is configured to be ready for deploy our services and application
+ ServerInstallUtil.configureDeploymentScanner(getClient());
+
// now create our deployment services and our main EAR
deployServices(serverProperties);
- // deploy the EAR and undeploy this installer - this will shut us down within seconds, return fast!
+ // deploy the EAR
deployApp();
// some of the changes we made require the app server container to reload
diff --git a/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/ServerInstallUtil.java b/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/ServerInstallUtil.java
index 14046ae..aa0b27c 100644
--- a/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/ServerInstallUtil.java
+++ b/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/ServerInstallUtil.java
@@ -46,6 +46,7 @@ import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.dmr.ModelNode;
import org.rhq.common.jbossas.client.controller.Address;
+import org.rhq.common.jbossas.client.controller.CoreJBossASClient;
import org.rhq.common.jbossas.client.controller.DatasourceJBossASClient;
import org.rhq.common.jbossas.client.controller.FailureException;
import org.rhq.common.jbossas.client.controller.JBossASClient;
@@ -99,10 +100,28 @@ public class ServerInstallUtil {
private static final String JDBC_DRIVER_ORACLE = "oracle";
/**
+ * Configure the deployment scanner to get ready to deploy the application.
+ * @param mcc JBossAS management client
+ * @throws Exception
+ */
+ public static void configureDeploymentScanner(ModelControllerClient mcc) throws Exception {
+ CoreJBossASClient client = new CoreJBossASClient(mcc);
+
+ // the EAR could take a long time to deploy, increase the deployment timeout
+ client.setAppServerDefaultDeploymentTimeout(1800); // 30 minutes should be plenty of time
+
+ // We don't need to scan the deployment directory after everything is installed.
+ // TODO: We would like this to be 0, so it only scans at startup, but the installer
+ // will need the scanner to deploy the ear after the .dodeploy is created.
+ //client.setAppServerDefaultDeploymentScanInterval(0);
+ }
+
+ /**
* Prepares the mail service by configuring the SMTP settings.
*
* @param mcc JBossAS management client
* @param serverProperties the server's properties
+ * @throws Exception
*/
public static void setupMailService(ModelControllerClient mcc, HashMap<String, String> serverProperties)
throws Exception {
11 years, 9 months
[rhq] Branch 'rhq-on-as7' - 2 commits - modules/enterprise
by mazz
modules/enterprise/gui/pom.xml | 2
modules/enterprise/server/ear/src/main/application/META-INF/jboss-deployment-structure.xml | 24 ++--------
2 files changed, 6 insertions(+), 20 deletions(-)
New commits:
commit 4b5aaac5801dddef9ab04ef58d0ea0c52909d7de
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Sep 7 14:36:19 2012 -0400
* fix xmlns name and point to 1.1 version of schema
* export module dependencies
diff --git a/modules/enterprise/server/ear/src/main/application/META-INF/jboss-deployment-structure.xml b/modules/enterprise/server/ear/src/main/application/META-INF/jboss-deployment-structure.xml
index c76f1d2..46b9cf7 100644
--- a/modules/enterprise/server/ear/src/main/application/META-INF/jboss-deployment-structure.xml
+++ b/modules/enterprise/server/ear/src/main/application/META-INF/jboss-deployment-structure.xml
@@ -1,32 +1,18 @@
-<jboss-deployment-structure xmlns="urn:jbosseployment-structure:1.0">
-
- <!-- This file gives fine-grained control of the RHQ EAR and sub-deployments -->
+<?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>
- <!-- Exclusions allow you to prevent the server from automatically adding some dependencies
- <exclusions>
- <module name="blah" />
- </exclusions>
- -->
-
- <!-- This allows you to define additional dependencies; it is the same as using the Dependencies: manifest attribute -->
<dependencies>
<module name="org.jboss.common-core" export="true" /> <!-- needed to fix https://issues.jboss.org/browse/AS7-5336 -->
- <module name="org.jboss.jts" /> <!-- needed for Arjuna CheckedAction related classes and our custom tx interceptor -->
- <module name="org.apache.commons.logging" /> <!-- needed as per https://docs.jboss.org/author/display/AS71/How+do+I+migrate+my+applicatio... -->
- <module name="org.hibernate" /> <!-- because we need hibernate specific APIs, e.g. for the HibernateDetachUtility -->
+ <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 -->
</dependencies>
-
- <!-- These add additional classes to the module. In this case it is the same as including the jar in the EAR's lib directory
- <resources>
- <resource-root path="my-library.jar" />
- </resources>
- -->
</deployment>
<!-- This corresponds to the Portal WAR - it requires the older JSF version packaged with AS 4.2.3, not the AS7 default -->
commit e8493207a4b2a4c27c45fbb5b8e7b614ddd61517
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Sep 7 14:35:35 2012 -0400
opps - build the new installer, not the old
diff --git a/modules/enterprise/gui/pom.xml b/modules/enterprise/gui/pom.xml
index c4432ac..5e51b37 100644
--- a/modules/enterprise/gui/pom.xml
+++ b/modules/enterprise/gui/pom.xml
@@ -28,7 +28,7 @@
</activation>
<modules>
<module>portal-war</module>
- <module>installer-war</module>
+ <module>installer</module>
<module>content_http-war</module>
<module>coregui</module>
<module>rest-war</module>
11 years, 9 months
[rhq] Branch 'rhq-on-as7' - modules/enterprise
by mazz
modules/enterprise/server/ear/pom.xml | 18
modules/enterprise/server/ear/src/main/application/META-INF/README.txt | 2
modules/enterprise/server/ear/src/main/application/META-INF/jboss-deployment-structure.xml | 44
modules/enterprise/server/ear/src/main/application/alert-email-template.txt | 23
modules/enterprise/server/ear/src/main/application/server-comm-configuration.xml | 468 ++++++++++
modules/enterprise/server/ear/src/main/resources/alert-email-template.txt | 23
modules/enterprise/server/ear/src/main/resources/server-comm-configuration.xml | 468 ----------
7 files changed, 536 insertions(+), 510 deletions(-)
New commits:
commit edc7d6d299259199435477588c6b2a93da1a81a6
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Sep 7 12:21:29 2012 -0400
start using the jboss-deployment-structure deployment file, rather than the Dependencies: entry in manifest file because we need some features only the .xml file gives us
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index fed8a33..1367364 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -203,13 +203,6 @@
<build>
<finalName>rhq</finalName>
- <resources>
- <resource>
- <directory>src/main/resources</directory>
- <filtering>true</filtering>
- </resource>
- </resources>
-
<plugins>
<plugin>
@@ -218,18 +211,9 @@
<version>6</version>
<displayName>RHQ</displayName>
<workDirectory>${earDirectory}</workDirectory>
- <earSourceDirectory>${basedir}/target/classes</earSourceDirectory>
+ <filtering>true</filtering>
<defaultJavaBundleDir>lib</defaultJavaBundleDir>
<unpackTypes>war,ejb</unpackTypes>
- <archive>
- <manifestEntries>
- <!-- org.jboss.common-core - needed to fix https://issues.jboss.org/browse/AS7-5336 -->
- <!-- org.jboss.jta - needed for Arjuna CheckedAction related classes and our custom tx interceptor -->
- <!-- org.apache.commons.logging - needed as per https://docs.jboss.org/author/display/AS71/How+do+I+migrate+my+applicatio... -->
- <!-- org.hibernate because we need hibernate specific APIs, e.g. for the HibernateDetachUtility -->
- <Dependencies>org.jboss.common-core export,org.jboss.jts,org.apache.commons.logging,org.hibernate</Dependencies>
- </manifestEntries>
- </archive>
<modules>
<!-- ** WARs -->
<webModule>
diff --git a/modules/enterprise/server/ear/src/main/application/META-INF/README.txt b/modules/enterprise/server/ear/src/main/application/META-INF/README.txt
deleted file mode 100644
index 7938d59..0000000
--- a/modules/enterprise/server/ear/src/main/application/META-INF/README.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-This is the location where our EAR can put META-INF configuration files.
-This file is really just a placeholder. We can delete it when we get actual content for META-INF.
\ No newline at end of file
diff --git a/modules/enterprise/server/ear/src/main/application/META-INF/jboss-deployment-structure.xml b/modules/enterprise/server/ear/src/main/application/META-INF/jboss-deployment-structure.xml
new file mode 100644
index 0000000..c76f1d2
--- /dev/null
+++ b/modules/enterprise/server/ear/src/main/application/META-INF/jboss-deployment-structure.xml
@@ -0,0 +1,44 @@
+<jboss-deployment-structure xmlns="urn:jbosseployment-structure:1.0">
+
+ <!-- This file gives fine-grained control of the RHQ EAR and sub-deployments -->
+
+ <!-- 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>
+ <!-- Exclusions allow you to prevent the server from automatically adding some dependencies
+ <exclusions>
+ <module name="blah" />
+ </exclusions>
+ -->
+
+ <!-- This allows you to define additional dependencies; it is the same as using the Dependencies: manifest attribute -->
+ <dependencies>
+ <module name="org.jboss.common-core" export="true" /> <!-- needed to fix https://issues.jboss.org/browse/AS7-5336 -->
+ <module name="org.jboss.jts" /> <!-- needed for Arjuna CheckedAction related classes and our custom tx interceptor -->
+ <module name="org.apache.commons.logging" /> <!-- needed as per https://docs.jboss.org/author/display/AS71/How+do+I+migrate+my+applicatio... -->
+ <module name="org.hibernate" /> <!-- 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 -->
+ </dependencies>
+
+ <!-- These add additional classes to the module. In this case it is the same as including the jar in the EAR's lib directory
+ <resources>
+ <resource-root path="my-library.jar" />
+ </resources>
+ -->
+ </deployment>
+
+ <!-- This corresponds to the Portal WAR - it requires the older JSF version packaged with AS 4.2.3, not the AS7 default -->
+ <sub-deployment name="rhq-portal.war">
+ <exclusions>
+ <module name="javax.faces.api" slot="main" />
+ <module name="com.sun.jsf-impl" slot="main" />
+ </exclusions>
+ <dependencies>
+ <module name="javax.faces.api" slot="1.2" />
+ <module name="com.sun.jsf-impl" slot="1.2" />
+ </dependencies>
+ </sub-deployment>
+
+</jboss-deployment-structure>
\ No newline at end of file
diff --git a/modules/enterprise/server/ear/src/main/application/alert-email-template.txt b/modules/enterprise/server/ear/src/main/application/alert-email-template.txt
new file mode 100644
index 0000000..a791933
--- /dev/null
+++ b/modules/enterprise/server/ear/src/main/application/alert-email-template.txt
@@ -0,0 +1,23 @@
+Subject: [ALERT] priority of [@@@PRIORITY@@@] for alert [@@@ALERT_NAME@@@] on resource [@@@RESOURCE_NAME@@@]
+
+The resource @@@RESOURCE_NAME@@@ has generated the following alert:
+
+------------------------------------------
+
+Resource Name : @@@RESOURCE_NAME@@@
+Alert Name : @@@ALERT_NAME@@@
+Alert Severity : @@@PRIORITY@@@
+Alert Date/Time : @@@TIMESTAMP@@@
+Conditions: @@@CONDITIONS@@@
+
+------------------------------------------
+
+Resource Ancestry:
+
+@@@FULL_RESOURCE_HIERARCHY@@@
+
+------------------------------------------
+
+For additional details about this alert, go to @@@ALERT_URL@@@
+
+This message was delivered to you by RHQ.
diff --git a/modules/enterprise/server/ear/src/main/application/server-comm-configuration.xml b/modules/enterprise/server/ear/src/main/application/server-comm-configuration.xml
new file mode 100644
index 0000000..7f30276
--- /dev/null
+++ b/modules/enterprise/server/ear/src/main/application/server-comm-configuration.xml
@@ -0,0 +1,468 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE preferences SYSTEM 'http://java.sun.com/dtd/preferences.dtd'>
+
+<!--
+==============================================================================
+RHQ Server Communications Configuration
+==============================================================================
+-->
+
+<preferences EXTERNAL_XML_VERSION="1.0">
+ <root type="user">
+ <map />
+ <node name="rhq-server">
+ <map />
+ <node name="default">
+ <map>
+ <!--
+ _______________________________________________________________
+ rhq.server.configuration-schema-version
+
+ Defines what version of the server configuration schema this
+ file conforms to. This is the schema for the rhq.server
+ preferences.
+ -->
+ <entry key="rhq.server.configuration-schema-version" value="1" />
+
+ <!--
+ _______________________________________________________________
+ rhq.server.agent-files-directory
+
+ This defines the directory location that contains all the files
+ that can be sent remotely to agents. If this is not defined,
+ this effectively disables the server's ability to remotely
+ send files to agents. If deploying within a JBossAS instance,
+ leave this undefined, and set this as a configuration override
+ property in the server-comm-service.xml
+ deployment configuration file. This will allow you to use the
+ ${jboss.server.home.dir} replacement variable expression
+ as part of the directory location, for example.
+ -->
+ <!--
+ <entry key="rhq.server.agent-files-directory" value="conf" />
+ -->
+
+ <!--
+ _______________________________________________________________
+ rhq.server.client.queue-size
+
+ The maximum size of the client command queue - this is the
+ maximum number of commands that can be queued for sending to
+ an agent. If this is 0, then the queue is unbounded.
+ WARNING! Setting this to 0 could lead to resources being used
+ up if for some reason commands keep getting queued but are
+ not getting sent.
+ -->
+ <entry key="rhq.server.client.queue-size" value="50000" />
+
+ <!--
+ _______________________________________________________________
+ rhq.server.client.max-concurrent
+
+ The maximum number of concurrent commands that can be in the
+ process of being sent to an agent at any one time.
+ -->
+ <entry key="rhq.server.client.max-concurrent" value="1" />
+
+ <!--
+ _______________________________________________________________
+ rhq.server.client.command-timeout-msecs
+
+ The time in milliseconds that the client sender will wait
+ before aborting a command. This is the amount of time in
+ milliseconds that the agent has in order to process commands.
+ This value is only the default if a command has not specified
+ its own timeout. A command can override this by setting its
+ own timeout in the command's configuration, so this value may
+ not be used for all commands that are sent. If this value is
+ less than or equal to 0, there will be no default timeout
+ and commands will therefore be allowed to take as long as they
+ need (again, this is the default, individual commands may
+ override this and set their own timeout). While this infinite
+ timeout default could conceivably cause a thread to hang
+ waiting for a rogue command that never finishes, it also reduces
+ the amount of short-lived threads created by the system
+ and will increase throughput, dramatically in some cases.
+ -->
+ <entry key="rhq.server.client.command-timeout-msecs" value="600000" />
+
+ <!--
+ _______________________________________________________________
+ rhq.server.client.retry-interval-msecs
+
+ This is the minimum amount of time, in milliseconds, the client
+ sender will wait before trying to resend a guaranteed command
+ that previously failed. This is not a guarantee of when
+ a command is retried - all that can be inferred is that a
+ command that fails to be sent will not be retried until at
+ least this amount of time passes.
+ Note: if the sender is currently waiting in this retry pause
+ period, the server will not be able to be shutdown until that
+ retry period is over. In other words, if the server is asked
+ to shutdown, it will wait for those commands waiting in this
+ retry interval to wake up. This is to help ensure those
+ commands are not lost.
+ -->
+ <entry key="rhq.server.client.retry-interval-msecs" value="15000" />
+
+ <!--
+ _______________________________________________________________
+ rhq.server.client.max-retries
+
+ If a guaranteed delivery message is sent, but the server fails
+ to connect to the agent and deliver the message, it will
+ always be retried. However, if the error was something other
+ than a "cannot connect" error, the command will only be retried
+ this amount of times before the command is dropped. When this
+ happens, the guaranteed command will never be delivered. This
+ will normally happen under very odd and rare circumstances.
+ Also, this setting only effects asynchronous messages that
+ are sent with guaranteed delivery. This setting has no effect
+ on other messages.
+ -->
+ <entry key="rhq.server.client.max-retries" value="10" />
+
+ <!--
+ _______________________________________________________________
+ rhq.server.client.command-spool-file.name
+
+ This defines the name of the command spool file. This
+ file must be located in the data directory (if one does not
+ exist, it will be created). Note that if you do not define
+ this setting, the default is to not spool commands to disk
+ and thus implicitly disable guaranteed delivery.
+ -->
+ <!--
+ <entry key="rhq.server.client.command-spool-file.name" value="command-spool.dat" />
+ -->
+
+ <!--
+ _______________________________________________________________
+ rhq.server.client.command-spool-file.params
+
+ This defines the parameters for the command spool file.
+ The spool file is where the server persists commands that
+ are flagged for guaranteed delivery and need to be sent.
+ The format is defined as "max-file-size:purge-percentage".
+ The first number is the size, in bytes, of the maximum file
+ size threshold. If the spool file grows larger than this, a
+ "purge" will be triggered in order to shrink the file.
+ The second number is the purge percentage which indicates how
+ large the file is allowed to be after a purge. This is
+ specified as a percentage of the first parameter - the max
+ file size threshold. For example, if the max file size is
+ 100000 (i.e. 100KB) and the purge percentage is 90, then when
+ the spool file grows larger than 100KB, a purge will be
+ triggered and the file will be shrunk to no more than
+ 90% of 100KB - which is 90KB. In effect, 10KB will be freed
+ to allow room for new commands to be spooled. When this
+ occurs, unused space is freed first and if that does not
+ free up enough space, the oldest commands in the spool file
+ will be sacrificed in order to make room for the newer
+ commands.
+ -->
+ <entry key="rhq.server.client.command-spool-file.params" value="1000000:75" />
+
+ <!--
+ _______________________________________________________________
+ rhq.server.client.command-spool-file.compressed
+
+ If this flag is true, the commands stored in the spool file
+ will be compressed. This can potentially save about 30%-40% in
+ disk space (give or take), however, it slows down the
+ persistence mechanism considerably. Recommended setting for
+ this should be false unless something on the server deployment
+ box warrants disk-saving over persistence performance.
+ -->
+ <entry key="rhq.server.client.command-spool-file.compressed" value="false" />
+
+ <!--
+ _______________________________________________________________
+ rhq.server.client.send-throttling
+
+ If this setting is defined, it will enable send throttling to
+ occur while sending commands to an agent. The format is
+ defined as "max-commands:quiet-period-milliseconds"
+ where the maximum commands defines the maximum number
+ of commands that will be sent before the start of a quiet
+ period. The quiet period defines the number of milliseconds
+ in which no commands should be sent. After this duration
+ expires, commands can again be sent, up to the maximum defined.
+ Note that send throttling only affects those commands that
+ are "throttle-able". Some commands are sent as soon as
+ possible, regardless of the throttling settings.
+
+ This affects sending commands synchronously and asynchronously.
+ -->
+ <!--
+ <entry key="rhq.server.client.send-throttling" value="100:1000" />
+ -->
+
+ <!--
+ _______________________________________________________________
+ rhq.server.client.queue-throttling
+
+ If this setting is defined, it will enable queue throttling to
+ occur while sending commands to an agent. The format is
+ defined as "max-commands-per-burst:burst-period-milliseconds"
+ where the maximum commands per burst defines the maximum number
+ of commands that can be dequeued within a burst period. The
+ burst period defines the number of milliseconds in which the
+ defined maximum number of commands can be dequeued. If more
+ than the maximum number of commands are queued within this
+ time period, they will wait until the next burst period starts
+ before being able to be dequeued.
+
+ This does not affect sending commands synchronously. It only
+ effects commands queued to be sent asynchronously.
+ -->
+ <!--
+ <entry key="rhq.server.client.queue-throttling" value="50:3000" />
+ -->
+
+ <!--
+ _______________________________________________________________
+ rhq.communications.configuration-schema-version
+
+ Defines what version of the configuration schema this
+ file conforms to. This is the schema for the
+ rhq.communications preferences.
+ -->
+ <entry key="rhq.communications.configuration-schema-version" value="1" />
+
+ <!--
+ _______________________________________________________________
+ rhq.communications.service-container.mbean-server-name
+
+ Name of the MBean Server that houses the communications MBean
+ services. This is actually the default domain name of the
+ MBean Server and if an MBean Server has already been registered
+ with this name, it will be used to house the communications
+ services. If an MBean Server has not yet been registered with
+ this name as its default domain, one will be created.
+ If deploying within a JBossAS instance, the JBoss MBeanServer
+ will be used, so this value can be left undefined since it
+ will be unused.
+ -->
+ <!--
+ <entry key="rhq.communications.service-container.mbean-server-name" value="jboss-on" />
+ -->
+
+ <!--
+ _______________________________________________________________
+ rhq.communications.data-directory
+
+ The location where the communication services write internal
+ data files. If deploying within a JBossAS instance, leave
+ this undefined, and set this as a configuration override
+ property in the server-comm-service.xml deployment
+ configuration file. This will allow you to use the
+ ${jboss.server.data.dir} replacement variable as the data
+ directory location.
+ -->
+ <!--
+ <entry key="rhq.communications.data-directory" value="data" />
+ -->
+
+ <!--
+ _______________________________________________________________
+ rhq.communications.global-concurrency-limit
+
+ The maximum number of incoming commands that are allowed to be
+ received concurrently. Any extra commands received over this
+ amount will be dropped and the client will be asked to
+ resend it later.
+ -->
+ <entry key="rhq.communications.global-concurrency-limit" value="200" />
+
+ <!--
+ _______________________________________________________________
+ rhq.communications.multicast-detector.enabled
+ rhq.communications.multicast-detector.multicast-address
+ rhq.communications.multicast-detector.bind-address
+ rhq.communications.multicast-detector.port
+ rhq.communications.multicast-detector.default-time-delay
+ rhq.communications.multicast-detector.heartbeat-time-delay
+
+ The multicast detector configuration. This is the service that
+ listens for new remote servers/agents coming on and going offline
+ and is required if you want agent auto-detection. If you do not
+ have auto-detection enabled or your network will not
+ support multicast traffic, you should disable the multicast
+ detector.
+
+ The multicast-address is used to broadcast detection messages.
+ To be more specific, it is the IP address of the
+ multicast group the detector will join. The bind-address
+ is the IP that is bound by the network interface.
+
+ The detector will send heartbeat messages every X milliseconds
+ (this is the heartbeat-time-delay). If external servers'
+ detectors do not send their heartbeat messages within the
+ default-time-delay, our detector will assume that external
+ server has gone down. These settings affect the timeliness
+ of our auto-detection mechanism.
+ -->
+ <entry key="rhq.communications.multicast-detector.enabled" value="false" />
+ <entry key="rhq.communications.multicast-detector.multicast-address" value="224.16.16.16" />
+ <entry key="rhq.communications.multicast-detector.bind-address" value="0.0.0.0" />
+ <entry key="rhq.communications.multicast-detector.port" value="16162" />
+ <entry key="rhq.communications.multicast-detector.default-time-delay" value="5000" />
+ <entry key="rhq.communications.multicast-detector.heartbeat-time-delay" value="1000" />
+
+ <!--
+ _______________________________________________________________
+ rhq.communications.connector.rhqtype
+ rhq.communications.connector.transport
+ rhq.communications.connector.bind-port
+ rhq.communications.connector.bind-address
+ rhq.communications.connector.transport-params
+ rhq.communications.connector.lease-period
+
+ The server connector configuration. This is the service that
+ listens for incoming agent requests and passes them to the
+ appropriate server-side components for processing. See the
+ JBoss/Remoting documentation for a full list of options
+ that can be specified. Note that because this is an XML file,
+ you must specify "&" in the transport-params value
+ when needing an ampersand to separate the parameters.
+ -->
+ <entry key="rhq.communications.connector.rhqtype" value="server" />
+ <entry key="rhq.communications.connector.transport" value="servlet" />
+ <entry key="rhq.communications.connector.bind-port" value="7080" />
+ <entry key="rhq.communications.connector.transport-params" value="/jboss-remoting-servlet-invoker/ServerInvokerServlet" />
+ <!--
+ <entry key="rhq.communications.connector.bind-address" value="127.0.0.1" />
+ <entry key="rhq.communications.connector.lease-period" value="5000" />
+ -->
+
+ <!--
+ _______________________________________________________________
+ rhq.communications.connector.security.secure-socket-protocol
+ rhq.communications.connector.security.keystore.file
+ rhq.communications.connector.security.keystore.algorithm
+ rhq.communications.connector.security.keystore.type
+ rhq.communications.connector.security.keystore.password
+ rhq.communications.connector.security.keystore.key-password
+ rhq.communications.connector.security.keystore.alias
+ rhq.communications.connector.security.truststore.file
+ rhq.communications.connector.security.truststore.algorithm
+ rhq.communications.connector.security.truststore.type
+ rhq.communications.connector.security.truststore.password
+ rhq.communications.connector.security.client-auth-mode
+
+ rhq.server.client.security.secure-socket-protocol
+ rhq.server.client.security.keystore.file
+ rhq.server.client.security.keystore.algorithm
+ rhq.server.client.security.keystore.type
+ rhq.server.client.security.keystore.password
+ rhq.server.client.security.keystore.key-password
+ rhq.server.client.security.keystore.alias
+ rhq.server.client.security.truststore.file
+ rhq.server.client.security.truststore.algorithm
+ rhq.server.client.security.truststore.type
+ rhq.server.client.security.truststore.password
+ rhq.server.client.security.server-auth-mode-enabled
+
+ These are the settings that are used if SSL is to be used for
+ either the server or client communications. These can be left
+ unset since the defaults will normally suffice. These
+ properties are here just in case some use case occurs that
+ require one or more of these settings to be customized.
+
+ Note that if client-auth-mode is specified, it must be one of:
+ "none", "want", "need". To support Tomcat syntax, "true" can be used
+ in place of "need" and "false" can be used in place of "none".
+ -->
+ <!--
+ <entry key="rhq.communications.connector.security.secure-socket-protocol" value="TLS" />
+ <entry key="rhq.communications.connector.security.keystore.file" value="data/keystore.dat" />
+ <entry key="rhq.communications.connector.security.keystore.algorithm" value="SunX509" />
+ <entry key="rhq.communications.connector.security.keystore.type" value="JKS" />
+ <entry key="rhq.communications.connector.security.keystore.password" value="rhqpwd" />
+ <entry key="rhq.communications.connector.security.keystore.key-password" value="rhqpwd" />
+ <entry key="rhq.communications.connector.security.keystore.alias" value="rhq" />
+ <entry key="rhq.communications.connector.security.truststore.file" value="data/truststore.dat" />
+ <entry key="rhq.communications.connector.security.truststore.algorithm" value="SunX509" />
+ <entry key="rhq.communications.connector.security.truststore.type" value="JKS" />
+ <entry key="rhq.communications.connector.security.truststore.password" value="" />
+ <entry key="rhq.communications.connector.security.client-auth-mode" value="none" />
+
+ <entry key="rhq.server.client.security.secure-socket-protocol" value="TLS" />
+ <entry key="rhq.server.client.security.keystore.file" value="data/keystore.dat" />
+ <entry key="rhq.server.client.security.keystore.algorithm" value="SunX509" />
+ <entry key="rhq.server.client.security.keystore.type" value="JKS" />
+ <entry key="rhq.server.client.security.keystore.password" value="rhqpwd" />
+ <entry key="rhq.server.client.security.keystore.alias" value="rhq" />
+ <entry key="rhq.server.client.security.keystore.key-password" value="rhqpwd" />
+ <entry key="rhq.server.client.security.truststore.file" value="data/truststore.dat" />
+ <entry key="rhq.server.client.security.truststore.algorithm" value="SunX509" />
+ <entry key="rhq.server.client.security.truststore.type" value="JKS" />
+ <entry key="rhq.server.client.security.truststore.password" value="" />
+ <entry key="rhq.server.client.security.server-auth-mode-enabled" value="false" />
+ -->
+
+ <!--
+ _______________________________________________________________
+ rhq.communications.remote-stream-max-idle-time-msecs
+
+ The maximum amount of milliseconds a remoted stream
+ is allowed to be idle before it is automatically closed and
+ removed from the server. This means that a client must
+ attempt to access the remoted stream every X milliseconds
+ (where X is the value of this setting) or that stream will no
+ longer be available. Note that this does not mean a client
+ must read or write the entire stream in this amount of time,
+ it only means a client must make a request on the stream every
+ X milliseconds (be it to read or write one byte, see how many
+ bytes are available to be read, etc).
+ -->
+ <entry key="rhq.communications.remote-stream-max-idle-time-msecs" value="300000" />
+
+ <!--
+ _______________________________________________________________
+ rhq.communications.command-service-directory.allow-dynamic-discovery
+
+ Flag to allow new command services to be added to the command
+ services directory during runtime. If this is false, only
+ those services defined in the
+ rhq.communications.command-services preference will be available
+ during the lifetime of the command service directory.
+ -->
+ <entry key="rhq.communications.command-service-directory.allow-dynamic-discovery" value="true" />
+
+ <!--
+ _______________________________________________________________
+ rhq.communications.command-services
+
+ Command Services that are to be added immediately at startup.
+ -->
+ <entry key="rhq.communications.command-services" value="org.rhq.enterprise.communications.command.impl.echo.server.EchoCommandService, org.rhq.enterprise.communications.command.impl.identify.server.IdentifyCommandService" />
+
+ <!--
+ _______________________________________________________________
+ rhq.communications.remote-pojos
+
+ Objects that are to be created and their remote interfaces
+ deployed immediately at startup. The format of the value is
+ a comma separated list of implementation/interface names:
+ class.to.instantiate.via.noarg.constructor:interface.to.expose
+ -->
+ <entry key="rhq.communications.remote-pojos"
+ value="org.rhq.enterprise.communications.PingImpl:org.rhq.enterprise.communications.Ping,org.rhq.enterprise.server.core.CoreServerServiceImpl:org.rhq.core.clientapi.server.core.CoreServerService,org.rhq.enterprise.server.discovery.DiscoveryServerServiceImpl:org.rhq.core.clientapi.server.discovery.DiscoveryServerService,org.rhq.enterprise.server.measurement.MeasurementServerServiceImpl:org.rhq.core.clientapi.server.measurement.MeasurementServerService,org.rhq.enterprise.server.operation.OperationServerServiceImpl:org.rhq.core.clientapi.server.operation.OperationServerService,org.rhq.enterprise.server.configuration.ConfigurationServerServiceImpl:org.rhq.core.clientapi.server.configuration.ConfigurationServerService,org.rhq.enterprise.server.resource.ResourceFactoryServerServiceImpl:org.rhq.core.clientapi.server.inventory.ResourceFactoryServerService,org.rhq.enterprise.server.content.ContentServerServiceImpl:org.rhq.core.clientapi.server.content.ContentSer
verService,org.rhq.enterprise.server.event.EventServerServiceImpl:org.rhq.core.clientapi.server.event.EventServerService,org.rhq.enterprise.server.bundle.BundleServerServiceImpl:org.rhq.core.clientapi.server.bundle.BundleServerService,org.rhq.enterprise.server.drift.DriftServerServiceImpl:org.rhq.core.clientapi.server.drift.DriftServerService" />
+
+ <!--
+ _______________________________________________________________
+ rhq.communications.command-authenticator
+
+ A command authenticator class that will be used to authenticate incoming commands.
+ -->
+ <entry key="rhq.communications.command-authenticator" value="org.rhq.enterprise.server.core.comm.SecurityTokenCommandAuthenticator" />
+
+ </map>
+ </node>
+ </node>
+ </root>
+</preferences>
+
\ No newline at end of file
diff --git a/modules/enterprise/server/ear/src/main/resources/alert-email-template.txt b/modules/enterprise/server/ear/src/main/resources/alert-email-template.txt
deleted file mode 100644
index a791933..0000000
--- a/modules/enterprise/server/ear/src/main/resources/alert-email-template.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-Subject: [ALERT] priority of [@@@PRIORITY@@@] for alert [@@@ALERT_NAME@@@] on resource [@@@RESOURCE_NAME@@@]
-
-The resource @@@RESOURCE_NAME@@@ has generated the following alert:
-
-------------------------------------------
-
-Resource Name : @@@RESOURCE_NAME@@@
-Alert Name : @@@ALERT_NAME@@@
-Alert Severity : @@@PRIORITY@@@
-Alert Date/Time : @@@TIMESTAMP@@@
-Conditions: @@@CONDITIONS@@@
-
-------------------------------------------
-
-Resource Ancestry:
-
-@@@FULL_RESOURCE_HIERARCHY@@@
-
-------------------------------------------
-
-For additional details about this alert, go to @@@ALERT_URL@@@
-
-This message was delivered to you by RHQ.
diff --git a/modules/enterprise/server/ear/src/main/resources/server-comm-configuration.xml b/modules/enterprise/server/ear/src/main/resources/server-comm-configuration.xml
deleted file mode 100644
index 7f30276..0000000
--- a/modules/enterprise/server/ear/src/main/resources/server-comm-configuration.xml
+++ /dev/null
@@ -1,468 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!DOCTYPE preferences SYSTEM 'http://java.sun.com/dtd/preferences.dtd'>
-
-<!--
-==============================================================================
-RHQ Server Communications Configuration
-==============================================================================
--->
-
-<preferences EXTERNAL_XML_VERSION="1.0">
- <root type="user">
- <map />
- <node name="rhq-server">
- <map />
- <node name="default">
- <map>
- <!--
- _______________________________________________________________
- rhq.server.configuration-schema-version
-
- Defines what version of the server configuration schema this
- file conforms to. This is the schema for the rhq.server
- preferences.
- -->
- <entry key="rhq.server.configuration-schema-version" value="1" />
-
- <!--
- _______________________________________________________________
- rhq.server.agent-files-directory
-
- This defines the directory location that contains all the files
- that can be sent remotely to agents. If this is not defined,
- this effectively disables the server's ability to remotely
- send files to agents. If deploying within a JBossAS instance,
- leave this undefined, and set this as a configuration override
- property in the server-comm-service.xml
- deployment configuration file. This will allow you to use the
- ${jboss.server.home.dir} replacement variable expression
- as part of the directory location, for example.
- -->
- <!--
- <entry key="rhq.server.agent-files-directory" value="conf" />
- -->
-
- <!--
- _______________________________________________________________
- rhq.server.client.queue-size
-
- The maximum size of the client command queue - this is the
- maximum number of commands that can be queued for sending to
- an agent. If this is 0, then the queue is unbounded.
- WARNING! Setting this to 0 could lead to resources being used
- up if for some reason commands keep getting queued but are
- not getting sent.
- -->
- <entry key="rhq.server.client.queue-size" value="50000" />
-
- <!--
- _______________________________________________________________
- rhq.server.client.max-concurrent
-
- The maximum number of concurrent commands that can be in the
- process of being sent to an agent at any one time.
- -->
- <entry key="rhq.server.client.max-concurrent" value="1" />
-
- <!--
- _______________________________________________________________
- rhq.server.client.command-timeout-msecs
-
- The time in milliseconds that the client sender will wait
- before aborting a command. This is the amount of time in
- milliseconds that the agent has in order to process commands.
- This value is only the default if a command has not specified
- its own timeout. A command can override this by setting its
- own timeout in the command's configuration, so this value may
- not be used for all commands that are sent. If this value is
- less than or equal to 0, there will be no default timeout
- and commands will therefore be allowed to take as long as they
- need (again, this is the default, individual commands may
- override this and set their own timeout). While this infinite
- timeout default could conceivably cause a thread to hang
- waiting for a rogue command that never finishes, it also reduces
- the amount of short-lived threads created by the system
- and will increase throughput, dramatically in some cases.
- -->
- <entry key="rhq.server.client.command-timeout-msecs" value="600000" />
-
- <!--
- _______________________________________________________________
- rhq.server.client.retry-interval-msecs
-
- This is the minimum amount of time, in milliseconds, the client
- sender will wait before trying to resend a guaranteed command
- that previously failed. This is not a guarantee of when
- a command is retried - all that can be inferred is that a
- command that fails to be sent will not be retried until at
- least this amount of time passes.
- Note: if the sender is currently waiting in this retry pause
- period, the server will not be able to be shutdown until that
- retry period is over. In other words, if the server is asked
- to shutdown, it will wait for those commands waiting in this
- retry interval to wake up. This is to help ensure those
- commands are not lost.
- -->
- <entry key="rhq.server.client.retry-interval-msecs" value="15000" />
-
- <!--
- _______________________________________________________________
- rhq.server.client.max-retries
-
- If a guaranteed delivery message is sent, but the server fails
- to connect to the agent and deliver the message, it will
- always be retried. However, if the error was something other
- than a "cannot connect" error, the command will only be retried
- this amount of times before the command is dropped. When this
- happens, the guaranteed command will never be delivered. This
- will normally happen under very odd and rare circumstances.
- Also, this setting only effects asynchronous messages that
- are sent with guaranteed delivery. This setting has no effect
- on other messages.
- -->
- <entry key="rhq.server.client.max-retries" value="10" />
-
- <!--
- _______________________________________________________________
- rhq.server.client.command-spool-file.name
-
- This defines the name of the command spool file. This
- file must be located in the data directory (if one does not
- exist, it will be created). Note that if you do not define
- this setting, the default is to not spool commands to disk
- and thus implicitly disable guaranteed delivery.
- -->
- <!--
- <entry key="rhq.server.client.command-spool-file.name" value="command-spool.dat" />
- -->
-
- <!--
- _______________________________________________________________
- rhq.server.client.command-spool-file.params
-
- This defines the parameters for the command spool file.
- The spool file is where the server persists commands that
- are flagged for guaranteed delivery and need to be sent.
- The format is defined as "max-file-size:purge-percentage".
- The first number is the size, in bytes, of the maximum file
- size threshold. If the spool file grows larger than this, a
- "purge" will be triggered in order to shrink the file.
- The second number is the purge percentage which indicates how
- large the file is allowed to be after a purge. This is
- specified as a percentage of the first parameter - the max
- file size threshold. For example, if the max file size is
- 100000 (i.e. 100KB) and the purge percentage is 90, then when
- the spool file grows larger than 100KB, a purge will be
- triggered and the file will be shrunk to no more than
- 90% of 100KB - which is 90KB. In effect, 10KB will be freed
- to allow room for new commands to be spooled. When this
- occurs, unused space is freed first and if that does not
- free up enough space, the oldest commands in the spool file
- will be sacrificed in order to make room for the newer
- commands.
- -->
- <entry key="rhq.server.client.command-spool-file.params" value="1000000:75" />
-
- <!--
- _______________________________________________________________
- rhq.server.client.command-spool-file.compressed
-
- If this flag is true, the commands stored in the spool file
- will be compressed. This can potentially save about 30%-40% in
- disk space (give or take), however, it slows down the
- persistence mechanism considerably. Recommended setting for
- this should be false unless something on the server deployment
- box warrants disk-saving over persistence performance.
- -->
- <entry key="rhq.server.client.command-spool-file.compressed" value="false" />
-
- <!--
- _______________________________________________________________
- rhq.server.client.send-throttling
-
- If this setting is defined, it will enable send throttling to
- occur while sending commands to an agent. The format is
- defined as "max-commands:quiet-period-milliseconds"
- where the maximum commands defines the maximum number
- of commands that will be sent before the start of a quiet
- period. The quiet period defines the number of milliseconds
- in which no commands should be sent. After this duration
- expires, commands can again be sent, up to the maximum defined.
- Note that send throttling only affects those commands that
- are "throttle-able". Some commands are sent as soon as
- possible, regardless of the throttling settings.
-
- This affects sending commands synchronously and asynchronously.
- -->
- <!--
- <entry key="rhq.server.client.send-throttling" value="100:1000" />
- -->
-
- <!--
- _______________________________________________________________
- rhq.server.client.queue-throttling
-
- If this setting is defined, it will enable queue throttling to
- occur while sending commands to an agent. The format is
- defined as "max-commands-per-burst:burst-period-milliseconds"
- where the maximum commands per burst defines the maximum number
- of commands that can be dequeued within a burst period. The
- burst period defines the number of milliseconds in which the
- defined maximum number of commands can be dequeued. If more
- than the maximum number of commands are queued within this
- time period, they will wait until the next burst period starts
- before being able to be dequeued.
-
- This does not affect sending commands synchronously. It only
- effects commands queued to be sent asynchronously.
- -->
- <!--
- <entry key="rhq.server.client.queue-throttling" value="50:3000" />
- -->
-
- <!--
- _______________________________________________________________
- rhq.communications.configuration-schema-version
-
- Defines what version of the configuration schema this
- file conforms to. This is the schema for the
- rhq.communications preferences.
- -->
- <entry key="rhq.communications.configuration-schema-version" value="1" />
-
- <!--
- _______________________________________________________________
- rhq.communications.service-container.mbean-server-name
-
- Name of the MBean Server that houses the communications MBean
- services. This is actually the default domain name of the
- MBean Server and if an MBean Server has already been registered
- with this name, it will be used to house the communications
- services. If an MBean Server has not yet been registered with
- this name as its default domain, one will be created.
- If deploying within a JBossAS instance, the JBoss MBeanServer
- will be used, so this value can be left undefined since it
- will be unused.
- -->
- <!--
- <entry key="rhq.communications.service-container.mbean-server-name" value="jboss-on" />
- -->
-
- <!--
- _______________________________________________________________
- rhq.communications.data-directory
-
- The location where the communication services write internal
- data files. If deploying within a JBossAS instance, leave
- this undefined, and set this as a configuration override
- property in the server-comm-service.xml deployment
- configuration file. This will allow you to use the
- ${jboss.server.data.dir} replacement variable as the data
- directory location.
- -->
- <!--
- <entry key="rhq.communications.data-directory" value="data" />
- -->
-
- <!--
- _______________________________________________________________
- rhq.communications.global-concurrency-limit
-
- The maximum number of incoming commands that are allowed to be
- received concurrently. Any extra commands received over this
- amount will be dropped and the client will be asked to
- resend it later.
- -->
- <entry key="rhq.communications.global-concurrency-limit" value="200" />
-
- <!--
- _______________________________________________________________
- rhq.communications.multicast-detector.enabled
- rhq.communications.multicast-detector.multicast-address
- rhq.communications.multicast-detector.bind-address
- rhq.communications.multicast-detector.port
- rhq.communications.multicast-detector.default-time-delay
- rhq.communications.multicast-detector.heartbeat-time-delay
-
- The multicast detector configuration. This is the service that
- listens for new remote servers/agents coming on and going offline
- and is required if you want agent auto-detection. If you do not
- have auto-detection enabled or your network will not
- support multicast traffic, you should disable the multicast
- detector.
-
- The multicast-address is used to broadcast detection messages.
- To be more specific, it is the IP address of the
- multicast group the detector will join. The bind-address
- is the IP that is bound by the network interface.
-
- The detector will send heartbeat messages every X milliseconds
- (this is the heartbeat-time-delay). If external servers'
- detectors do not send their heartbeat messages within the
- default-time-delay, our detector will assume that external
- server has gone down. These settings affect the timeliness
- of our auto-detection mechanism.
- -->
- <entry key="rhq.communications.multicast-detector.enabled" value="false" />
- <entry key="rhq.communications.multicast-detector.multicast-address" value="224.16.16.16" />
- <entry key="rhq.communications.multicast-detector.bind-address" value="0.0.0.0" />
- <entry key="rhq.communications.multicast-detector.port" value="16162" />
- <entry key="rhq.communications.multicast-detector.default-time-delay" value="5000" />
- <entry key="rhq.communications.multicast-detector.heartbeat-time-delay" value="1000" />
-
- <!--
- _______________________________________________________________
- rhq.communications.connector.rhqtype
- rhq.communications.connector.transport
- rhq.communications.connector.bind-port
- rhq.communications.connector.bind-address
- rhq.communications.connector.transport-params
- rhq.communications.connector.lease-period
-
- The server connector configuration. This is the service that
- listens for incoming agent requests and passes them to the
- appropriate server-side components for processing. See the
- JBoss/Remoting documentation for a full list of options
- that can be specified. Note that because this is an XML file,
- you must specify "&" in the transport-params value
- when needing an ampersand to separate the parameters.
- -->
- <entry key="rhq.communications.connector.rhqtype" value="server" />
- <entry key="rhq.communications.connector.transport" value="servlet" />
- <entry key="rhq.communications.connector.bind-port" value="7080" />
- <entry key="rhq.communications.connector.transport-params" value="/jboss-remoting-servlet-invoker/ServerInvokerServlet" />
- <!--
- <entry key="rhq.communications.connector.bind-address" value="127.0.0.1" />
- <entry key="rhq.communications.connector.lease-period" value="5000" />
- -->
-
- <!--
- _______________________________________________________________
- rhq.communications.connector.security.secure-socket-protocol
- rhq.communications.connector.security.keystore.file
- rhq.communications.connector.security.keystore.algorithm
- rhq.communications.connector.security.keystore.type
- rhq.communications.connector.security.keystore.password
- rhq.communications.connector.security.keystore.key-password
- rhq.communications.connector.security.keystore.alias
- rhq.communications.connector.security.truststore.file
- rhq.communications.connector.security.truststore.algorithm
- rhq.communications.connector.security.truststore.type
- rhq.communications.connector.security.truststore.password
- rhq.communications.connector.security.client-auth-mode
-
- rhq.server.client.security.secure-socket-protocol
- rhq.server.client.security.keystore.file
- rhq.server.client.security.keystore.algorithm
- rhq.server.client.security.keystore.type
- rhq.server.client.security.keystore.password
- rhq.server.client.security.keystore.key-password
- rhq.server.client.security.keystore.alias
- rhq.server.client.security.truststore.file
- rhq.server.client.security.truststore.algorithm
- rhq.server.client.security.truststore.type
- rhq.server.client.security.truststore.password
- rhq.server.client.security.server-auth-mode-enabled
-
- These are the settings that are used if SSL is to be used for
- either the server or client communications. These can be left
- unset since the defaults will normally suffice. These
- properties are here just in case some use case occurs that
- require one or more of these settings to be customized.
-
- Note that if client-auth-mode is specified, it must be one of:
- "none", "want", "need". To support Tomcat syntax, "true" can be used
- in place of "need" and "false" can be used in place of "none".
- -->
- <!--
- <entry key="rhq.communications.connector.security.secure-socket-protocol" value="TLS" />
- <entry key="rhq.communications.connector.security.keystore.file" value="data/keystore.dat" />
- <entry key="rhq.communications.connector.security.keystore.algorithm" value="SunX509" />
- <entry key="rhq.communications.connector.security.keystore.type" value="JKS" />
- <entry key="rhq.communications.connector.security.keystore.password" value="rhqpwd" />
- <entry key="rhq.communications.connector.security.keystore.key-password" value="rhqpwd" />
- <entry key="rhq.communications.connector.security.keystore.alias" value="rhq" />
- <entry key="rhq.communications.connector.security.truststore.file" value="data/truststore.dat" />
- <entry key="rhq.communications.connector.security.truststore.algorithm" value="SunX509" />
- <entry key="rhq.communications.connector.security.truststore.type" value="JKS" />
- <entry key="rhq.communications.connector.security.truststore.password" value="" />
- <entry key="rhq.communications.connector.security.client-auth-mode" value="none" />
-
- <entry key="rhq.server.client.security.secure-socket-protocol" value="TLS" />
- <entry key="rhq.server.client.security.keystore.file" value="data/keystore.dat" />
- <entry key="rhq.server.client.security.keystore.algorithm" value="SunX509" />
- <entry key="rhq.server.client.security.keystore.type" value="JKS" />
- <entry key="rhq.server.client.security.keystore.password" value="rhqpwd" />
- <entry key="rhq.server.client.security.keystore.alias" value="rhq" />
- <entry key="rhq.server.client.security.keystore.key-password" value="rhqpwd" />
- <entry key="rhq.server.client.security.truststore.file" value="data/truststore.dat" />
- <entry key="rhq.server.client.security.truststore.algorithm" value="SunX509" />
- <entry key="rhq.server.client.security.truststore.type" value="JKS" />
- <entry key="rhq.server.client.security.truststore.password" value="" />
- <entry key="rhq.server.client.security.server-auth-mode-enabled" value="false" />
- -->
-
- <!--
- _______________________________________________________________
- rhq.communications.remote-stream-max-idle-time-msecs
-
- The maximum amount of milliseconds a remoted stream
- is allowed to be idle before it is automatically closed and
- removed from the server. This means that a client must
- attempt to access the remoted stream every X milliseconds
- (where X is the value of this setting) or that stream will no
- longer be available. Note that this does not mean a client
- must read or write the entire stream in this amount of time,
- it only means a client must make a request on the stream every
- X milliseconds (be it to read or write one byte, see how many
- bytes are available to be read, etc).
- -->
- <entry key="rhq.communications.remote-stream-max-idle-time-msecs" value="300000" />
-
- <!--
- _______________________________________________________________
- rhq.communications.command-service-directory.allow-dynamic-discovery
-
- Flag to allow new command services to be added to the command
- services directory during runtime. If this is false, only
- those services defined in the
- rhq.communications.command-services preference will be available
- during the lifetime of the command service directory.
- -->
- <entry key="rhq.communications.command-service-directory.allow-dynamic-discovery" value="true" />
-
- <!--
- _______________________________________________________________
- rhq.communications.command-services
-
- Command Services that are to be added immediately at startup.
- -->
- <entry key="rhq.communications.command-services" value="org.rhq.enterprise.communications.command.impl.echo.server.EchoCommandService, org.rhq.enterprise.communications.command.impl.identify.server.IdentifyCommandService" />
-
- <!--
- _______________________________________________________________
- rhq.communications.remote-pojos
-
- Objects that are to be created and their remote interfaces
- deployed immediately at startup. The format of the value is
- a comma separated list of implementation/interface names:
- class.to.instantiate.via.noarg.constructor:interface.to.expose
- -->
- <entry key="rhq.communications.remote-pojos"
- value="org.rhq.enterprise.communications.PingImpl:org.rhq.enterprise.communications.Ping,org.rhq.enterprise.server.core.CoreServerServiceImpl:org.rhq.core.clientapi.server.core.CoreServerService,org.rhq.enterprise.server.discovery.DiscoveryServerServiceImpl:org.rhq.core.clientapi.server.discovery.DiscoveryServerService,org.rhq.enterprise.server.measurement.MeasurementServerServiceImpl:org.rhq.core.clientapi.server.measurement.MeasurementServerService,org.rhq.enterprise.server.operation.OperationServerServiceImpl:org.rhq.core.clientapi.server.operation.OperationServerService,org.rhq.enterprise.server.configuration.ConfigurationServerServiceImpl:org.rhq.core.clientapi.server.configuration.ConfigurationServerService,org.rhq.enterprise.server.resource.ResourceFactoryServerServiceImpl:org.rhq.core.clientapi.server.inventory.ResourceFactoryServerService,org.rhq.enterprise.server.content.ContentServerServiceImpl:org.rhq.core.clientapi.server.content.ContentSer
verService,org.rhq.enterprise.server.event.EventServerServiceImpl:org.rhq.core.clientapi.server.event.EventServerService,org.rhq.enterprise.server.bundle.BundleServerServiceImpl:org.rhq.core.clientapi.server.bundle.BundleServerService,org.rhq.enterprise.server.drift.DriftServerServiceImpl:org.rhq.core.clientapi.server.drift.DriftServerService" />
-
- <!--
- _______________________________________________________________
- rhq.communications.command-authenticator
-
- A command authenticator class that will be used to authenticate incoming commands.
- -->
- <entry key="rhq.communications.command-authenticator" value="org.rhq.enterprise.server.core.comm.SecurityTokenCommandAuthenticator" />
-
- </map>
- </node>
- </node>
- </root>
-</preferences>
-
\ No newline at end of file
11 years, 9 months
[rhq] modules/enterprise
by snegrea
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryConfigurationStep.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
New commits:
commit 47f97e620781574cf19e8a9473fc82ccdb8d0833
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Fri Sep 7 10:42:58 2012 -0500
[BZ 854903] Corrected the logic to allow creation of resources without configuration.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryConfigurationStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryConfigurationStep.java
index 538aa7f..1806348 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryConfigurationStep.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryConfigurationStep.java
@@ -127,7 +127,7 @@ public class ResourceFactoryConfigurationStep extends AbstractWizardStep impleme
@Override
public boolean isNextButtonEnabled() {
- return (editor != null) && editor.isValid();
+ return (editor == null) || ((editor != null) && editor.isValid());
}
public boolean nextPage() {
11 years, 9 months
[rhq] Branch 'rhq-on-as7' - modules/enterprise
by mazz
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/upload/MultipartFilter.java | 3 +++
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/web.xml | 9 ---------
2 files changed, 3 insertions(+), 9 deletions(-)
New commits:
commit f6da9eb8f397602997c1a90f7565dadb770873bf
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Sep 6 16:25:04 2012 -0400
fix file upload
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/upload/MultipartFilter.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/upload/MultipartFilter.java
index fb2af4c..91704d2 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/upload/MultipartFilter.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/upload/MultipartFilter.java
@@ -21,6 +21,7 @@ package org.rhq.enterprise.gui.common.upload;
import java.io.IOException;
import java.util.List;
import java.util.Map;
+
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@@ -28,6 +29,7 @@ import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
+
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
@@ -37,6 +39,7 @@ import org.apache.commons.fileupload.servlet.ServletFileUpload;
* Filter used to handle multipart/form-data requests.
*
* @author Jason Dobies
+ * @deprecated this should be deleted, it was used prior to JSF
*/
public class MultipartFilter implements Filter {
// Filter Implementation --------------------------------------------
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/web.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/web.xml
index 0539e78..06220bf 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/web.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/web.xml
@@ -203,15 +203,6 @@
</context-param>
<!-- Allows completeUpload of files through JSF (i.e. software uploads) -->
- <filter>
- <filter-name>MultipartFilter</filter-name>
- <filter-class>org.rhq.enterprise.gui.common.upload.MultipartFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>MultipartFilter</filter-name>
- <url-pattern>/rhq/resource/*</url-pattern>
- </filter-mapping>
-
<!-- The stuff needed for ajax4jsf / richfaces -->
<filter>
11 years, 9 months
[rhq] Branch 'bug/783603' - 205 commits - .classpath etc/standalone-pc modules/core modules/enterprise modules/helpers modules/plugins pom.xml
by mazz
.classpath | 5
etc/standalone-pc/README.txt | 3
etc/standalone-pc/standalone.bat | 9
etc/standalone-pc/standalone.sh | 12
modules/core/arquillian-integration/archive/pom.xml | 6
modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginArchiveImpl.java | 28
modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginDescriptorContainer.java | 16
modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/drift/DriftServerService.java | 5
modules/core/dbutils/pom.xml | 2
modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml | 2
modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml | 29
modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java | 2
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java | 166 +
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertySimple.java | 2
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java | 20
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java | 2
modules/core/domain/src/main/java/org/rhq/core/domain/measurement/Availability.java | 4
modules/core/domain/src/main/java/org/rhq/core/domain/resource/Agent.java | 5
modules/core/domain/src/main/java/org/rhq/core/domain/resource/composite/ResourceIdWithAgentComposite.java | 48
modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/DuplicateExpressionTypeException.java | 38
modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/InvalidExpressionException.java | 38
modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/ResourceGroup.java | 3
modules/core/domain/src/main/java/org/rhq/core/domain/util/collection/ArrayUtils.java | 75
modules/core/domain/src/test/java/org/rhq/core/domain/drift/JPADriftChangeSetTest.java | 9
modules/core/native-system/src/main/java/org/rhq/core/system/pquery/ProcessInfoQuery.java | 2
modules/core/native-system/src/test/java/org/rhq/core/system/pquery/ProcessInfoQueryTest.java | 55
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/InventoryContext.java | 65
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java | 16
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java | 4
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java | 13
modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java | 12
modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java | 175 +
modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java | 18
modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/SingleResourceDiscoveryComponent.java | 30
modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ821058DiscoveryComponent.java | 51
modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java | 104
modules/core/plugin-container-itest/src/test/resources/arquillian.xml | 1
modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml | 29
modules/core/plugin-container-itest/src/test/resources/single-metric-rhq-plugin.xml | 21
modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml | 27
modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java | 18
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftFilesSender.java | 42
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java | 6
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java | 12
modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java | 43
modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryContextImpl.java | 57
modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java | 49
modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java | 2
modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java | 24
modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginValidator.java | 57
modules/core/plugin-container/src/test/java/org/rhq/core/pc/bundle/BundleManagerTest.java | 2
modules/core/util/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java | 3
modules/enterprise/agent/src/etc/plugin-validator.sh | 7
modules/enterprise/agent/src/etc/rhq-agent-wrapper.sh | 40
modules/enterprise/agent/src/etc/standalone-pc.bat | 9
modules/enterprise/agent/src/etc/standalone-pc.sh | 12
modules/enterprise/binding/pom.xml | 35
modules/enterprise/binding/src/main/java/org/rhq/bindings/SandboxedScriptEngine.java | 204 -
modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java | 211 +
modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java | 55
modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java | 53
modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java | 92
modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java | 102
modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManager.java | 133 +
modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManagers.java | 133 -
modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/JsEngineInitializer.java | 104
modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/ScriptEngineInitializer.java | 82
modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java | 63
modules/enterprise/binding/src/main/java/org/rhq/bindings/script/RepoScriptSourceProvider.java | 127
modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java | 524 +++-
modules/enterprise/binding/src/main/java/org/rhq/bindings/util/MultiScriptSourceProvider.java | 66
modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptAssert.java | 36
modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptUtil.java | 5
modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedClass.java | 38
modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedMethod.java | 41
modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SummaryFilter.java | 8
modules/enterprise/binding/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider | 1
modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java | 152 -
modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java | 56
modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptedTestBase.java | 220 +
modules/enterprise/binding/src/test/java/org/rhq/bindings/client/AbstractRhqFacadeProxyTest.java | 185 +
modules/enterprise/binding/src/test/java/org/rhq/bindings/script/RepoScriptSourceProviderTest.java | 160 +
modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java | 351 ++
modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java | 270 +-
modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/AbstractPerspectiveResourceUIBean.java | 4
modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/PerspectiveClientUIBean.java | 2
modules/enterprise/gui/coregui/pom.xml | 13
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java | 13
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java | 40
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java | 5
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewNotificationEditor.java | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java | 14
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java | 11
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesDataSource.java | 28
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java | 38
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java | 480 +--
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/EnhancedSearchBarItem.java | 62
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/ImgButtonItem.java | 67
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/SearchBarItem.java | 62
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java | 35
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java | 116
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/DynamicCallbackFormImplIE8.java | 50
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/MeasurementDataGWTService.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java | 3
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java | 7
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java | 14
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListView.java | 43
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java | 21
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java | 15
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java | 19
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java | 33
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java | 7
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java | 21
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java | 8
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java | 45
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/traits/TraitsView.java | 107
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/wizard/GroupCreateStep.java | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/AncestryUtil.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java | 116
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java | 17
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java | 84
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java | 26
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java | 39
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java | 25
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java | 17
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java | 18
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java | 86
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/AbstractSearchBar.java | 3
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/FlexSearchBar.java | 28
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/SearchBar.java | 586 ----
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/favorites/SavedSearchGrid.java | 11
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/suggest/SuggestTextBox_v3.java | 45
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/AbstractSearchStrategy.java | 91
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java | 246 +
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java | 279 ++
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java | 158 +
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationFactory.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java | 24
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java | 40
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java | 32
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/rpc/TrackingRequestCallback.java | 8
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/MeasurementDataGWTServiceImpl.java | 9
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java | 14
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java | 13
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml | 20
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties | 13
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties | 13
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties | 13
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties | 13
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties | 13
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties | 13
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties | 13
modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html | 3
modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.7.2.min.js | 4
modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-1.6.js | 1271 ----------
modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-2.0.min.js | 5
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java | 2
modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/advisoryInfo-plain.xhtml | 3
modules/enterprise/pom.xml | 2
modules/enterprise/remoting/cli/pom.xml | 40
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java | 132 -
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java | 602 ----
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java | 15
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java | 77
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/FileSystemScriptSourceProvider.java | 72
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/SamplesScriptSourceProvider.java | 67
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java | 93
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ChangeRegisteringPrintWriter.java | 233 +
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java | 48
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/DummyCodeCompletion.java | 50
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ReflectionUtility.java | 27
modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider | 2
modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml | 12
modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java | 98
modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java | 256 --
modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java | 47
modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RhqDownloadsScriptSourceProvider.java | 89
modules/enterprise/remoting/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider | 1
modules/enterprise/scripting/api/pom.xml | 173 +
modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java | 70
modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java | 84
modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java | 104
modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java | 68
modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java | 44
modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProviderFactory.java | 61
modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/util/SandboxedScriptEngine.java | 224 +
modules/enterprise/scripting/javascript/pom.xml | 230 +
modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java | 586 ++++
modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java | 163 +
modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java | 53
modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/ExternalScriptable.java | 496 +++
modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/JSAdapter.java | 361 ++
modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoCompiledScript.java | 91
modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java | 724 +++++
modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngineFactory.java | 219 +
modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ExtendedScriptException.java | 76
modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/InterfaceImplementor.java | 94
modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ScriptEngineFactoryBase.java | 62
modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/util/ScriptSourceToModuleSourceProviderAdapter.java | 75
modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory | 1
modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider | 1
modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java | 124
modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java | 190 +
modules/enterprise/scripting/javascript/src/test/resources/allow-all.policy | 3
modules/enterprise/scripting/javascript/src/test/resources/test-module1.js | 7
modules/enterprise/scripting/javascript/src/test/resources/test-module2.js | 7
modules/enterprise/scripting/pom.xml | 34
modules/enterprise/scripting/python/pom.xml | 218 +
modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineFactory.java | 41
modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java | 132 +
modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java | 54
modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonSourceProvider.java | 136 +
modules/enterprise/scripting/python/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory | 1
modules/enterprise/scripting/python/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider | 1
modules/enterprise/scripting/python/src/test/java/org/rhq/scripting/python/PythonScriptEngineInitializerTest.java | 178 +
modules/enterprise/scripting/python/src/test/resources/allow-all.policy | 3
modules/enterprise/server/client-api/pom.xml | 10
modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java | 457 ---
modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java | 13
modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java | 80
modules/enterprise/server/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider | 1
modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java | 55
modules/enterprise/server/container/src/main/bin-resources/bin/rhq-server.sh | 8
modules/enterprise/server/container/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf | 3
modules/enterprise/server/ear/pom.xml | 26
modules/enterprise/server/itests/pom.xml | 7
modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/client/security/test/JndiAccessTest.java | 3
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java | 18
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java | 19
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java | 5
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java | 13
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/FailoverListManagerBean.java | 34
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/ServerBucket.java | 5
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StatusManagerBean.java | 29
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java | 50
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java | 1
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java | 31
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerLocal.java | 3
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerRemote.java | 14
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginScanner.java | 68
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScanner.java | 16
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftServerServiceImpl.java | 20
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java | 67
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java | 15
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java | 7
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java | 81
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java | 18
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java | 83
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/InvalidExpressionException.java | 38
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java | 32
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerLocal.java | 3
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java | 27
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java | 5
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java | 67
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java | 13
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java | 93
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java | 34
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java | 6
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java | 6
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java | 28
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java | 13
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java | 15
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricAggregate.java | 11
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java | 5
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentDriftLocal.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java | 8
modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl | 8
modules/enterprise/server/jar/src/main/resources/rest_templates/listMetricDefinitions.ftl | 38
modules/enterprise/server/jar/src/main/resources/rest_templates/metricData.ftl | 12
modules/enterprise/server/jar/src/main/resources/rest_templates/metricDefinition.ftl | 52
modules/enterprise/server/jar/src/main/xsl/apiout2docbook.xsl | 3
modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl | 3
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java | 177 -
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java | 2
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java | 33
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementDataManagerTest.java | 242 +
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java | 704 +++++
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/GroupWithUncommittedTest.java | 13
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/LargeGroupCriteriaTest.java | 55
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest.java | 22
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java | 2
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java | 139 -
modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java | 97
modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java | 2
modules/enterprise/server/plugins/pom.xml | 1
modules/helpers/pluginAnnotations/pom.xml | 8
modules/helpers/pluginGen/pom.xml | 6
modules/helpers/pluginGen/src/main/resources/pom.ftl | 15
modules/helpers/rest-docs-generator/pom.xml | 5
modules/helpers/rest-docs-generator/src/main/java/org/rhq/helpers/rest_docs_generator/ClassLevelProcessor.java | 6
modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java | 1
modules/plugins/database/pom.xml | 7
modules/plugins/database/src/main/java/org/rhq/plugins/database/AbstractDatabaseComponent.java | 6
modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableComponent.java | 31
modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableDiscoveryComponent.java | 58
modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableRowDiscoveryComponent.java | 11
modules/plugins/database/src/main/java/org/rhq/plugins/database/DatabaseQueryUtility.java | 90
modules/plugins/database/src/main/resources/META-INF/rhq-plugin.xml | 59
modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java | 550 ++++
modules/plugins/database/src/test/java/org/rhq/plugins/database/H2Database.java | 79
modules/plugins/database/src/test/java/org/rhq/plugins/database/H2DatabaseDiscovery.java | 46
modules/plugins/database/src/test/java/org/rhq/plugins/database/PluginTest.java | 52
modules/plugins/database/src/test/resources/META-INF/rhq-plugin.xml | 47
modules/plugins/hardware/src/main/java/org/rhq/plugins/hardware/SmartDiskComponent.java | 2
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java | 77
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/WebApplicationContextComponent.java | 46
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java | 13
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstallationInfo.java | 47
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java | 7
modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/itest/ApplicationServerComponentTest.java | 28
modules/plugins/jboss-as-7/pom.xml | 1
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java | 56
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationLoadDelegate.java | 3
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java | 49
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConnectorDiscoveryGroupValidatorComponent.java | 83
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DatasourceComponent.java | 43
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DomainDeploymentComponent.java | 8
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HornetQComponent.java | 27
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java | 7
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JmsComponent.java | 32
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java | 2
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASDiscovery.java | 33
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsComponent.java | 2
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SocketBindingGroupComponent.java | 11
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java | 118
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java | 7
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SubsystemDiscovery.java | 61
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ThreadingComponent.java | 61
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/TransactionsComponent.java | 62
modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml | 349 +-
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java | 107
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java | 675 +++++
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java | 4
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java | 3
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java | 802 ------
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java | 5
modules/plugins/jboss-as-7/src/test/resources/test-plugin.xml | 33
modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/util/FileContentDelegate.java | 38
modules/plugins/jboss-cache-v3/src/main/java/org/rhq/plugins/jbosscache3/JBossCacheDetailDiscoveryComponent.java | 8
modules/plugins/jboss-cache-v3/src/main/resources/META-INF/rhq-plugin.xml | 2
modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ObjectNameQueryUtility.java | 75
modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ParentDefinedJMXServerNamingUtility.java | 40
modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityDelegateTest.java | 106
modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityTest.java | 13
modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlDatabaseDiscoveryComponent.java | 2
modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlTableDiscoveryComponent.java | 11
modules/plugins/mysql/src/main/resources/META-INF/rhq-plugin.xml | 1
modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java | 567 ++++
modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java | 61
modules/plugins/mysql/src/test/resources/log4j.xml | 35
modules/plugins/noop/pom.xml | 119
modules/plugins/noop/src/main/java/org/rhq/plugins/noop/NoopComponent.java | 67
modules/plugins/noop/src/main/resources/META-INF/rhq-plugin.xml | 25
modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleFlashRecoveryAreaComponent.java | 83
modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleServerComponent.java | 12
modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleTablespaceComponent.java | 83
modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml | 53
modules/plugins/oracle/src/test/java/org/rhq/plugins/oracle/ComponentTest.java | 11
modules/plugins/pattern-generator/src/main/java/org/rhq/plugins/pattern/PatternComponent.java | 45
modules/plugins/pattern-generator/src/main/resources/META-INF/rhq-plugin.xml | 1
modules/plugins/perftest/src/main/resources/META-INF/rhq-plugin.xml | 8
modules/plugins/perftest/src/main/resources/configurable-7.xml | 40
modules/plugins/platform/src/main/java/org/rhq/plugins/platform/NetworkAdapterComponent.java | 203 -
modules/plugins/pom.xml | 7
modules/plugins/snmptrapd/src/test/java/org/rhq/plugins/snmptrapd/ComponentTest.java | 5
pom.xml | 57
379 files changed, 19041 insertions(+), 6991 deletions(-)
New commits:
commit 8d36d210e044aa092e5fd0ec95b8810539a05578
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Sep 6 18:42:54 2012 -0400
fix compile errors
diff --git a/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java b/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java
index 050aa2e..2251c24 100644
--- a/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java
+++ b/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java
@@ -19,13 +19,16 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
import javax.xml.bind.JAXBElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeSuite;
+
import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
import org.rhq.core.clientapi.descriptor.configuration.ConfigurationProperty;
@@ -46,6 +49,7 @@ import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
import org.rhq.core.domain.resource.ProcessScan;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pc.CollectorThreadPool;
import org.rhq.core.pc.PluginContainer;
import org.rhq.core.pc.PluginContainerConfiguration;
import org.rhq.core.pc.availability.AvailabilityContextImpl;
@@ -73,10 +77,6 @@ import org.rhq.core.system.ProcessInfo;
import org.rhq.core.system.SystemInfo;
import org.rhq.core.system.SystemInfoFactory;
import org.rhq.core.system.pquery.ProcessInfoQuery;
-import org.testng.annotations.AfterSuite;
-import org.testng.annotations.AfterTest;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeSuite;
/**
* Base class for RHQ Component Testing.
@@ -136,7 +136,7 @@ public abstract class ComponentTest {
private final String pluginContainerName = "rhq";
private final OperationContext operationContext = new OperationContextImpl(0);
private final ContentContext contentContext = new ContentContextImpl(0);
- private final Executor availCollectorThreadPool = Executors.newCachedThreadPool();
+ private final CollectorThreadPool availCollectorThreadPool = new CollectorThreadPool();
private PluginContainerDeployment pluginContainerDeployment = null;
private Resource platform;
private ResourceContainer platformContainer;
@@ -279,14 +279,14 @@ public abstract class ComponentTest {
String rclassname = pmm.getComponentClass(type);
ResourceComponent component = (ResourceComponent) Class.forName(rclassname).newInstance();
- availabilityContext = new AvailabilityContextImpl(cresource,availCollectorThreadPool);
+ availabilityContext = new AvailabilityContextImpl(cresource, availCollectorThreadPool.getExecutor());
inventoryContext = new InventoryContextImpl(cresource);
EventContext eventContext = new EventContextImpl(resource);
ResourceContext context = new ResourceContext(cresource, parentComponent,
null, rdc, systemInfo, temporaryDirectory, dataDirectory,
pluginContainerName, eventContext, operationContext, contentContext,
- availabilityContext, inventoryContext, pluginContainerDeployment);
+ availabilityContext, inventoryContext, availCollectorThreadPool.getExecutor(), pluginContainerDeployment);
component.start(context);
components.put(component, cresource);
diff --git a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
index 610cb61..fa5fa58 100644
--- a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
+++ b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
@@ -38,13 +38,16 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
import javax.xml.bind.JAXBElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeSuite;
+
import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
import org.rhq.core.clientapi.descriptor.configuration.ConfigurationProperty;
@@ -65,6 +68,7 @@ import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
import org.rhq.core.domain.resource.ProcessScan;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pc.CollectorThreadPool;
import org.rhq.core.pc.PluginContainer;
import org.rhq.core.pc.PluginContainerConfiguration;
import org.rhq.core.pc.availability.AvailabilityContextImpl;
@@ -92,10 +96,6 @@ import org.rhq.core.system.ProcessInfo;
import org.rhq.core.system.SystemInfo;
import org.rhq.core.system.SystemInfoFactory;
import org.rhq.core.system.pquery.ProcessInfoQuery;
-import org.testng.annotations.AfterSuite;
-import org.testng.annotations.AfterTest;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeSuite;
/**
* Base class for RHQ Component Testing.
@@ -155,7 +155,7 @@ public abstract class ComponentTest {
private final String pluginContainerName = "rhq";
private final OperationContext operationContext = new OperationContextImpl(0);
private final ContentContext contentContext = new ContentContextImpl(0);
- private final Executor availCollectorThreadPool = Executors.newCachedThreadPool();
+ private final CollectorThreadPool availCollectorThreadPool = new CollectorThreadPool();
private PluginContainerDeployment pluginContainerDeployment = null;
private Resource platform;
private ResourceContainer platformContainer;
@@ -295,14 +295,15 @@ public abstract class ComponentTest {
String rclassname = pmm.getComponentClass(type);
ResourceComponent component = (ResourceComponent) Class.forName(rclassname).newInstance();
- AvailabilityContext availContext = new AvailabilityContextImpl(cresource,availCollectorThreadPool);
+ AvailabilityContext availContext = new AvailabilityContextImpl(cresource,
+ availCollectorThreadPool.getExecutor());
InventoryContext inventoryContext = new InventoryContextImpl(cresource);
EventContext eventContext = new EventContextImpl(resource);
ResourceContext context = new ResourceContext(cresource, parentComponent,
null, rdc, systemInfo, temporaryDirectory, dataDirectory,
pluginContainerName, eventContext, operationContext, contentContext,
- availContext, inventoryContext,pluginContainerDeployment);
+ availContext, inventoryContext, availCollectorThreadPool.getExecutor(), pluginContainerDeployment);
component.start(context);
components.put(component, cresource);
commit 3bf984baa2d579e168a89a8cb4e5e9aee3fd6f0f
Merge: 65df953 6da6f84
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Sep 6 17:44:56 2012 -0400
Merge remote-tracking branch 'origin/master' into bug/783603
commit 6da6f84c7fd682c5c1e2f3d2c2eedc40989c381a
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Sep 6 17:43:32 2012 -0400
add mysql test classes to eclipse
diff --git a/.classpath b/.classpath
index 2094bae..a5a5568 100644
--- a/.classpath
+++ b/.classpath
@@ -107,6 +107,7 @@
<classpathentry kind="src" path="modules/plugins/postgres/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/postgres/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/mysql/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/mysql/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/oracle/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/oracle/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/apache/src/main/java"/>
commit e5bf5151f28aa3c5f973e01963a610629cc389dc
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Sep 6 17:34:32 2012 -0400
add database test module to eclipse
diff --git a/.classpath b/.classpath
index 9ce50a8..2094bae 100644
--- a/.classpath
+++ b/.classpath
@@ -103,6 +103,7 @@
<classpathentry kind="src" path="modules/plugins/jboss-cache/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/jboss-cache-v3/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/database/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/database/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/postgres/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/postgres/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/mysql/src/main/java"/>
commit 65df9532d020e508a57771bf3fb21352a864e57d
Merge: 0945945 84b8df3
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Sep 6 17:20:02 2012 -0400
Merge remote-tracking branch 'origin/master' into bug/783603
commit 84b8df302149f20bd6eef423d55ec3e26581c283
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Sep 6 16:55:24 2012 -0400
Eclipse .classpath update
diff --git a/.classpath b/.classpath
index 0516dd7..9ce50a8 100644
--- a/.classpath
+++ b/.classpath
@@ -270,7 +270,7 @@
<classpathentry exported="true" kind="var" path="M2_REPO/com/google/gwt/gwt-user/2.4.0/gwt-user-2.4.0.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/com/google/gwt/gwt-dev/2.4.0/gwt-dev-2.4.0.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/com/smartgwt/smartgwt/3.0/smartgwt-3.0.jar"/>
- <classpathentry exported="true" kind="var" path="M2_REPO/ca/nanometrics/gflot/1.0.0/gflot-1.0.0.jar"/>
+ <classpathentry exported="true" kind="var" path="M2_REPO/com/googlecode/gflot/gflot/2.4.2/gflot-2.4.2.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/com/jcraft/jsch/0.1.29/jsch-0.1.29.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/commons-jxpath/commons-jxpath/1.3/commons-jxpath-1.3.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/org/dbunit/dbunit/2.4.8/dbunit-2.4.8.jar"/>
commit 0945945e2fa7dca6bab91637d15b443af5cfd83e
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Sep 6 16:54:21 2012 -0400
fix compile errors after merge/conflict resolution
diff --git a/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java b/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java
index 118d514..47f43bd 100644
--- a/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java
+++ b/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java
@@ -86,7 +86,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null,
- mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
+ mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -152,7 +152,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parent1ResourceContext, null,
- null, mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
+ null, mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -206,7 +206,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null,
- mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
+ mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -260,7 +260,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null,
- mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
+ mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -314,7 +314,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null,
- mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
+ mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -377,7 +377,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parent1ResourceContext, null,
- null, mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
+ null, mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getFutureChildResourceDataDirectory(inputChildResourceKey);
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/bundle/BundleManagerTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/bundle/BundleManagerTest.java
index 4b37c89..f41e3e7 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/bundle/BundleManagerTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/bundle/BundleManagerTest.java
@@ -478,7 +478,7 @@ public class BundleManagerTest {
@SuppressWarnings("unchecked")
private static class MockResourceContext extends ResourceContext {
public MockResourceContext(Resource resource) {
- super(resource, null, null, null, null, null, null, null, null, null, null, null, null, null);
+ super(resource, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
}
}
}
\ No newline at end of file
diff --git a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
index daf5463..1289c81 100644
--- a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
+++ b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
@@ -102,6 +102,7 @@ public class AntBundlePluginComponentTest {
@SuppressWarnings({ "rawtypes", "unchecked" })
ResourceContext<?> context = new ResourceContext(resource, null, null, null,
SystemInfoFactory.createJavaSystemInfo(), tmpDir, null, "antBundleTestPC", null, null, null, null, null,
+ null,
null);
this.plugin.start(context);
}
diff --git a/modules/plugins/hardware/src/main/java/org/rhq/plugins/hardware/SmartDiskComponent.java b/modules/plugins/hardware/src/main/java/org/rhq/plugins/hardware/SmartDiskComponent.java
index bde1627..6ede21d 100644
--- a/modules/plugins/hardware/src/main/java/org/rhq/plugins/hardware/SmartDiskComponent.java
+++ b/modules/plugins/hardware/src/main/java/org/rhq/plugins/hardware/SmartDiskComponent.java
@@ -116,7 +116,7 @@ public class SmartDiskComponent implements ResourceComponent, MeasurementFacet {
public static void main(String[] args) throws Exception {
SmartDiskComponent sdc = new SmartDiskComponent();
sdc.start(new ResourceContext(new Resource("/dev/sda", "foo", new ResourceType()), null, null, null, null, null,
- null, null, null, null, null, null, null, PluginContainerDeployment.AGENT));
+ null, null, null, null, null, null, null, null, PluginContainerDeployment.AGENT));
sdc.getValues(null, null);
}
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java
index 28a8688..28d7d21 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java
@@ -346,7 +346,7 @@ public class UploadAndDeployTest extends AbstractIntegrationTest {
StandaloneASComponent parentComponent = new StandaloneASComponent();
parentComponent.setConnection(getASConnection());
ResourceContext context = new ResourceContext(resource, parentComponent, null, null, null, null, null, null,
- null, null, null, null, null, null);
+ null, null, null, null, null, null, null);
bc.start(context);
String bytes_value = uploadToAs(TEST_WAR_PATH);
@@ -381,7 +381,7 @@ public class UploadAndDeployTest extends AbstractIntegrationTest {
StandaloneASComponent parentComponent = new StandaloneASComponent();
parentComponent.setConnection(getASConnection());
ResourceContext context = new ResourceContext(resource, parentComponent, null, null, null, null, null, null,
- null, null, null, null, null, null);
+ null, null, null, null, null, null, null);
bc.start(context);
String bytes_value = uploadToAs(TEST_WAR_PATH);
commit 50af0c6a223dbaf8201dc3caccb8aa23d0724d71
Merge: 7c9cbda 42c00f9
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Sep 6 16:14:08 2012 -0400
Merge remote-tracking branch 'origin/master' into bug/783603
Conflicts:
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java
modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
modules/plugins/oracle/src/test/java/org/rhq/plugins/oracle/ComponentTest.java
modules/plugins/snmptrapd/src/test/java/org/rhq/plugins/snmptrapd/ComponentTest.java
diff --cc modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java
index 7af868d,76ccf39..24952ed
--- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java
@@@ -86,7 -83,7 +86,8 @@@ public class ResourceContext<T extends
private final OperationContext operationContext;
private final ContentContext contentContext;
private final AvailabilityContext availabilityContext;
+ private final ScheduledExecutorService collectionThreadPool;
+ private final InventoryContext inventoryContext;
private final PluginContainerDeployment pluginContainerDeployment;
private final ResourceTypeProcesses trackedProcesses;
@@@ -160,8 -153,7 +161,8 @@@
public ResourceContext(Resource resource, T parentResourceComponent, ResourceContext<?> parentResourceContext,
ResourceDiscoveryComponent<T> resourceDiscoveryComponent, SystemInfo systemInfo, File temporaryDirectory,
File dataDirectory, String pluginContainerName, EventContext eventContext, OperationContext operationContext,
- ContentContext contentContext, AvailabilityContext availabilityContext,
+ ContentContext contentContext, AvailabilityContext availabilityContext, InventoryContext inventoryContext,
+ ScheduledExecutorService collectionThreadPool,
PluginContainerDeployment pluginContainerDeployment) {
this.resourceKey = resource.getResourceKey();
@@@ -186,7 -178,7 +187,8 @@@
this.operationContext = operationContext;
this.contentContext = contentContext;
this.availabilityContext = availabilityContext;
+ this.collectionThreadPool = collectionThreadPool;
+ this.inventoryContext = inventoryContext;
String parentResourceUuid = "";
if (resource.getParentResource() != null) {
@@@ -590,4 -581,4 +602,4 @@@
return messageDigest.getDigestString();
}
--}
++}
diff --cc modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java
index 94a9d00,471978c..b674d11
--- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java
@@@ -60,12 -60,11 +61,13 @@@ public class ResourceUpgradeContext<T e
T parentResourceComponent, ResourceDiscoveryComponent<T> resourceDiscoveryComponent, SystemInfo systemInfo,
File temporaryDirectory, File dataDirectory, String pluginContainerName, EventContext eventContext,
OperationContext operationContext, ContentContext contentContext, AvailabilityContext availabilityContext,
- InventoryContext inventoryContext, PluginContainerDeployment pluginContainerDeployment) {
++ InventoryContext inventoryContext,
+ ScheduledExecutorService collectorThreadPool,
+ PluginContainerDeployment pluginContainerDeployment) {
super(resource, parentResourceComponent, parentResourceContext, resourceDiscoveryComponent, systemInfo,
temporaryDirectory, dataDirectory, pluginContainerName, eventContext, operationContext, contentContext,
- availabilityContext, collectorThreadPool, pluginContainerDeployment);
- availabilityContext, inventoryContext, pluginContainerDeployment);
++ availabilityContext, inventoryContext, collectorThreadPool, pluginContainerDeployment);
this.resourceConfiguration = resource.getResourceConfiguration();
this.name = resource.getName();
diff --cc modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
index dd0157e,b3f7fa9..8c52d6c
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
@@@ -1783,8 -1803,8 +1803,9 @@@ public class InventoryManager extends A
getEventContext(resource), // for event access
getOperationContext(resource), // for operation manager access
getContentContext(resource), // for content manager access
- getAvailabilityContext(resource, this.availabilityCollectors), // for components that want to perform async avail checking
+ getAvailabilityContext(resource, this.collectors.getExecutor()), // for components that want to perform async avail checking
+ getInventoryContext(resource),
+ this.collectors.getExecutor(), // for components that want to perform async measurement collection
this.configuration.getPluginContainerDeployment()); // helps components make determinations of what to do
}
@@@ -1803,8 -1823,8 +1824,9 @@@
getEventContext(resource), // for event access
getOperationContext(resource), // for operation manager access
getContentContext(resource), // for content manager access
- getAvailabilityContext(resource, this.availabilityCollectors), // for components that want avail manager access
+ getAvailabilityContext(resource, this.collectors.getExecutor()), // for components that want avail manager access
+ getInventoryContext(resource),
+ this.collectors.getExecutor(), // for components that want to perform async measurement collection
this.configuration.getPluginContainerDeployment()); // helps components make determinations of what to do
}
diff --cc modules/plugins/oracle/src/test/java/org/rhq/plugins/oracle/ComponentTest.java
index 4f1ef84,569bd09..c62273d
--- a/modules/plugins/oracle/src/test/java/org/rhq/plugins/oracle/ComponentTest.java
+++ b/modules/plugins/oracle/src/test/java/org/rhq/plugins/oracle/ComponentTest.java
@@@ -133,11 -134,11 +135,12 @@@ public abstract class ComponentTest
ResourceDiscoveryComponent resourceDiscoveryComponent = new NothingDiscoveringDiscoveryComponent();
EventContext eventContext = new EventContextImpl(resource);
- AvailabilityContext availContext = new AvailabilityContextImpl(resource, Executors.newCachedThreadPool());
+ ScheduledExecutorService collectorThreadPool = Executors.newScheduledThreadPool(1);
+ AvailabilityContext availContext = new AvailabilityContextImpl(resource, collectorThreadPool);
+ InventoryContext inventoryContext = new InventoryContextImpl(resource);
ResourceContext context = new ResourceContext(resource, parentResourceComponent, parentResourceContext,
resourceDiscoveryComponent, systemInfo, temporaryDirectory, dataDirectory, pluginContainerName,
- eventContext, operationContext, contentContext, availContext, collectorThreadPool,
- eventContext, operationContext, contentContext, availContext, inventoryContext,
++ eventContext, operationContext, contentContext, availContext, inventoryContext, collectorThreadPool,
pluginContainerDeployment);
component.start(context);
@@@ -171,11 -172,11 +174,12 @@@
log.debug("rdc=" + rdc);
EventContext eventContext = new EventContextImpl(resource);
- AvailabilityContext availContext = new AvailabilityContextImpl(resource, Executors.newCachedThreadPool());
+ ScheduledExecutorService collectorThreadPool = Executors.newScheduledThreadPool(1);
+ AvailabilityContext availContext = new AvailabilityContextImpl(resource, collectorThreadPool);
+ InventoryContext inventoryContext = new InventoryContextImpl(resource);
ResourceContext context = new ResourceContext(resource, component, parentContext, resourceDiscoveryComponent,
systemInfo, temporaryDirectory, dataDirectory, pluginContainerName, eventContext, operationContext,
- contentContext, availContext, collectorThreadPool, pluginContainerDeployment);
- contentContext, availContext, inventoryContext, pluginContainerDeployment);
++ contentContext, availContext, inventoryContext, collectorThreadPool, pluginContainerDeployment);
ResourceDiscoveryContext resourceDiscoveryContext = new ResourceDiscoveryContext(resourceType, component,
context, systemInfo, Collections.emptyList(), Collections.emptyList(), pluginContainerName,
pluginContainerDeployment);
@@@ -203,12 -204,11 +207,13 @@@
ResourceComponent component = (ResourceComponent) Class.forName(rclassname).newInstance();
EventContext eventContext = new EventContextImpl(resource);
- AvailabilityContext availContext = new AvailabilityContextImpl(resource, Executors.newCachedThreadPool());
+ ScheduledExecutorService collectorThreadPool = Executors.newScheduledThreadPool(1);
+ AvailabilityContext availContext = new AvailabilityContextImpl(resource, collectorThreadPool);
+ InventoryContext inventoryContext = new InventoryContextImpl(resource);
ResourceContext context = new ResourceContext(cresource, parentComponent, parentContext,
resourceDiscoveryComponent, systemInfo, temporaryDirectory, dataDirectory, pluginContainerName,
- eventContext, operationContext, contentContext, availContext, collectorThreadPool,
- eventContext, operationContext, contentContext, availContext, inventoryContext, pluginContainerDeployment);
++ eventContext, operationContext, contentContext, availContext, inventoryContext, collectorThreadPool,
+ pluginContainerDeployment);
component.start(context);
components.put(component, cresource);
diff --cc modules/plugins/snmptrapd/src/test/java/org/rhq/plugins/snmptrapd/ComponentTest.java
index cfd64fb,cd90737..555263f
--- a/modules/plugins/snmptrapd/src/test/java/org/rhq/plugins/snmptrapd/ComponentTest.java
+++ b/modules/plugins/snmptrapd/src/test/java/org/rhq/plugins/snmptrapd/ComponentTest.java
@@@ -96,12 -97,12 +98,13 @@@ public abstract class ComponentTest
EventContext eventContext = new EventContextImpl(resource);
OperationContext operationContext = new OperationContextImpl(0);
ContentContext contentContext = new ContentContextImpl(0);
+ ScheduledExecutorService availCollectorThreadPool = Executors.newScheduledThreadPool(1);
PluginContainerDeployment pluginContainerDeployment = null;
- AvailabilityContext availContext = new AvailabilityContextImpl(resource, Executors.newCachedThreadPool());
+ AvailabilityContext availContext = new AvailabilityContextImpl(resource, availCollectorThreadPool);
+ InventoryContext inventoryContext = new InventoryContextImpl(resource);
ResourceContext context = new ResourceContext(resource, parentResourceComponent, parentResourceContext,
resourceDiscoveryComponent, systemInfo, temporaryDirectory, dataDirectory, pluginContainerName,
- eventContext, operationContext, contentContext, availContext, availCollectorThreadPool, pluginContainerDeployment);
- eventContext, operationContext, contentContext, availContext, inventoryContext, pluginContainerDeployment);
++ eventContext, operationContext, contentContext, availContext, inventoryContext, availCollectorThreadPool, pluginContainerDeployment);
Assert.assertNotNull(context.getEventContext());
component.start(context);
}
commit 42c00f9ade61af787ec4dd325b1045c6841f22bb
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Aug 27 15:25:57 2012 -0400
Update pom-template.
diff --git a/modules/helpers/pluginGen/src/main/resources/pom.ftl b/modules/helpers/pluginGen/src/main/resources/pom.ftl
index 378bd76..2434ddd 100644
--- a/modules/helpers/pluginGen/src/main/resources/pom.ftl
+++ b/modules/helpers/pluginGen/src/main/resources/pom.ftl
@@ -2,7 +2,7 @@
<#--
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-20012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -31,7 +31,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version><#if props.rhqVersion??>${props.rhqVersion}<#else >1.3.0-SNAPSHOT</#if></version><!-- TODO adjust RHQ version -->
+ <version><#if props.rhqVersion??>${props.rhqVersion}<#else >4.5.0-SNAPSHOT</#if></version><!-- TODO adjust RHQ version -->
</parent>
<groupId>org.rhq</groupId>
@@ -43,9 +43,6 @@
<description>${props.description}</description>
</#if>
- <properties>
- <rhq.version><#if props.rhqVersion??>${props.rhqVersion}<#else >1.3.0-SNAPSHOT</#if></rhq.version> <!-- TODO adjust, see above too -->
- </properties>
<build>
<plugins>
@@ -212,26 +209,26 @@
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-domain</artifactId>
- <version>${r"${rhq.version}"}</version>
+ <version>${r"${project.version}"}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-plugin-api</artifactId>
- <version>${r"${rhq.version}"}</version>
+ <version>${r"${project.version}"}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-native-system</artifactId>
- <version>${r"${rhq.version}"}</version>
+ <version>${r"${project.version}"}</version>
<scope>provided</scope>
</dependency>
<#if props.dependsOnJmxPlugin>
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-jmx-plugin</artifactId>
- <version>${r"${rhq.version}"}</version>
+ <version>${r"${project.version}"}</version>
<scope>provided</scope>
</dependency>
</#if>
commit 11fb6e5360c29a76726d7759b680220459386497
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu Aug 23 12:07:35 2012 -0400
Update plugin generator poms.
diff --git a/modules/helpers/pluginAnnotations/pom.xml b/modules/helpers/pluginAnnotations/pom.xml
index b6720cb..74800f8 100644
--- a/modules/helpers/pluginAnnotations/pom.xml
+++ b/modules/helpers/pluginAnnotations/pom.xml
@@ -7,20 +7,20 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.0</version>
+ <version>4.5.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-pluginAnnotations</artifactId>
<packaging>jar</packaging>
- <version>3.0.2-SNAPSHOT</version>
+ <version>4.5.0-SNAPSHOT</version>
<name>RHQ plugin annotations</name>
<description>Annotations to help generate plugin descriptors</description>
<build>
-
+
<plugins>
<plugin>
@@ -31,7 +31,7 @@
</configuration>
</plugin>
- <plugin>
+ <plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
diff --git a/modules/helpers/pluginGen/pom.xml b/modules/helpers/pluginGen/pom.xml
index 299550d..62bf822 100644
--- a/modules/helpers/pluginGen/pom.xml
+++ b/modules/helpers/pluginGen/pom.xml
@@ -7,14 +7,14 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.0</version>
+ <version>4.5.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-pluginGen</artifactId>
<packaging>jar</packaging>
- <version>3.0.2-SNAPSHOT</version>
+ <version>4.5.0-SNAPSHOT</version>
<name>RHQ plugin generator</name>
<description>Helper to generate plugin skeletons</description>
@@ -90,7 +90,7 @@
<dependency>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-pluginAnnotations</artifactId>
- <version>3.0.2-SNAPSHOT</version>
+ <version>4.5.0-SNAPSHOT</version>
</dependency>
</dependencies>
commit e33404e91d4b0cfc681e7816872e93c107b5d8f5
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Fri Aug 31 13:02:07 2012 +0200
[BZ 773626 - Failed to load resource composite data error when refreshing Inventory page (Unavailable Servers, Servers, etc)] handling the exception on the client side and re-fetch the data
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
index 55271c6..383602b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
@@ -171,6 +171,12 @@ public class ResourceDatasource extends RPCDataSource<Resource, ResourceCriteria
if (caught.getMessage().contains("SearchExpressionException")) {
Message message = new Message("Invalid search expression.", Message.Severity.Error);
CoreGUI.getMessageCenter().notify(message);
+ } else if (caught.getMessage().contains("PageList was passed an empty collection")) {
+ // Because of bug 773626
+ Log.warn(caught.getMessage());
+ criteria.setPageControl(new PageControl(0, getDataPageSize()));
+ executeFetch(request, response, criteria);
+ return;
} else {
CoreGUI.getErrorHandler().handleError(MSG.view_inventory_resources_loadFailed(), caught);
}
commit 1293a88ef64918b6401bd830a0739c8f22398fc9
Author: Simeon Pinder <spinder(a)fulliautomatix.conchfritter.com>
Date: Thu Aug 30 16:11:28 2012 -0400
[BZ 840512] adding logic to defend against @PostLoad logic not being called after installation as expected.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java
index 07b3467..bb00ef5 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java
@@ -122,6 +122,9 @@ public class ObfuscatedPropertySimple extends PropertySimple {
*/
@Override
public String getStringValue() {
+ if (clearTextValue == null) {
+ initClearTextValue();
+ }
return clearTextValue;
}
commit 26941dd6fb00043842ad5d4e6786b1f5ed391382
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Aug 30 11:18:30 2012 -0400
[Bug 852561 - AlertCondition.name is null in database after JON 2.4 to 3.1 upgrade]
fix merge issue
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index 94fa46f..1443b80 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -4010,20 +4010,22 @@
<!-- RHQ 4.4, JON 3.1.0 RELEASE uses DB Schema 2.121 -->
<schemaSpec version="2.122">
- <statement desc="Updating DOWN Alert Conditions to new format">
- UPDATE RHQ_ALERT_CONDITION
- SET NAME = 'AVAIL_GOES_DOWN', OPTION_STATUS = NULL
- WHERE TYPE = 'AVAILABILITY'
- AND NAME IS NULL
- AND OPTION_STATUS = 'DOWN'
- </statement>
- <statement desc="Updating UP Alert Conditions to new format">
- UPDATE RHQ_ALERT_CONDITION
- SET NAME = 'AVAIL_GOES_UP', OPTION_STATUS = NULL
- WHERE TYPE = 'AVAILABILITY'
- AND NAME IS NULL
- AND OPTION_STATUS = 'UP'
- </statement>
+ <schema-directSQL>
+ <statement desc="Updating DOWN Alert Conditions to new format">
+ UPDATE RHQ_ALERT_CONDITION
+ SET NAME = 'AVAIL_GOES_DOWN', OPTION_STATUS = NULL
+ WHERE TYPE = 'AVAILABILITY'
+ AND NAME IS NULL
+ AND OPTION_STATUS = 'DOWN'
+ </statement>
+ <statement desc="Updating UP Alert Conditions to new format">
+ UPDATE RHQ_ALERT_CONDITION
+ SET NAME = 'AVAIL_GOES_UP', OPTION_STATUS = NULL
+ WHERE TYPE = 'AVAILABILITY'
+ AND NAME IS NULL
+ AND OPTION_STATUS = 'UP'
+ </statement>
+ </schema-directSQL>
</schemaSpec>
<!-- JON 3.1.1 RELEASE uses DB Schema 2.122 -->
commit 35c152e87e280d8a5cd93353892da39067883819
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Wed Aug 29 15:39:00 2012 -0400
[Bug 852561 - AlertCondition.name is null in database after JON 2.4 to 3.1 upgrade]
From an RHQ perspective this should have affected upgrades to RHQ 4.4. Add
a db upgrade step to convert relevant alert condition rows to the new format.
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index d4b5505..eee04da 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -17,7 +17,7 @@
<description>Database schema setup, upgrade and other utilities</description>
<properties>
- <db.schema.version>2.122</db.schema.version>
+ <db.schema.version>2.123</db.schema.version>
<rhq.ds.type-mapping>${rhq.test.ds.type-mapping}</rhq.ds.type-mapping>
<rhq.ds.server-name>${rhq.test.ds.server-name}</rhq.ds.server-name>
<rhq.ds.db-name>${rhq.test.ds.db-name}</rhq.ds.db-name>
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index 2cee9f4..94fa46f 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -4007,7 +4007,28 @@
<schema-javaTask className="ContentSourceConfigurationObfuscationUpgradeTask" />
</schemaSpec>
- <schemaSpec version="2.122">
+<!-- RHQ 4.4, JON 3.1.0 RELEASE uses DB Schema 2.121 -->
+
+ <schemaSpec version="2.122">
+ <statement desc="Updating DOWN Alert Conditions to new format">
+ UPDATE RHQ_ALERT_CONDITION
+ SET NAME = 'AVAIL_GOES_DOWN', OPTION_STATUS = NULL
+ WHERE TYPE = 'AVAILABILITY'
+ AND NAME IS NULL
+ AND OPTION_STATUS = 'DOWN'
+ </statement>
+ <statement desc="Updating UP Alert Conditions to new format">
+ UPDATE RHQ_ALERT_CONDITION
+ SET NAME = 'AVAIL_GOES_UP', OPTION_STATUS = NULL
+ WHERE TYPE = 'AVAILABILITY'
+ AND NAME IS NULL
+ AND OPTION_STATUS = 'UP'
+ </statement>
+ </schemaSpec>
+
+<!-- JON 3.1.1 RELEASE uses DB Schema 2.122 -->
+
+ <schemaSpec version="2.123">
<schema-addColumn table="RHQ_CONFIG_PROP_DEF" column="MIN_ENTRIES" columnType="INTEGER"/>
<schema-addColumn table="RHQ_CONFIG_PROP_DEF" column="MAX_ENTRIES" columnType="INTEGER"/>
</schemaSpec>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java
index 8a72244..0744199 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java
@@ -427,7 +427,7 @@ public class AlertCondition implements Serializable {
/**
* The name of the condition whose semantics are different based on this condition's category:
*
- * AVAILABILITY: n/a (null)
+ * AVAILABILITY: The relevant Avail AlertConditionOperator name
* THRESHOLD: the name of the metric (TODO: today its the display name, very bad for i18n purposes)
* BASELINE: the name of the metric (TODO: today its the display name, very bad for i18n purposes)
* CHANGE: the name of the metric (TODO: today its the display name, very bad for i18n purposes)
commit 74704eda37bce26278fa089437d98bcd590b4317
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Wed Aug 29 14:15:26 2012 +0200
[BZ 814305 - Dealing with singletons in inventory] Refresh button now takes into consideration the already created singletons and they are not populated in the create/import child combobox
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
index 2eea340..d539136 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
@@ -597,7 +597,7 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
} else {
// menu action
LocatableMenu menu = new LocatableMenu(tableAction.getLocatorId() + "Menu");
- final Map<String, ? extends Object> menuEntries = tableAction.getValueMap();
+ final Map<String, Object> menuEntries = tableAction.getValueMap();
for (final String key : menuEntries.keySet()) {
MenuItem item = new MenuItem(key);
item.addClickHandler(new com.smartgwt.client.widgets.menu.events.ClickHandler() {
@@ -980,7 +980,7 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
* completion. Failure to do so may leave the widgets disabled.
*/
public void addTableAction(String locatorId, String title, String confirmation,
- LinkedHashMap<String, ? extends Object> valueMap, TableAction tableAction) {
+ Map<String, Object> valueMap, TableAction tableAction) {
// If the specified locator ID is qualified, strip off the ancestry prefix, so we can make sure its locator ID
// extends the footer's locator ID as it should.
int underscoreIndex = locatorId.lastIndexOf('_');
@@ -995,6 +995,37 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
tableActions.add(info);
}
+ /**
+ * Updates the list of table's associated actions <code>tableActions</code>.
+ * It automatically updates the gui by calling <code>drawFooter()</code> provided the table has been initialized.
+ *
+ * Note: To prevent user action while a current action completes, all widgets on the footer are disabled
+ * when footer actions take place, typically a button click. It is up to the action to ensure the page
+ * (via refresh() or CoreGUI.refresh()) or footer (via refreshTableActions) are refreshed as needed at action
+ * completion. Failure to do so may leave the widgets disabled.
+ *
+ * @param title the title of a modified action
+ * @param valueMap the map containing the tuples with name of a select item and <code>actionValue</code> which is
+ * then passed to <code>tableAction.executeAction()</code>; use the <code>LinkedHashMap</code> if you want to
+ * preserve the order of map items
+ * @param tableAction the tableAction object (on this object the <code>executeAction()</code> is actually invoked)
+ */
+ public void updateTableAction(String title, Map<String, Object> valueMap,
+ TableAction tableAction) {
+ if (title == null) {
+ return;
+ }
+ for (TableActionInfo info : tableActions) {
+ if (title.equals(info.getTitle())) {
+ if (valueMap != null) info.setValueMap(valueMap);
+ if (tableAction != null) info.setAction(tableAction);
+ // the action listeners have to be re-added
+ if (isInitialized()) drawFooter();
+ break;
+ }
+ }
+ }
+
public void setListGridDoubleClickHandler(DoubleClickHandler handler) {
doubleClickHandler = handler;
}
@@ -1247,12 +1278,12 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
private String locatorId;
private String title;
private String confirmMessage;
- private LinkedHashMap<String, ? extends Object> valueMap;
+ private Map<String, Object> valueMap;
private TableAction action;
private Canvas actionCanvas;
protected TableActionInfo(String locatorId, String title, String confirmMessage,
- LinkedHashMap<String, ? extends Object> valueMap, TableAction action) {
+ Map<String, Object> valueMap, TableAction action) {
this.locatorId = locatorId;
this.title = title;
this.confirmMessage = confirmMessage;
@@ -1272,9 +1303,13 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
return confirmMessage;
}
- public LinkedHashMap<String, ? extends Object> getValueMap() {
+ public Map<String, Object> getValueMap() {
return valueMap;
}
+
+ public void setValueMap(Map<String, Object> valueMap) {
+ this.valueMap = valueMap;
+ }
public Canvas getActionCanvas() {
return actionCanvas;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java
index bb43f26..265778b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java
@@ -89,41 +89,49 @@ public class ResourceCompositeSearchView extends ResourceSearchView {
super.onInit();
// To properly filter Create Child and Import menus we need existing singleton child resources. If the
- // user has creat permission and the parent type has singleton child types and creatable or importable child
+ // user has create permission and the parent type has singleton child types and creatable or importable child
// types, perform an async call to fetch the singleton children. If we make the async call don't declare this
- // instance initialized until after it completesas we must have the children before the menu buttons can be drawn.
+ // instance initialized until after it completes as we must have the children before the menu buttons can be drawn.
final Resource parentResource = parentResourceComposite.getResource();
ResourceType parentType = parentResource.getResourceType();
-
creatableChildTypes = getCreatableChildTypes(parentType);
importableChildTypes = getImportableChildTypes(parentType);
hasCreatableTypes = !creatableChildTypes.isEmpty();
hasImportableTypes = !importableChildTypes.isEmpty();
- singletonChildren = new ArrayList(); // initialize to non-null
+ refreshSingletons(parentResource, null);
+
+ }
+
+ private void refreshSingletons(final Resource parentResource, final AsyncCallback<PageList<Resource>> callback) {
+ singletonChildren = new ArrayList<Resource>(); // initialize to non-null
- Integer[] singletonChildTypes = getSingletonChildTypes(parentType);
+ Integer[] singletonChildTypes = getSingletonChildTypes(parentResource.getResourceType());
if (canCreate && singletonChildTypes.length > 0 && (hasCreatableTypes || hasImportableTypes)) {
ResourceCriteria criteria = new ResourceCriteria();
criteria.addFilterParentResourceId(parentResource.getId());
criteria.addFilterResourceTypeIds(singletonChildTypes);
- GWTServiceLookup.getResourceService().findResourcesByCriteria(criteria,
- new AsyncCallback<PageList<Resource>>() {
-
- @Override
- public void onSuccess(PageList<Resource> result) {
- singletonChildren = result;
- initialized = true;
+ GWTServiceLookup.getResourceService().findResourcesByCriteria(criteria, new AsyncCallback<PageList<Resource>>() {
+
+ @Override
+ public void onSuccess(PageList<Resource> result) {
+ singletonChildren = result;
+ initialized = true;
+ if (callback != null) {
+ callback.onSuccess(result);
}
+ }
- @Override
- public void onFailure(Throwable caught) {
- Log.error("Failed to load child resources for [" + parentResource + "]", caught);
- initialized = true;
+ @Override
+ public void onFailure(Throwable caught) {
+ Log.error("Failed to load child resources for [" + parentResource + "]", caught);
+ initialized = true;
+ if (callback != null) {
+ callback.onFailure(caught);
}
- });
-
+ }
+ });
} else {
initialized = true;
}
@@ -196,34 +204,38 @@ public class ResourceCompositeSearchView extends ResourceSearchView {
}
});
- addImportAndCreateButtons();
+ addImportAndCreateButtons(false);
super.configureTable();
}
@SuppressWarnings("unchecked")
- private void addImportAndCreateButtons() {
+ private void addImportAndCreateButtons(boolean override) {
final Resource parentResource = parentResourceComposite.getResource();
ResourceType parentType = parentResource.getResourceType();
// Create Child Menu and Manual Import Menu
if (canCreate && (hasCreatableTypes || hasImportableTypes)) {
-
if (hasCreatableTypes) {
Map<String, ResourceType> displayNameMap = getDisplayNames(creatableChildTypes);
LinkedHashMap<String, ResourceType> createTypeValueMap = new LinkedHashMap<String, ResourceType>(
displayNameMap);
removeExistingSingletons(singletonChildren, createTypeValueMap);
- addTableAction(extendLocatorId("CreateChild"), MSG.common_button_create_child(), null,
- createTypeValueMap, new AbstractTableAction(TableActionEnablement.ALWAYS) {
- public void executeAction(ListGridRecord[] selection, Object actionValue) {
- ResourceFactoryCreateWizard.showCreateWizard(parentResource, (ResourceType) actionValue);
- // we can refresh the table buttons immediately since the wizard is a dialog, the
- // user can't access enabled buttons anyway.
- ResourceCompositeSearchView.this.refreshTableInfo();
- }
- });
+ AbstractTableAction createAction = new AbstractTableAction(TableActionEnablement.ALWAYS) {
+ public void executeAction(ListGridRecord[] selection, Object actionValue) {
+ ResourceFactoryCreateWizard.showCreateWizard(parentResource, (ResourceType) actionValue);
+ // we can refresh the table buttons immediately since the wizard is a dialog, the
+ // user can't access enabled buttons anyway.
+ ResourceCompositeSearchView.this.refreshTableInfo();
+ }
+ };
+ if (override) {
+ updateTableAction(MSG.common_button_create_child(), createTypeValueMap, createAction);
+ } else {
+ addTableAction(extendLocatorId("CreateChild"), MSG.common_button_create_child(), null,
+ createTypeValueMap, createAction);
+ }
}
if (hasImportableTypes) {
@@ -231,18 +243,23 @@ public class ResourceCompositeSearchView extends ResourceSearchView {
LinkedHashMap<String, ResourceType> importTypeValueMap = new LinkedHashMap<String, ResourceType>(
displayNameMap);
removeExistingSingletons(singletonChildren, importTypeValueMap);
- addTableAction(extendLocatorId("Import"), MSG.common_button_import(), null, importTypeValueMap,
- new AbstractTableAction(TableActionEnablement.ALWAYS) {
- public void executeAction(ListGridRecord[] selection, Object actionValue) {
- ResourceFactoryImportWizard.showImportWizard(parentResource, (ResourceType) actionValue);
- // we can refresh the table buttons immediately since the wizard is a dialog, the
- // user can't access enabled buttons anyway.
- ResourceCompositeSearchView.this.refreshTableInfo();
- }
- });
+ AbstractTableAction importAction = new AbstractTableAction(TableActionEnablement.ALWAYS) {
+ public void executeAction(ListGridRecord[] selection, Object actionValue) {
+ ResourceFactoryImportWizard.showImportWizard(parentResource, (ResourceType) actionValue);
+ // we can refresh the table buttons immediately since the wizard is a dialog, the
+ // user can't access enabled buttons anyway.
+ ResourceCompositeSearchView.this.refreshTableInfo();
+ }
+ };
+ if (override) {
+ updateTableAction(MSG.common_button_import(), importTypeValueMap, importAction);
+ } else {
+ addTableAction(extendLocatorId("Import"), MSG.common_button_import(), null, importTypeValueMap,
+ importAction);
+ }
}
- } else {
+ } else if (!override) {
if (!canCreate && hasCreatableTypes) {
addTableAction(extendLocatorId("CreateChild"), MSG.common_button_create_child(),
new AbstractTableAction(TableActionEnablement.NEVER) {
@@ -261,6 +278,7 @@ public class ResourceCompositeSearchView extends ResourceSearchView {
}
}
}
+
private void removeExistingSingletons(List<Resource> singletonChildren, Map<String, ResourceType> displayNameMap) {
@@ -359,5 +377,23 @@ public class ResourceCompositeSearchView extends ResourceSearchView {
return new ResourceCompositeSearchView(locatorId, parentResourceComposite, new Criteria("parentId",
String.valueOf(parentResourceComposite.getResource().getId())), MSG.view_tabs_common_child_resources());
}
+
+ @Override
+ public void refresh() {
+ refreshSingletons(parentResourceComposite.getResource(), new AsyncCallback<PageList<Resource>>() {
+
+ @Override
+ public void onSuccess(PageList<Resource> result) {
+ addImportAndCreateButtons(true);
+ ResourceCompositeSearchView.super.refresh();
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ ResourceCompositeSearchView.super.refresh();
+ }
+ });
+
+ }
}
commit c6c1e7819fbd8f667649223e12355e66ddd33252
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Aug 29 03:06:38 2012 -0500
[BZ 852632] Remove allow-direct-connections-only property from configuration to prevent sending the value to the application server. If this property is not left undefined, the configuration file for the server becomes invalid if the user attempts to use discovery-group-name.
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 01618e2..46b3084 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
@@ -4714,7 +4714,6 @@
<metric property="started" dataType="trait" description="Whether the cluster connection is started."/>
<resource-configuration>
- <c:simple-property name="allow-direct-connections-only" required="false" type="boolean" readOnly="true" defaultValue="false" description="Whether, if a node learns of the existence of a node that is more than 1 hop away, we do not create a bridge for direct cluster connection. Only relevant if 'static-connectors' is defined. The default value is false."/>
<c:simple-property name="call-timeout" required="false" type="long" readOnly="true" defaultValue="30000" description="The timeout (in ms) for remote calls made by the cluster connection. The default value is 30000."/>
<c:simple-property name="check-period" required="false" type="long" readOnly="true" defaultValue="30000" description="The period (in milliseconds) between client failure check. The default value is 30000."/>
<c:simple-property name="cluster-connection-address" required="true" type="string" readOnly="true" description="Each cluster connection only applies to messages sent to an address that starts with this value."/>
@@ -6843,7 +6842,6 @@
</plugin-configuration>
<resource-configuration>
- <c:simple-property name="allow-direct-connections-only" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether, if a node learns of the existence of a node that is more than 1 hop away, we do not create a bridge for direct cluster connection. Only relevant if 'static-connectors' is defined. The default value is false."/>
<c:simple-property name="call-timeout" required="false" type="long" readOnly="false" defaultValue="30000" description="The timeout (in ms) for remote calls made by the cluster connection. The default value is 30000."/>
<c:simple-property name="check-period" required="false" type="long" readOnly="false" defaultValue="30000" description="The period (in milliseconds) between client failure check. The default value is 30000."/>
<c:simple-property name="cluster-connection-address" required="true" type="string" readOnly="false" description="Each cluster connection only applies to messages sent to an address that starts with this value."/>
@@ -12948,7 +12946,6 @@
<metric property="started" dataType="trait" description="Whether the cluster connection is started."/>
<resource-configuration>
- <c:simple-property name="allow-direct-connections-only" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether, if a node learns of the existence of a node that is more than 1 hop away, we do not create a bridge for direct cluster connection. Only relevant if 'static-connectors' is defined. The default value is false."/>
<c:simple-property name="call-timeout" required="false" type="long" readOnly="false" defaultValue="30000" description="The timeout (in ms) for remote calls made by the cluster connection. The default value is 30000."/>
<c:simple-property name="check-period" required="false" type="long" readOnly="false" defaultValue="30000" description="The period (in milliseconds) between client failure check. The default value is 30000."/>
<c:simple-property name="cluster-connection-address" required="true" type="string" readOnly="false" description="Each cluster connection only applies to messages sent to an address that starts with this value."/>
commit 74aa0f7f9b0f2dd1044450d924f61b3faee78c27
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Aug 29 02:52:42 2012 -0500
[BZ 852552] Updates to set correctly all the data-source and xa-data-source properties that do not support null values and cannot be undefined.
While these properties look undefined in the server, they cannot undefined or set to null at any point in time. The application server makes use of the default value at all times.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DatasourceComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DatasourceComponent.java
index a4efae1..5011120 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DatasourceComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DatasourceComponent.java
@@ -13,6 +13,9 @@ import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.Property;
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.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
import org.rhq.core.domain.measurement.MeasurementDataNumeric;
import org.rhq.core.domain.measurement.MeasurementDataTrait;
import org.rhq.core.domain.measurement.MeasurementReport;
@@ -174,6 +177,27 @@ public class DatasourceComponent extends BaseComponent<BaseComponent<?>> impleme
}
}
+ @Override
+ public void updateResourceConfiguration(ConfigurationUpdateReport report) {
+ Configuration config = report.getConfiguration();
+ ConfigurationDefinition configDef = context.getResourceType().getResourceConfigurationDefinition();
+
+ //These properties cannot be undefined once set.
+ //Also the AS7 server does not accept null values even if the properties are still unset.
+ replaceWithDefaultIfNull("max-pool-size", config, configDef);
+ replaceWithDefaultIfNull("min-pool-size", config, configDef);
+ replaceWithDefaultIfNull("pool-prefill", config, configDef);
+ replaceWithDefaultIfNull("pool-use-strict-min", config, configDef);
+ replaceWithDefaultIfNull("blocking-timeout-wait-millis", config, configDef);
+ replaceWithDefaultIfNull("idle-timeout-minutes", config, configDef);
+ replaceWithDefaultIfNull("background-validation-millis", config, configDef);
+ replaceWithDefaultIfNull("background-validation-minutes", config, configDef);
+ replaceWithDefaultIfNull("background-validation", config, configDef);
+
+ ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(configDef, getASConnection(), address);
+ delegate.updateResourceConfiguration(report);
+ }
+
private void getRCAsMetric(MeasurementReport report, MeasurementScheduleRequest request) {
Operation op = new ReadAttribute(getAddress(), request.getName());
Result res = getASConnection().execute(op);
@@ -204,4 +228,23 @@ public class DatasourceComponent extends BaseComponent<BaseComponent<?>> impleme
return trait;
}
+
+ /**
+ * Replace the value configured by the user with the default value from the resource descriptor if
+ * the value to be sent to the server is null or empty.
+ *
+ * @param propertyName property name
+ * @param config configuration update
+ * @param configDef configuration definition
+ */
+ private void replaceWithDefaultIfNull(String propertyName, Configuration config, ConfigurationDefinition configDef) {
+ PropertyDefinitionSimple propertyDefinition = configDef.getPropertyDefinitionSimple(propertyName);
+
+ if (propertyDefinition != null) {
+ String propertyValue = config.getSimpleValue(propertyName);
+ if (propertyValue == null || propertyValue.isEmpty()) {
+ config.put(new PropertySimple(propertyName, propertyDefinition.getDefaultValue()));
+ }
+ }
+ }
}
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 29ef057..01618e2 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
@@ -412,10 +412,10 @@
<c:simple-property name="use-java-context" type="boolean" readOnly="false" required="false" default="true" description="Setting this to false will bind the DataSource into global JNDI;"/>
<c:simple-property name="enabled" type="boolean" readOnly="true" required="false" description="Specifies if the datasource should be enabled"/>
<c:simple-property name="jta" type="boolean" readOnly="false" required="false" default="true" description="Enable JTA integration"/>
- <c:simple-property name="max-pool-size" type="integer" readOnly="false" required="false" description="The max-pool-size element indicates the maximum number of connections for a pool. No more connections will be created in each sub-pool."/>
- <c:simple-property name="min-pool-size" type="integer" readOnly="false" required="false" description="The min-pool-size element 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."/>
- <c:simple-property name="pool-prefill" type="boolean" readOnly="false" required="false" default="false" description="Whether to attempt to prefill the connection pool. Changing this value require a server restart."/>
- <c:simple-property name="pool-use-strict-min" type="boolean" readOnly="false" required="false" default="false" description="Define if the min-pool-size should be considered a strictly."/>
+ <c:simple-property name="max-pool-size" type="integer" readOnly="false" required="false" defaultValue="20" description="The max-pool-size element indicates the maximum number of connections for a pool. No more connections will be created in each sub-pool."/>
+ <c:simple-property name="min-pool-size" type="integer" readOnly="false" required="false" defaultValue="0" description="The min-pool-size element 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."/>
+ <c:simple-property name="pool-prefill" type="boolean" readOnly="false" required="false" defaultValue="false" description="Whether to attempt to prefill the connection pool. Changing this value require a server restart."/>
+ <c:simple-property name="pool-use-strict-min" type="boolean" readOnly="false" required="false" defaultValue="false" description="Define if the min-pool-size should be considered a strictly."/>
<c:simple-property name="security-domain" required="false" type="string" readOnly="false" description="Indicates Subject (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 handleauthentication. This name correlates to the JAAS login-config.xml descriptor application-policy/name attribute."/>
<c:simple-property name="reauth-plugin-class-name" required="false" type="string" readOnly="false" description="re-authentication plugin implementation provided for specific purpose (i.e vendor)"/>
<!--
@@ -433,7 +433,7 @@
</c:simple-property>
<c:simple-property name="allow-multiple-users" type="boolean" required="false" readOnly="false" description="Specifies if multiple users will access the datasource through the getConnection(user, password) method and hence if the internal pool type should account for that"/>
- <c:simple-property name="prepared-statements-cacheSize" type="long" readOnly="false" required="false" description="The number of prepared statements per connection in an LRU cache"/>
+ <c:simple-property name="prepared-statements-cache-size" type="long" readOnly="false" required="false" description="The number of prepared statements per connection in an LRU cache"/>
<c:simple-property name="share-prepared-statements" type="boolean" readOnly="false" required="false" default="false" description="Whether to share prepare statements, i.e. whether asking for same statement twice without closing uses the same underlying prepared statement"/>
<c:simple-property name="track-statements" type="string" readOnly="false" required="false" description="Whether to check for unclosed statements when a connection is returned to the pool and result sets are closed when a statement is closed/return to the prepared statement cache. valid values are: false - do not track statements and results true - track statements and result sets and warn when they are not closed nowarn - track statements but do no warn about them being unclosed">
<c:property-options>
@@ -444,8 +444,8 @@
</c:simple-property>
<c:simple-property name="allocation-retry" type="integer" readOnly="false" required="false" description="The allocation retry element indicates the number of times that allocating a connection should be tried before throwing an exception."/>
<c:simple-property name="allocation-retry-wait-millis" type="long" readOnly="false" required="false" description="Indicates the time in milliseconds to wait between retrying to allocate a connection."/>
- <c:simple-property name="blocking-timeout-wait-millis" type="long" readOnly="false" required="false" description="The blocking-timeout-millis element 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."/>
- <c:simple-property name="idle-timeout-minutes" type="long" readOnly="false" required="false" description="The idle-timeout-minutes elements 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. Changing this value require a server restart."/>
+ <c:simple-property name="blocking-timeout-wait-millis" type="long" readOnly="false" required="false" defaultValue="30000" description="The blocking-timeout-millis element 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."/>
+ <c:simple-property name="idle-timeout-minutes" type="long" readOnly="false" required="false" defaultValue="15" description="The idle-timeout-minutes elements 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. Changing this value require a server restart."/>
<c:simple-property name="query-timeout" type="long" readOnly="false" required="false" description="Any configured query timeout in seconds The default is no timeout"/>
<c:simple-property name="use-try-lock" type="long" readOnly="false" required="false" description="Any configured timeout for internal locks on the resource adapter objects in seconds"/>
<c:simple-property name="set-tx-query-timeout" type="boolean" readOnly="false" required="false" default="false" description="Whether to set the query timeout based on the time remaining until transaction timeout, any configured query timeout will be used if there is no transaction."/>
@@ -462,8 +462,8 @@
<c:simple-property name="exception-sorter-class-name" type="string" readOnly="false" required="false" description="An org.jboss.jca.adapters.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"/>
<c:simple-property name="stale-connection-checker-class-name" type="string" readOnly="false" required="false" description="An org.jboss.jca.adapters.jdbc.StaleConnectionChecker that provides a boolean isStaleConnection(SQLException e) method which if it it returns true will wrap the exception in an org.jboss.jca.adapters.jdbc.StaleConnectionException"/>
<c:simple-property name="valid-connection-checker-class-name" type="string" readOnly="false" required="false" description="An org.jboss.jca.adapters.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."/>
- <c:simple-property name="background-validation-millis" type="long" readOnly="false" required="false" description="The background-validation-minutes element specifies the amount of time, in minutes, that background validation will run. Changing this value require a server restart."/>
- <c:simple-property name="background-validation" type="boolean" readOnly="false" required="false" default="false" description="An element to specify that connections should be validated on a background thread versus being validated prior to use. Changing this value require a server restart."/>
+ <c:simple-property name="background-validation-millis" type="long" readOnly="false" required="false" defaultValue="600000" description="The background-validation-minutes element specifies the amount of time, in minutes, that background validation will run. Changing this value require a server restart."/>
+ <c:simple-property name="background-validation" type="boolean" readOnly="false" required="false" defaultValue="false" description="An element to specify that connections should be validated on a background thread versus being validated prior to use. Changing this value require a server restart."/>
<c:simple-property name="use-fast-fail" type="boolean" readOnly="false" required="false" description="Whether fail a connection allocation on the first connection if it is invalid (true) or keep trying until the pool is exhausted of all potential connections (false)"/>
<c:simple-property name="validate-on-match" type="boolean" readOnly="false" required="false" default="false" description="The validate-on-match element indicates whether or not connection level validation should be done when a connection factory attempts to match a managed connection for a given set. This is typically exclusive to the use of background validation"/>
<c:simple-property name="spy" type="boolean" readOnly="false" required="false" defaultValue="false" description="whatever spy or not the jdbc connection"/>
@@ -515,7 +515,7 @@
</c:property-options>
</c:simple-property>
- <c:simple-property name="prepared-statements-cacheSize" type="long" readOnly="true" required="false" description="The number of prepared statements per connection in an LRU cache"/>
+ <c:simple-property name="prepared-statements-cache-size" type="long" readOnly="true" required="false" description="The number of prepared statements per connection in an LRU cache"/>
<c:simple-property name="share-prepared-statements" type="boolean" readOnly="true" required="false" description="Whether to share prepare statements, i.e. whether asking for same statement twice without closing uses the same underlying prepared statement"/>
<c:simple-property name="track-statements" type="string" readOnly="true" required="false" description="Whether to check for unclosed statements when a connection is returned to the pool and result sets are closed when a statement is closed/return to the prepared statement cache. valid values are: false - do not track statements and results true - track statements and result sets and warn when they are not closed nowarn - track statements but do no warn about them being unclosed"/>
<c:simple-property name="allocation-retry" type="integer" readOnly="true" required="false" description="The allocation retry element indicates the number of times that allocating a connection should be tried before throwing an exception."/>
@@ -570,10 +570,10 @@
<c:simple-property name="url-selector-strategy-class-name" required="false" type="string" readOnly="true" description="A class that implements org.jboss.jca.adapters.jdbc.URLSelectorStrategy"/>
<c:simple-property name="use-java-context" required="false" type="boolean" readOnly="true" description="Setting this to false will bind the DataSource into global JNDI;"/>
<c:simple-property name="enabled" required="false" type="boolean" readOnly="true" description="Specifies if the datasource should be enabled"/>
- <c:simple-property name="max-pool-size" required="false" type="integer" readOnly="false" description="The max-pool-size element indicates the maximum number of connections for a pool. No more connections will be created in each sub-pool."/>
- <c:simple-property name="min-pool-size" required="false" type="integer" readOnly="false" description="The min-pool-size element 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."/>
- <c:simple-property name="pool-prefill" required="false" type="boolean" readOnly="false" description="Whether to attempt to prefill the connection pool. Changing this value require a server restart."/>
- <c:simple-property name="pool-use-strict-min" required="false" type="boolean" readOnly="false" description="Define if the min-pool-size should be considered a strictly."/>
+ <c:simple-property name="max-pool-size" required="false" type="integer" readOnly="false" defaultValue="20" description="The max-pool-size element indicates the maximum number of connections for a pool. No more connections will be created in each sub-pool."/>
+ <c:simple-property name="min-pool-size" required="false" type="integer" readOnly="false" defaultValue="0" description="The min-pool-size element 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."/>
+ <c:simple-property name="pool-prefill" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether to attempt to prefill the connection pool. Changing this value require a server restart."/>
+ <c:simple-property name="pool-use-strict-min" required="false" type="boolean" readOnly="false" defaultValue="false" description="Define if the min-pool-size should be considered a strictly."/>
<c:simple-property name="interleaving" required="false" type="boolean" readOnly="true" description="An element to enable interleaving for XA connection factories"/>
<c:simple-property name="no-tx-separate-pool" required="false" type="boolean" readOnly="true" description="Oracle does not like XA connections getting used both inside and outside a JTA transaction. To workaround the problem you can create separate sub-pools for the different context"/>
<c:simple-property name="pad-xid" required="false" type="boolean" readOnly="true" description="Should the Xid be padded"/>
@@ -596,13 +596,13 @@
<c:option value="EntirePool"/>
</c:property-options>
</c:simple-property>
- <c:simple-property name="prepared-statements-cacheSize" required="false" type="long" readOnly="true" description="The number of prepared statements per connection in an LRU cache"/>
+ <c:simple-property name="prepared-statements-cache-size" required="false" type="long" readOnly="true" description="The number of prepared statements per connection in an LRU cache"/>
<c:simple-property name="share-prepared-statements" required="false" type="boolean" readOnly="true" description="Whether to share prepare statements, i.e. whether asking for same statement twice without closing uses the same underlying prepared statement"/>
<c:simple-property name="track-statements" required="false" type="string" readOnly="true" description="Whether to check for unclosed statements when a connection is returned to the pool and result sets are closed when a statement is closed/return to the prepared statement cache. valid values are: false - do not track statements and results true - track statements and result sets and warn when they are not closed nowarn - track statements but do no warn about them being unclosed"/>
<c:simple-property name="allocation-retry" required="false" type="integer" readOnly="true" description="The allocation retry element indicates the number of times that allocating a connection should be tried before throwing an exception."/>
<c:simple-property name="allocation-retry-wait-millis" required="false" type="long" readOnly="true" description="he allocation retry wait millis element indicates the time in milliseconds to wait between retrying to allocate a connection."/>
- <c:simple-property name="blocking-timeout-wait-millis" required="false" type="long" readOnly="false" description="The blocking-timeout-millis element 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."/>
- <c:simple-property name="idle-timeout-minutes" required="false" type="long" readOnly="false" description="The idle-timeout-minutes elements 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. Changing this value require a server restart."/>
+ <c:simple-property name="blocking-timeout-wait-millis" required="false" type="long" readOnly="false" defaultValue="30000" description="The blocking-timeout-millis element 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."/>
+ <c:simple-property name="idle-timeout-minutes" required="false" type="long" readOnly="false" defaultValue="15" description="The idle-timeout-minutes elements 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. Changing this value require a server restart."/>
<c:simple-property name="query-timeout" required="false" type="long" readOnly="true" description="Any configured query timeout in seconds The default is no timeout"/>
<c:simple-property name="use-try-lock" required="false" type="long" readOnly="true" description="Any configured timeout for internal locks on the resource adapter objects in seconds"/>
<c:simple-property name="set-tx-query-timeout" required="false" type="boolean" readOnly="true" description="Whether to set the query timeout based on the time remaining until transaction timeout, any configured query timeout will be used if there is no transaction."/>
@@ -637,8 +637,8 @@
configuration
</c:map-property>
-->
- <c:simple-property name="background-validation-minutes" required="false" type="long" readOnly="false" description="The background-validation-minutes element specifies the amount of time, in minutes, that background validation will run. Changing this value require a server restart."/>
- <c:simple-property name="background-validation" required="false" type="boolean" readOnly="false" description="An element to specify that connections should be validated on a background thread versus being validated prior to use. Changing this value require a server restart."/>
+ <c:simple-property name="background-validation-minutes" required="false" type="long" readOnly="false" defaultValue="10" description="The background-validation-minutes element specifies the amount of time, in minutes, that background validation will run. Changing this value require a server restart."/>
+ <c:simple-property name="background-validation" required="false" type="boolean" readOnly="false" defaultValue="false" description="An element to specify that connections should be validated on a background thread versus being validated prior to use. Changing this value require a server restart."/>
<c:simple-property name="use-fast-fail" required="false" type="boolean" readOnly="false" description="Whether fail a connection allocation on the first connection if it is invalid (true) or keep trying until the pool is exhausted of all potential connections (false)"/>
<c:simple-property name="validate-on-match" required="false" type="boolean" readOnly="true" description="The validate-on-match element indicates whether or not connection level validation should be done when a connection factory attempts to match a managed connection for a given set. This is typically exclusive to the use of background validation"/>
<c:simple-property name="xa-resource-timeout" required="false" type="integer" readOnly="true" description="Passed to XAResource.setTransactionTimeout() Default is zero which does not invoke the setter. In seconds"/>
@@ -706,7 +706,7 @@
<c:option value="EntirePool"/>
</c:property-options>
</c:simple-property>
- <c:simple-property name="prepared-statements-cacheSize" required="false" type="long" readOnly="true" description="The number of prepared statements per connection in an LRU cache"/>
+ <c:simple-property name="prepared-statements-cache-size" required="false" type="long" readOnly="true" description="The number of prepared statements per connection in an LRU cache"/>
<c:simple-property name="share-prepared-statements" required="false" type="boolean" readOnly="true" description="Whether to share prepare statements, i.e. whether asking for same statement twice without closing uses the same underlying prepared statement"/>
<c:simple-property name="track-statements" required="false" type="string" readOnly="true" description="Whether to check for unclosed statements when a connection is returned to the pool and result sets are closed when a statement is closed/return to the prepared statement cache. valid values are: false - do not track statements and results true - track statements and result sets and warn when they are not closed nowarn - track statements but do no warn about them being unclosed"/>
<c:simple-property name="allocation-retry" required="false" type="integer" readOnly="true" description="The allocation retry element indicates the number of times that allocating a connection should be tried before throwing an exception."/>
commit e6e91058f3ac76c6458847bd66a8ee5c9c24493e
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Aug 29 02:20:24 2012 -0500
[BZ 847674] Updated all the wait methods for reload, shutdown, and restart to have the same design. All the methods now take into account possible exceptions for the test operation sent to the application server.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
index 27b1133..98a46d2 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
@@ -241,25 +241,36 @@ public abstract class BaseServerComponent<T extends ResourceComponent<?>> extend
return startServer();
}
- protected boolean waitUntilDown(OperationResult tmp) throws InterruptedException {
+ protected boolean waitUntilDown() throws InterruptedException {
boolean down=false;
int count=0;
+
while (!down) {
Operation op = new ReadAttribute(new Address(),"release-version");
- Result res = getASConnection().execute(op);
- if (!res.isSuccess()) { // If op succeeds, server is not down
- down=true;
- } else if (count > 20) {
- tmp.setErrorMessage("Was not able to shut down the server");
- return true;
+
+ try{
+ Result res = getASConnection().execute(op);
+ if (!res.isSuccess()) { // If op succeeds, server is not down
+ down = true;
+ } else if (count > 20) {
+ break;
+ }
+ } catch (Exception e) {
+ down = true;
}
+
if (!down) {
- Thread.sleep(1000); // Wait 1s
+ try {
+ Thread.sleep(1000); // Wait 1s
+ } catch (InterruptedException e) {
+ // ignore
+ }
}
count++;
}
- log.debug("waitUntilDown: Used " + count + " delay round(s) to shut down");
- return false;
+
+ log.debug("waitUntilDown: Used " + count + " delay round(s) to shut down. Server down=" + down);
+ return down;
}
/**
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java
index 565add2..7ea12b9 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java
@@ -92,8 +92,11 @@ public class HostControllerComponent<T extends ResourceComponent<?>> extends Bas
Result res = getASConnection().execute(op);
operationResult = postProcessResult(name, res);
- waitUntilDown(operationResult);
-
+ if (waitUntilDown()) {
+ operationResult.setSimpleResult("Success");
+ } else {
+ operationResult.setErrorMessage("Was not able to shut down the server.");
+ }
} else if (name.equals("installRhqUser")) {
operationResult = installManagementUser(parameters, pluginConfiguration);
} else {
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
index 573742e..778d127 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
@@ -163,39 +163,59 @@ public class StandaloneASComponent<T extends ResourceComponent<?>> extends BaseS
OperationResult operationResult = postProcessResult(name, res);
- if (name.equals("shutdown"))
- waitUntilDown(operationResult);
+ if (name.equals("shutdown")) {
+ if (waitUntilDown()) {
+ operationResult.setSimpleResult("Success");
+ } else {
+ operationResult.setErrorMessage("Was not able to shut down the server.");
+ }
+ }
- if (name.equals("reload"))
- waitUntilReloaded(operationResult);
+ if (name.equals("reload")) {
+ if (waitUntilReloaded()) {
+ operationResult.setSimpleResult("Success");
+ } else {
+ operationResult.setErrorMessage("Was not able to reload the server.");
+ }
+ }
context.getAvailabilityContext().requestAvailabilityCheck();
return operationResult;
}
- private void waitUntilReloaded(OperationResult operationResult) {
+ private boolean waitUntilReloaded() {
boolean reloaded = false;
int count = 0;
+
while (!reloaded) {
- try {
- Thread.sleep(2000); // Wait 2s
- } catch (InterruptedException e) {
- // Ignore
+ Operation op = new ReadAttribute(new Address(), "release-version");
+ try{
+ Result res = getASConnection().execute(op);
+ if (res.isSuccess() && !res.isReloadRequired()) {
+ reloaded = true;
+ } else if (count > 20) {
+ break;
+ }
+ } catch (Exception e) {
+ //do absolutely nothing
+ //if an exception is thrown that means the server is still reloading, so consider this
+ //a single failed attempt, equivalent to res.isSuccess == false
}
- Operation op = new ReadAttribute(new Address(), "release-version");
- Result res = getASConnection().execute(op);
- if (res.isSuccess() && !res.isReloadRequired()) {
- reloaded = true;
- } else if (count > 20) {
- operationResult.setErrorMessage("Was not able to reload the server");
- return;
+ if (!reloaded) {
+ try {
+ Thread.sleep(1000); // Wait 1s
+ } catch (InterruptedException e) {
+ // ignore
+ }
}
count++;
}
- log.debug("waitUntilReloaded: Used " + count + " delay round(s) to reload");
- return;
+
+ log.debug("waitUntilReloaded: Used " + count + " delay round(s) to reload. Reload=" + reloaded);
+
+ return reloaded;
}
@Override
commit 96602db100b087e36016b1aa6a2e39780b583898
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 23:33:45 2012 -0500
[BZ 852552] Adding special validation for the transaction subsystem.
The special case for this subsystem:
If [process-id-uuid] == true then do not send updates for [process-id-socket-binding], this property will be undefined by the AS7 on the next reload/restart
If [process-id-uuid] == false then allow AS7 to perform property validation * If [process-id-uuid] == false then send [process-id-socket-binding] value and allow AS7 to perform property validation
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/TransactionsComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/TransactionsComponent.java
new file mode 100644
index 0000000..102118b
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/TransactionsComponent.java
@@ -0,0 +1,62 @@
+/*
+ * 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.modules.plugins.jbossas7;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+
+/**
+ * Support for transactions subsystem configuration updates.
+ *
+ * The special case for this subsystem:
+ *
+ * If [process-id-uuid] == true then do not send updates for [process-id-socket-binding], this property
+ * will be undefined by the AS7 on the next server reload/restart
+ *
+ * If [process-id-uuid] == false then send [process-id-socket-binding] value and
+ * allow AS7 to perform property validation
+ *
+ *
+ * @author Stefan Negrea
+ */
+public class TransactionsComponent extends BaseComponent<ResourceComponent<?>> {
+
+ @Override
+ public void updateResourceConfiguration(ConfigurationUpdateReport report) {
+ Configuration config = report.getConfiguration();
+ ConfigurationDefinition configDef = context.getResourceType().getResourceConfigurationDefinition();
+
+ boolean processIdUuid = Boolean.valueOf(config.getSimpleValue("process-id-uuid"));
+ if (processIdUuid == true) {
+ //Do not even send the updates for [process-id-socket-binding] because the AS7 will
+ //undefine it during the next reload/restart.
+ //Also, sending null for [process-id-socket-binding] with [process-id-uuid] == true causes
+ //a validation error on the server.
+ configDef.getPropertyDefinitions().remove("process-id-socket-binding");
+ config.remove("process-id-socket-binding");
+ }
+
+ ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(configDef, getASConnection(), address);
+ delegate.updateResourceConfiguration(report);
+ }
+}
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 0f150a4..29ef057 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
@@ -8338,7 +8338,7 @@
<service name="Transactions Subsystem (Standalone)"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="TransactionsComponent"
singleton="true"
description="The transactions subsystem.">
@@ -8460,7 +8460,7 @@
<service name="Transactions Subsystem (Profile)"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="TransactionsComponent"
singleton="true"
description="The transactions subsystem.">
@@ -8516,7 +8516,7 @@
<service name="Transactions Subsystem (Managed)"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="TransactionsComponent"
singleton="true"
description="The transactions subsystem.">
commit b8d890aaf85b9d3f74eb60d1bad32af02d030759
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 23:01:08 2012 -0500
[BZ 852552] Add two resource types to the list of ignored resources for this integration test. Both of these resources have special requirements with regards to configuration updates.
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
index aad8739..824162a 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
@@ -86,6 +86,9 @@ public class ResourcesStandaloneServerTest extends AbstractJBossAS7PluginTest {
//will revisit after BZ 826542 is resolved
// ignoredResources.add("Authentication (Classic)");
+ ignoredResources.add("Memory Pool");
+ ignoredResources.add("Periodic Rotating File Handler");
+
Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
Resource server = getResourceByTypeAndKey(platform, StandaloneServerComponentTest.RESOURCE_TYPE,
StandaloneServerComponentTest.RESOURCE_KEY);
commit a31197fcd63548c6e49606525b9938c123e5ffb2
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 22:59:02 2012 -0500
[BZ 852552] Update socket binding group to not send at all port-offset for non-standalone servers.
Just setting port-offset to null was not enough since now all the unset properties are sent to the AS7 server. The property and property definition are now removed from updates sent host controllers.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SocketBindingGroupComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SocketBindingGroupComponent.java
index 00d28ca..573db2e 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SocketBindingGroupComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SocketBindingGroupComponent.java
@@ -2,6 +2,7 @@ package org.rhq.modules.plugins.jbossas7;
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.pluginapi.configuration.ConfigurationFacet;
import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
@@ -29,12 +30,14 @@ public class SocketBindingGroupComponent extends BaseComponent implements Config
public void updateResourceConfiguration(ConfigurationUpdateReport report) {
Configuration config = report.getConfiguration();
+ ConfigurationDefinition configDef = context.getResourceType().getResourceConfigurationDefinition();
+
if (!(context.getParentResourceComponent() instanceof StandaloneASComponent)) { // TODO what about managed servers
- config.put(new PropertySimple("port-offset",null));
+ configDef.getPropertyDefinitions().remove("port-offset");
+ config.remove("port-offset");
}
- super.updateResourceConfiguration(report);
-
-
+ ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(configDef, getASConnection(), address);
+ delegate.updateResourceConfiguration(report);
}
}
commit 91aaaf71e585022ca85f62e371a7d63ae554ff6d
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 22:55:05 2012 -0500
[BZ 852552] Create a separate distributed cache definition because this resource contains addtional properties not available for invalidation and replicate caches.
The diferrence between these caches was obvious only after the updates to always send unset properties. All these extra properties (which are null) were sent to the server causing failures for caches that do not have them in their definition.
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 81ddfe9..0f150a4 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
@@ -2002,7 +2002,7 @@
class="TemplatedComponent">
<plugin-configuration>
- <c:simple-property name="path" readOnly="true" default="distributed-cache|invalidation-cache|replicated-cache"/>
+ <c:simple-property name="path" readOnly="true" default="invalidation-cache|replicated-cache"/>
</plugin-configuration>
<resource-configuration>
@@ -2031,30 +2031,64 @@
<c:simple-property name="queue-flush-interval" required="false" type="long" readOnly="true" default="10" description="In ASYNC mode, this attribute controls how often the asynchronous thread used to flush the replication queue runs. This should be a positive integer which represents thread wakeup time in milliseconds."/>
<c:simple-property name="remote-timeout" required="false" type="long" readOnly="true" default="17500" description="In SYNC mode, the timeout (in ms) used to wait for an acknowledgment when making a remote call, after which the call is aborted and an exception is thrown."/>
<c:simple-property name="async-marshalling" required="false" type="boolean" readOnly="true" defaultValue="false" description="If enabled, this will cause marshalling of entries to be performed asynchronously. The default value is false."/>
- <c:simple-property name="l1-lifespan" required="false" type="long" readOnly="true" defaultValue="600000" description="Maximum lifespan of an entry placed in the L1 cache. This element configures the L1 cache behavior in 'distributed' caches instances. In any other cache modes, this element is ignored. The default value is 600000."/>
<c:simple-property name="module" required="false" type="string" readOnly="true" description="The module whose class loader should be used when building this cache's configuration."/>
- <c:simple-property name="owners" required="false" type="integer" readOnly="true" defaultValue="2" description="Number of cluster-wide replicas for each cache entry. The default value is 2."/>
- <c:simple-property name="virtual-nodes" required="false" type="integer" readOnly="true" defaultValue="1" description="Controls the number of virtual nodes per 'real' node. If numVirtualNodes is 1, then virtual nodes are disabled. The topology aware consistent hash must be used if you wish to take advantage of virtual nodes. A default of 1 is used. The default value is 1."/>
- <c:simple-property name="__type" displayName="Type of cache" required="true" readOnly="true" default="local-cache" description="Type of cache">
+ <c:simple-property name="__type" displayName="Type of cache" required="true" readOnly="true" default="invalidation-cache" description="Type of cache">
<c:property-options>
<c:option value="invalidation-cache"/>
- <c:option value="distributed-cache"/>
<c:option value="replicated-cache"/>
</c:property-options>
</c:simple-property>
<c:template name="Invalidation Cache" description="Invalidation Cache">
<c:simple-property name="__type" readOnly="true" default="invalidation-cache"/>
</c:template>
- <c:template name="Distributed Cache" description="Distributed Cache">
- <c:simple-property name="__type" readOnly="true" default="distributed-cache"/>
- </c:template>
<c:template name="Replicated Cache" description="Replicated Cache">
<c:simple-property name="__type" readOnly="true" default="replicated-cache"/>
</c:template>
</resource-configuration>
</service>
+ <service name="Distributed Cache (Managed Server)"
+ discovery="SubsystemDiscovery"
+ class="BaseComponent">
+
+ <plugin-configuration>
+ <c:simple-property name="path" readOnly="true" default="distributed-cache"/>
+ </plugin-configuration>
+
+ <resource-configuration>
+ <c:simple-property name="start" required="false" type="string" readOnly="true" default="LAZY" description="The cache start mode, which can be EAGER (immediate start) or LAZY (on-demand start).">
+ <c:property-options>
+ <c:option value="LAZY"/>
+ <c:option value="EAGER"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="batching" required="false" type="boolean" readOnly="true" default="false" description="If enabled, the invocation batching API will be made available for this cache."/>
+ <c:simple-property name="indexing" required="false" type="string" readOnly="true" default="NONE" description="If enabled, entries will be indexed when they are added to the cache. Indexes will be updated as entries change or are removed.">
+ <c:property-options>
+ <c:option value="NONE"/>
+ <c:option value="LOCAL"/>
+ <c:option value="ALL"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="jndi-name" required="false" type="string" readOnly="true" description="The jndi-name to which to bind this cache instance."/>
+ <c:simple-property name="mode" required="false" type="string" readOnly="true" default="SYNC" description="Sets the clustered cache mode, ASYNC for asynchronous operation, or SYNC for synchronous operation.">
+ <c:property-options>
+ <c:option value="SYNC"/>
+ <c:option value="ASYNC"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="queue-size" required="false" type="integer" readOnly="true" default="0" description="In ASYNC mode, this attribute can be used to trigger flushing of the queue when it reaches a specific threshold."/>
+ <c:simple-property name="queue-flush-interval" required="false" type="long" readOnly="true" default="10" description="In ASYNC mode, this attribute controls how often the asynchronous thread used to flush the replication queue runs. This should be a positive integer which represents thread wakeup time in milliseconds."/>
+ <c:simple-property name="remote-timeout" required="false" type="long" readOnly="true" default="17500" description="In SYNC mode, the timeout (in ms) used to wait for an acknowledgment when making a remote call, after which the call is aborted and an exception is thrown."/>
+ <c:simple-property name="async-marshalling" required="false" type="boolean" readOnly="true" defaultValue="false" description="If enabled, this will cause marshalling of entries to be performed asynchronously. The default value is false."/>
+ <c:simple-property name="l1-lifespan" required="false" type="long" readOnly="true" defaultValue="600000" description="Maximum lifespan of an entry placed in the L1 cache. This element configures the L1 cache behavior in 'distributed' caches instances. In any other cache modes, this element is ignored. The default value is 600000."/>
+ <c:simple-property name="module" required="false" type="string" readOnly="true" description="The module whose class loader should be used when building this cache's configuration."/>
+ <c:simple-property name="owners" required="false" type="integer" readOnly="true" defaultValue="2" description="Number of cluster-wide replicas for each cache entry. The default value is 2."/>
+ <c:simple-property name="virtual-nodes" required="false" type="integer" readOnly="true" defaultValue="1" description="Controls the number of virtual nodes per 'real' node. If numVirtualNodes is 1, then virtual nodes are disabled. The topology aware consistent hash must be used if you wish to take advantage of virtual nodes. A default of 1 is used. The default value is 1."/>
+ </resource-configuration>
+ </service>
+
<service name="Local Cache (Managed Server)"
discovery="SubsystemDiscovery"
class="BaseComponent"
@@ -11331,7 +11365,7 @@
creationDataType="configuration">
<plugin-configuration>
- <c:simple-property name="path" readOnly="true" default="distributed-cache|invalidation-cache|replicated-cache"/>
+ <c:simple-property name="path" readOnly="true" default="invalidation-cache|replicated-cache"/>
</plugin-configuration>
<resource-configuration>
@@ -11360,30 +11394,66 @@
<c:simple-property name="queue-flush-interval" required="false" type="long" readOnly="false" default="10" description="In ASYNC mode, this attribute controls how often the asynchronous thread used to flush the replication queue runs. This should be a positive integer which represents thread wakeup time in milliseconds."/>
<c:simple-property name="remote-timeout" required="false" type="long" readOnly="false" default="17500" description="In SYNC mode, the timeout (in ms) used to wait for an acknowledgment when making a remote call, after which the call is aborted and an exception is thrown."/>
<c:simple-property name="async-marshalling" required="false" type="boolean" readOnly="false" defaultValue="false" description="If enabled, this will cause marshalling of entries to be performed asynchronously. The default value is false."/>
- <c:simple-property name="l1-lifespan" required="false" type="long" readOnly="false" defaultValue="600000" description="Maximum lifespan of an entry placed in the L1 cache. This element configures the L1 cache behavior in 'distributed' caches instances. In any other cache modes, this element is ignored. The default value is 600000."/>
<c:simple-property name="module" required="false" type="string" readOnly="false" description="The module whose class loader should be used when building this cache's configuration."/>
- <c:simple-property name="owners" required="false" type="integer" readOnly="false" defaultValue="2" description="Number of cluster-wide replicas for each cache entry. The default value is 2."/>
- <c:simple-property name="virtual-nodes" required="false" type="integer" readOnly="false" defaultValue="1" description="Controls the number of virtual nodes per 'real' node. If numVirtualNodes is 1, then virtual nodes are disabled. The topology aware consistent hash must be used if you wish to take advantage of virtual nodes. A default of 1 is used. The default value is 1."/>
- <c:simple-property name="__type" displayName="Type of cache" required="true" readOnly="true" default="local-cache" description="Type of cache">
+ <c:simple-property name="__type" displayName="Type of cache" required="true" readOnly="true" default="invalidation-cache" description="Type of cache">
<c:property-options>
<c:option value="invalidation-cache"/>
- <c:option value="distributed-cache"/>
<c:option value="replicated-cache"/>
</c:property-options>
</c:simple-property>
<c:template name="Invalidation Cache" description="Invalidation Cache">
<c:simple-property name="__type" readOnly="true" default="invalidation-cache"/>
</c:template>
- <c:template name="Distributed Cache" description="Distributed Cache">
- <c:simple-property name="__type" readOnly="true" default="distributed-cache"/>
- </c:template>
<c:template name="Replicated Cache" description="Replicated Cache">
<c:simple-property name="__type" readOnly="true" default="replicated-cache"/>
</c:template>
</resource-configuration>
</service>
+ <service name="Distributed Cache"
+ discovery="SubsystemDiscovery"
+ class="BaseComponent"
+ createDeletePolicy="both"
+ creationDataType="configuration">
+
+ <plugin-configuration>
+ <c:simple-property name="path" readOnly="true" default="distributed-cache"/>
+ </plugin-configuration>
+
+ <resource-configuration>
+ <c:simple-property name="start" required="false" type="string" readOnly="false" default="LAZY" description="The cache start mode, which can be EAGER (immediate start) or LAZY (on-demand start).">
+ <c:property-options>
+ <c:option value="LAZY"/>
+ <c:option value="EAGER"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="batching" required="false" type="boolean" readOnly="false" default="false" description="If enabled, the invocation batching API will be made available for this cache."/>
+ <c:simple-property name="indexing" required="false" type="string" readOnly="false" default="NONE" description="If enabled, entries will be indexed when they are added to the cache. Indexes will be updated as entries change or are removed.">
+ <c:property-options>
+ <c:option value="NONE"/>
+ <c:option value="LOCAL"/>
+ <c:option value="ALL"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="jndi-name" required="false" type="string" readOnly="false" description="The jndi-name to which to bind this cache instance."/>
+ <c:simple-property name="mode" required="true" type="string" readOnly="false" default="SYNC" defaultValue="SYNC" description="Sets the clustered cache mode, ASYNC for asynchronous operation, or SYNC for synchronous operation.">
+ <c:property-options>
+ <c:option value="SYNC"/>
+ <c:option value="ASYNC"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="queue-size" required="false" type="integer" readOnly="false" default="0" description="In ASYNC mode, this attribute can be used to trigger flushing of the queue when it reaches a specific threshold."/>
+ <c:simple-property name="queue-flush-interval" required="false" type="long" readOnly="false" default="10" description="In ASYNC mode, this attribute controls how often the asynchronous thread used to flush the replication queue runs. This should be a positive integer which represents thread wakeup time in milliseconds."/>
+ <c:simple-property name="remote-timeout" required="false" type="long" readOnly="false" default="17500" description="In SYNC mode, the timeout (in ms) used to wait for an acknowledgment when making a remote call, after which the call is aborted and an exception is thrown."/>
+ <c:simple-property name="async-marshalling" required="false" type="boolean" readOnly="false" defaultValue="false" description="If enabled, this will cause marshalling of entries to be performed asynchronously. The default value is false."/>
+ <c:simple-property name="l1-lifespan" required="false" type="long" readOnly="false" defaultValue="600000" description="Maximum lifespan of an entry placed in the L1 cache. This element configures the L1 cache behavior in 'distributed' caches instances. In any other cache modes, this element is ignored. The default value is 600000."/>
+ <c:simple-property name="module" required="false" type="string" readOnly="false" description="The module whose class loader should be used when building this cache's configuration."/>
+ <c:simple-property name="owners" required="false" type="integer" readOnly="false" defaultValue="2" description="Number of cluster-wide replicas for each cache entry. The default value is 2."/>
+ <c:simple-property name="virtual-nodes" required="false" type="integer" readOnly="false" defaultValue="1" description="Controls the number of virtual nodes per 'real' node. If numVirtualNodes is 1, then virtual nodes are disabled. The topology aware consistent hash must be used if you wish to take advantage of virtual nodes. A default of 1 is used. The default value is 1."/>
+ </resource-configuration>
+ </service>
+
<service name="Local Cache"
discovery="SubsystemDiscovery"
class="BaseComponent"
commit 9320bfa050c332a5f89334fcf5606395e5ef9098
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 22:46:02 2012 -0500
[BZ 852552] Update mod-cluster property name to load-balancing-group. The "domain" alias no longer works for load-balancing-group causing configuration updates to fail with unknown domain property.
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 bef06ec..81ddfe9 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
@@ -168,7 +168,7 @@
<c:simple-property name="connector" required="true" type="string" readOnly="false" defaultValue="ajp" description="Name of the web connector used to communicate with the load balancer.">
<c:option-source target="resource" expression="type=Connector plugin=&pluginName;"/>
</c:simple-property>
- <c:simple-property name="domain" required="false" type="string" readOnly="false" description="loadBalancingGroup name."/>
+ <c:simple-property name="load-balancing-group" required="false" type="string" readOnly="false" description="loadBalancingGroup name."/>
</c:group>
<c:group name="context" displayName="Web Context Options">
commit 9f82d413e980967ea3fae7ffe2579c44cc29cbb7
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 22:44:05 2012 -0500
[BZ 852552] Removing properties from the Transport subresource because the resource definition no longer contains them.
Because unset properties are now always sent to the AS7 server, all these removed Transport properties were sent to the AS7 causing an unknown property failure.
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 6f13412..bef06ec 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
@@ -2099,9 +2099,6 @@
<c:simple-property name="cluster" required="false" type="string" readOnly="true" description="The name of the group communication cluster"/>
<c:simple-property name="executor" required="false" type="string" readOnly="true" description="The executor to use for the transport"/>
<c:simple-property name="lock-timeout" required="false" type="long" readOnly="true" defaultValue="240000" description="The timeout for locks for the transport. The default value is 240000."/>
- <c:simple-property name="machine" required="false" type="string" readOnly="true" description="A machine identifier for the transport"/>
- <c:simple-property name="rack" required="false" type="string" readOnly="true" description="A rack identifier for the transport"/>
- <c:simple-property name="site" required="false" type="string" readOnly="true" description="A site identifier for the transport"/>
<c:simple-property name="stack" required="false" type="string" readOnly="true" description="The jgroups stack to use for the transport"/>
</resource-configuration>
</service>
@@ -11431,9 +11428,6 @@
<c:simple-property name="cluster" required="false" type="string" readOnly="false" description="The name of the group communication cluster"/>
<c:simple-property name="executor" required="false" type="string" readOnly="false" description="The executor to use for the transport"/>
<c:simple-property name="lock-timeout" required="false" type="long" readOnly="false" defaultValue="240000" description="The timeout for locks for the transport. The default value is 240000."/>
- <c:simple-property name="machine" required="false" type="string" readOnly="false" description="A machine identifier for the transport"/>
- <c:simple-property name="rack" required="false" type="string" readOnly="false" description="A rack identifier for the transport"/>
- <c:simple-property name="site" required="false" type="string" readOnly="false" description="A site identifier for the transport"/>
<c:simple-property name="stack" required="false" type="string" readOnly="false" description="The jgroups stack to use for the transport"/>
</resource-configuration>
</service>
commit c1655d4d576311b9034a31b505e75981b1d6e720
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 22:39:35 2012 -0500
[BZ 852552] Send unset properties to AS7 as null.
Existing code was not sending updates for unset properties at all to AS7 making it impossible to unset (or set to empty) a property after it was set to something not null.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
index aad2105..f73ccf5 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
@@ -431,16 +431,25 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
private void createWriteAttributePropertySimple(CompositeOperation cop, PropertySimple property,
PropertyDefinitionSimple propertyDefinition, Address address) {
- // If the property value is null and the property is optional, skip too
- if (property.getStringValue() == null && !propertyDefinition.isRequired())
- return;
-
if (property.getName().endsWith(":ignore")) // Caller takes care
return;
if (propertyDefinition.isReadOnly() && !createChildRequested)
return;
+ //If the property value is null and the property is optional,
+ //then send default value or null to the server
+ if (property.getStringValue() == null && !propertyDefinition.isRequired()) {
+ String name = property.getName();
+ if (name.indexOf(':') != -1) {
+ name = name.substring(0, name.indexOf(":"));
+ }
+
+ Operation writeAttribute = new WriteAttribute(address, name, null);
+ cop.addStep(writeAttribute);
+ return;
+ }
+
SimpleEntry<String, Object> entry = this.preparePropertySimple(property, propertyDefinition);
Operation writeAttribute = new WriteAttribute(address, entry.getKey(), entry.getValue());
cop.addStep(writeAttribute);
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java
index 21e3d5f..48b6783 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java
@@ -59,7 +59,6 @@ public class ConfigurationUpdatingTest extends AbstractConfigurationHandlingTest
public void test1() throws Exception {
ConfigurationDefinition definition = loadDescriptor("simple1");
-
FakeConnection connection = new FakeConnection();
ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(definition, connection, null);
@@ -70,12 +69,22 @@ public class ConfigurationUpdatingTest extends AbstractConfigurationHandlingTest
CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, new Address());
- assert cop.numberOfSteps() == 1;
- Operation step1 = cop.step(0);
- assert step1.getOperation().equals("write-attribute");
- Map<String, Object> props = step1.getAdditionalProperties();
- assert props.size() == 2;
+ Assert.assertEquals(cop.numberOfSteps(), 2);
+ for (int i = 0; i < cop.numberOfSteps(); i++) {
+ Operation step = cop.step(0);
+ Assert.assertEquals(step.getOperation(), "write-attribute");
+ Map<String, Object> stepProps = step.getAdditionalProperties();
+ Assert.assertEquals(stepProps.size(), 2);
+
+ if (stepProps.get("name").equals("needed")) {
+ Assert.assertEquals(stepProps.get("value"), "test");
+ } else if (stepProps.get("name").equals("optional")) {
+ Assert.assertEquals(stepProps.get("value"), null);
+ } else {
+ Assert.fail("Unexepected property found!");
+ }
+ }
}
public void test2() throws Exception {
commit e1d2190442ddcfe023696fa59b040f78929a27c6
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 20:14:08 2012 -0500
[BZ 846400] Add validation for components that rely connectors and discovery group name. A compoment should have either the connector or discovery group configured, but not both.
This validation is handled by the AS7 server itself for new resource creation but the validation is missing for configuration updates. Without this validation code in place, the AS7 server accepts the commands, persists the configuration, but fails to reload or restart rendering the server unusable until the configuration file is manually edited. With this fix, the AS7 plugin will not send the configuration updates to the AS7 server unless they meet the descriptor requirements.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConnectorDiscoveryGroupValidatorComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConnectorDiscoveryGroupValidatorComponent.java
new file mode 100644
index 0000000..fab342f
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConnectorDiscoveryGroupValidatorComponent.java
@@ -0,0 +1,83 @@
+/*
+ * 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.modules.plugins.jbossas7;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
+import org.rhq.core.domain.configuration.PropertyList;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public class ConnectorDiscoveryGroupValidatorComponent extends BaseComponent<ResourceComponent<?>> {
+
+ @Override
+ public void updateResourceConfiguration(ConfigurationUpdateReport report) {
+ Configuration resourceConfiguration = report.getConfiguration();
+ ResourceType resourceType = this.context.getResourceType();
+
+ // we need to check that a connector XOR a discovery-group-name is given
+ int configuredItemsFound = 0;
+ String errorMessage = "";
+
+ if (resourceType.getName().equals("Connection Factory")
+ || resourceType.getName().equals("Pooled Connection Factory")) {
+
+ PropertyMap connector = resourceConfiguration.getMap("connector:collapsed");
+ if (connector != null) {
+ String name = connector.getSimpleValue("name:0", "");
+ if (!name.isEmpty()) {
+ configuredItemsFound++;
+ }
+ }
+
+ errorMessage = "You need to provide either a connector name OR a discovery-group-name. ";
+ } else if (resourceType.getName().equals("Bridge") || resourceType.getName().equals("Cluster Connection")) {
+
+ PropertyList staticConnectors = resourceConfiguration.getList("static-connectors:nullable");
+ if (staticConnectors != null) {
+ if (!staticConnectors.getList().isEmpty()) {
+ configuredItemsFound++;
+ }
+ }
+
+ errorMessage = "You need to provide either static connectors name OR a discovery-group-name. ";
+ }
+
+ String discoveryGroup = resourceConfiguration.getSimpleValue("discovery-group-name", "");
+ if (!discoveryGroup.isEmpty()) {
+ configuredItemsFound++;
+ }
+
+ if (configuredItemsFound != 1) {
+ errorMessage += (configuredItemsFound == 0) ? "You provided none." : "You provided both.";
+ report.setErrorMessage(errorMessage);
+ report.setStatus(ConfigurationUpdateStatus.FAILURE);
+ } else {
+ super.updateResourceConfiguration(report);
+ }
+ }
+}
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HornetQComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HornetQComponent.java
index dad90bc..cd791fa 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HornetQComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HornetQComponent.java
@@ -21,9 +21,7 @@ package org.rhq.modules.plugins.jbossas7;
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.resource.CreateResourceStatus;
-import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pluginapi.inventory.CreateResourceReport;
/**
@@ -43,31 +41,6 @@ public class HornetQComponent extends TemplatedSubResourcesComponent {
return report;
}
- ResourceType resourceType = report.getResourceType();
- if (resourceType.getName().equals("Connection-Factory")) {
- // we need to check that a connector XOR a discovery-group-name is given
- int found = 0;
- PropertyMap connector = resourceConfiguration.getMap("connector:collapsed");
-
- if (connector != null) {
-
- String name = connector.getSimpleValue("name:0", "");
- if (!name.isEmpty())
- found++;
- }
- String discoveryGroup = resourceConfiguration.getSimpleValue("discovery-group-name", "");
- if (!discoveryGroup.isEmpty())
- found++;
-
- if (found == 0 || found == 2) {
- String errorMessage = "You need to provide either a connector name OR a discovery-group-name. You provided ";
- errorMessage += (found == 0) ? "none" : "both";
- report.setErrorMessage(errorMessage);
- report.setStatus(CreateResourceStatus.FAILURE);
- return report;
- }
- }
-
report = super.createResource(report);
return report;
}
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JmsComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JmsComponent.java
index 8b6eb12..1ede55e 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JmsComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JmsComponent.java
@@ -21,16 +21,13 @@ package org.rhq.modules.plugins.jbossas7;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
import org.rhq.core.domain.configuration.PropertyList;
-import org.rhq.core.domain.configuration.PropertyMap;
-import org.rhq.core.domain.resource.CreateResourceStatus;
-import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
/**
* Component class for the JMS subsystem
* @author Heiko W. Rupp
*/
-public class JmsComponent extends BaseComponent {
+public class JmsComponent extends ConnectorDiscoveryGroupValidatorComponent {
@Override
public void updateResourceConfiguration(ConfigurationUpdateReport report) {
@@ -43,31 +40,8 @@ public class JmsComponent extends BaseComponent {
return;
}
- ResourceType resourceType = context.getResourceType();
- if (resourceType.getName().equals("Connection-Factory")) {
- // we need to check that a connector XOR a discovery-group-name is given
- int found = 0;
- PropertyMap connector = resourceConfiguration.getMap("connector:collapsed");
-
- if (connector != null) {
-
- String name = connector.getSimpleValue("name:0", "");
- if (!name.isEmpty())
- found++;
- }
- String discoveryGroup = resourceConfiguration.getSimpleValue("discovery-group-name", "");
- if (!discoveryGroup.isEmpty())
- found++;
-
- if (found == 0 || found == 2) {
- String errorMessage = "You need to provide either a connector name OR a discovery-group-name. You provided ";
- errorMessage += (found == 0) ? "none" : "both";
- report.setErrorMessage(errorMessage);
- report.setStatus(ConfigurationUpdateStatus.FAILURE);
- return;
- }
- }
-
+ //defer the rest of the validation for connector and discovery group name to
+ //the base class
super.updateResourceConfiguration(report);
}
}
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 8143d04..6f13412 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
@@ -4654,7 +4654,7 @@
<service name="Cluster Connection (Managed Server)"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="ConnectorDiscoveryGroupValidatorComponent"
createDeletePolicy="neither">
<plugin-configuration>
@@ -4784,7 +4784,7 @@
<service name="Bridge (Managed Server)"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="ConnectorDiscoveryGroupValidatorComponent"
createDeletePolicy="neither">
<plugin-configuration>
@@ -6804,7 +6804,7 @@
<service name="Cluster Connection (Profile)"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="ConnectorDiscoveryGroupValidatorComponent"
createDeletePolicy="both">
<plugin-configuration>
@@ -6893,7 +6893,7 @@
<service name="Bridge (Profile)"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="ConnectorDiscoveryGroupValidatorComponent"
createDeletePolicy="both">
<plugin-configuration>
@@ -12855,7 +12855,7 @@
<service name="Cluster Connection"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="ConnectorDiscoveryGroupValidatorComponent"
createDeletePolicy="both">
<plugin-configuration>
@@ -12985,7 +12985,7 @@
<service name="Bridge"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="ConnectorDiscoveryGroupValidatorComponent"
createDeletePolicy="both">
<plugin-configuration>
commit e96ce182758719f86364bdc7a2e73c287dddbe4c
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 15:22:40 2012 -0500
[BZ 852534] Collapsed maps with null keys should be set to null. Attempting to send maps with null values to the application server results in validation errors.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
index 8286f17..aad2105 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
@@ -628,10 +628,14 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
throw new IllegalArgumentException("Member names in a :collapsed map must end in :0 and :1");
}
- Map<String, Object> resultMap = new HashMap<String, Object>();
- resultMap.put(key, value);
+ if (key != null) {
+ Map<String, Object> resultMap = new HashMap<String, Object>();
+ resultMap.put(key, value);
- return resultMap;
+ return resultMap;
+ } else {
+ return null;
+ }
}
commit 9fda60f21e354f3b33a1ecf85b81cae19e0af1af
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Tue Aug 28 14:34:23 2012 +0200
[BZ 850818 - Globally uncaught exception on clicking OK button while adding CLI Script alert notification to the alert definition] Added the check whether the repository has been picked
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java
index f63eb55..b212043 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java
@@ -403,6 +403,11 @@ public class CliNotificationSenderForm extends AbstractNotificationSenderForm {
}
private void validatePackage(final AsyncCallback<Void> callback) {
+ if (config.selectedRepo == null) {
+ repoSelector.setIcons(failureIcon);
+ callback.onFailure(null);
+ return;
+ }
getConfiguration().put(new PropertySimple(PROP_REPO_ID, config.selectedRepo.getId()));
if (packageSelector.getSelectedIndex() == 0) {
commit f3f26d0a85bf71fad532424b6267a331bd048136
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Aug 27 14:42:26 2012 -0700
[BZ 848501] - IE8 rendering of resource measurement time overlaid on the actual metric name
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
index c27e626..8a0898d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
@@ -290,6 +290,7 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet {
StaticTextItem value = AbstractActivityView
.newTextItem(convertedValue);
value.setVAlign(VerticalAlignment.TOP);
+ value.setAlign(Alignment.RIGHT);
row.setItems(graphContainer, link, value);
row.setWidth100();
commit b8a6a496d40915abb22fdd87753aec0c131ed95d
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Fri Aug 24 10:21:20 2012 -0500
[BZ 849964] Increase the operation timeout to 30 seconds to avoid cases where the host is under heavy load thus making all managed server operations take longer than the default 10 seconds.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java
index d26f54e..e7fcd5b 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java
@@ -271,7 +271,7 @@ public class ManagedASComponent extends BaseComponent<HostControllerComponent<?>
}
}
- Result res = getASConnection().execute(op);
+ Result res = getASConnection().execute(op, 30);
OperationResult opRes;
if (res.isSuccess()) {
commit 97867e2b4b241fa5ea33d0f439b1026914def5be
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Thu Aug 23 16:55:00 2012 +0200
[BZ 851239 - Globally uncaught exception on clicking the link Bundles->Repositories->JBoss Patches] Defensive programming - check for null/empty list -> exception is not thrown
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java
index 6eaa263..1f2f660 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java
@@ -42,7 +42,11 @@ import org.rhq.core.domain.bundle.Bundle;
import org.rhq.core.domain.criteria.BundleCriteria;
import org.rhq.core.domain.tagging.Tag;
import org.rhq.core.domain.util.PageList;
-import org.rhq.enterprise.gui.coregui.client.*;
+import org.rhq.enterprise.gui.coregui.client.BookmarkableView;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.IconEnum;
+import org.rhq.enterprise.gui.coregui.client.ViewId;
+import org.rhq.enterprise.gui.coregui.client.ViewPath;
import org.rhq.enterprise.gui.coregui.client.bundle.BundleTopView;
import org.rhq.enterprise.gui.coregui.client.bundle.deploy.BundleDeployWizard;
import org.rhq.enterprise.gui.coregui.client.bundle.deployment.BundleDeploymentView;
@@ -286,6 +290,11 @@ public class BundleView extends LocatableVLayout implements BookmarkableView {
}
public void onSuccess(PageList<Bundle> result) {
+ if (result == null || result.isEmpty()) {
+ CoreGUI.getMessageCenter().notify(
+ new Message(MSG.view_bundle_list_error4(), Message.Severity.Error));
+ return;
+ }
Bundle bundle = result.get(0);
viewBundle(bundle, viewPath.getCurrent());
}
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index cfa1f6d..9681ea1 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -413,10 +413,10 @@ filter_from_date = From
filter_to_date = To
group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
-search_invalid_search_expression = Invalid search expression.
-search_failed_to_save_search = Failed to Save Search: {0}
search_failed_to_retrieve_saved_search = Failed to retrieve saved search
search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
+search_failed_to_save_search = Failed to Save Search: {0}
+search_invalid_search_expression = Invalid search expression.
search_name_your_search = name you search
search_successfully_saved_search = Successfully Saved Search: {0}
util_ancestry_parentAncestry = Parent Ancestry for:
@@ -1127,6 +1127,7 @@ view_bundle_list_destinationsCount = Destinations Count
view_bundle_list_error1 = Failed to load bundle to deploy [{0}]
view_bundle_list_error2 = Failed to get a single bundle to deploy [{0}]
view_bundle_list_error3 = Failed to load bundle
+view_bundle_list_error4 = No bundles found in this repository
view_bundle_list_loadFailure = Failed to load the bundle to be deployed [{0}]
view_bundle_list_loadWithLatestFailure = Failed to load bundle with the latest version data
view_bundle_list_singleLoadFailure = Failed to get a single bundle to be deployed [{0}]
@@ -1182,7 +1183,7 @@ view_configEdit_error_3 = Cannot add property named [{0}]. The property name is
view_configEdit_files = Files
view_configEdit_hideAll = Hide All
view_configEdit_jumpToSection = Jump to Section
-view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
view_configEdit_msg_1 = Added property [{0}] to the set.
view_configEdit_msg_2 = Removed properties from the set.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index 5be0d57..b2a842d 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -1146,6 +1146,7 @@ view_bundle_list_destinationsCount = PoÄet cÃlů
view_bundle_list_error1 = NepodaÅilo se naÄÃst balÃk k nasazenà [{0}]
view_bundle_list_error2 = NepodaÅilo se zÃskat 1 balÃk k nasazenà [{0}]
view_bundle_list_error3 = NepodaÅilo se zÃskat balÃk
+view_bundle_list_error3 = V tomto repozitáÅi nejsou şádné balÃky
view_bundle_list_loadFailure = NepodaÅilo se zÃskat balÃk k nasazenà [{0}]
view_bundle_list_loadWithLatestFailure = NepodaÅilo se zÃskat balÃk s poslednà verzÃ
view_bundle_list_singleLoadFailure = NepodaÅilo se zÃskat 1 balÃk k nasazenà [{0}]
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index d39f16a..4fe89d0 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -397,10 +397,10 @@ filter_from_date = Von
filter_to_date = Bis
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} der {1} Gruppenmitglieder haben eine ''{2}'' Ressource
-##search_invalid_search_expression = Invalid search expression.
-##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
+##search_failed_to_save_search = Failed to Save Search: {0}
+##search_invalid_search_expression = Invalid search expression.
##search_name_your_search = name you search
##search_successfully_saved_search = Successfully Saved Search: {0}
util_disambiguationReportDecorator_pluginSuffix = ({0} Plugin)
@@ -1013,6 +1013,7 @@ view_bundle_list_destinationsCount = Anzahl Ziele
##view_bundle_list_error1 = Failed to load bundle to deploy [{0}]
##view_bundle_list_error2 = Failed to get a single bundle to deploy [{0}]
view_bundle_list_error3 = Konnte das Bundle nicht laden
+##view_bundle_list_error4 = No bundles found in this repository
##view_bundle_list_loadFailure = Failed to load the bundle to be deployed [{0}]
##view_bundle_list_loadWithLatestFailure = Failed to load bundle with the latest version data
##view_bundle_list_singleLoadFailure = Failed to get a single bundle to be deployed [{0}]
@@ -1066,7 +1067,7 @@ view_configEdit_confirm_2 = Sind Sie sicher dass sie diese Zeile löschen wollen
view_configEdit_files = Dateien
view_configEdit_hideAll = Alle verbergen
view_configEdit_jumpToSection = Zum Abschnitt springen
-##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
view_configEdit_msg_1 = Eigentschaft [{0}] zur Menge hinzugefÃŒgt
##view_configEdit_msg_2 = Removed properties from the set.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index 6c2044a..e2e25e8 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -1123,6 +1123,7 @@ view_bundle_list_destinationsCount = å®å
æ°
view_bundle_list_error1 = [{0}] ããããã€ããããã®ãã³ãã«ã®ããŒãã«å€±æããŸãã
view_bundle_list_error2 = [{0}] ããããã€ããããã®åäžãã³ãã«ã®ååŸã«å€±æããŸãã
view_bundle_list_error3 = ãã³ãã«ã®ããŒãã«å€±æããŸãã
+##view_bundle_list_error4 = No bundles found in this repository
view_bundle_list_loadFailure = ãããã€ããããã³ãã« [{0}] ã®ããŒãã«å€±æããŸãã
view_bundle_list_loadWithLatestFailure = ææ°ããŒãžã§ã³ããŒã¿ãæã€ãã³ãã«ã®ããŒãã«å€±æããŸãã
view_bundle_list_singleLoadFailure = ãããã€ãããåäžãã³ãã« [{0}] ã®ååŸã«å€±æããŸãã
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 9f00c55..e3f044f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -416,10 +416,10 @@ favorites_resources = Recursos Favoritos
##filter_to_date = To
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
-##search_invalid_search_expression = Invalid search expression.
-##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
+##search_failed_to_save_search = Failed to Save Search: {0}
+##search_invalid_search_expression = Invalid search expression.
##search_name_your_search = name you search
##search_successfully_saved_search = Successfully Saved Search: {0}
util_ancestry_parentAncestry = Ancestral para:
@@ -1133,6 +1133,7 @@ view_bundle_list_destinationsCount = Soma das Destina\u00E7\u00F5es
view_bundle_list_error1 = Falha ao carregar bundle [{0}] para implantar
view_bundle_list_error2 = Falha ao obter um \u00FAnico bundle [{0}] para deploy
view_bundle_list_error3 = Falha ao carregar o bundle
+##view_bundle_list_error4 = No bundles found in this repository
view_bundle_list_loadFailure = Falha ao carregar o bundle [{0}] para ser implantado
view_bundle_list_loadWithLatestFailure = Falha ao carregar o bundle com os dados da \u00FAltima vers\u00E3o
view_bundle_list_singleLoadFailure = Falha ao obter um \u00FAnico bundle [{0}] para ser implantado
@@ -1188,7 +1189,7 @@ view_configEdit_error_3 = N\u00E3o f\u00F3 poss\u00EDvel adicionar a propriedade
view_configEdit_files = Arquivos
view_configEdit_hideAll = Ocultar todos
view_configEdit_jumpToSection = Ir direto para a Sele\u00E7\u00E3o
-##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
view_configEdit_msg_1 = Propriedade [{0}] adicionada ao conjunto.
view_configEdit_msg_2 = Propriedades removidas do conjunto.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 25671e1..e27ce16 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -2464,6 +2464,7 @@ view_admin_downloads_cli_version = ÐеÑÑÐžÑ CLI
##view_admin_downloads_connectors_none = No connectors are available for download
##view_alert_details_field_resource_ancestry = Resource Ancestry
##view_alert_details_field_watched_resource = Watched Resource
+##view_bundle_list_error4 = No bundles found in this repository
##view_bundle_revertWizard_getInfoStep_revertDeployDescFull = [REVERT From] {0} [REVERT To] {1}
##view_configEdit_property = Property
##view_configEdit_unset = Unset?
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 827e01b..2de43cc 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -405,10 +405,10 @@ favorites_resources = \u8d44\u6e90\u6536\u85cf\u5939
##filter_to_date = To
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = \u9664\u53bb {1},{0}\u7684\u7ec4\u6210\u5458\u62e5\u6709 \u4e00\u4e2a''{2}''\u8d44\u6e90
-##search_invalid_search_expression = Invalid search expression.
-##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
+##search_failed_to_save_search = Failed to Save Search: {0}
+##search_invalid_search_expression = Invalid search expression.
##search_name_your_search = name you search
##search_successfully_saved_search = Successfully Saved Search: {0}
util_ancestry_parentAncestry = Parent Ancestry for:
@@ -1117,6 +1117,7 @@ view_bundle_list_destinationsCount = \u76ee\u7684\u5730\u6570
view_bundle_list_error1 = Failed to load bundle to deploy [{0}]
view_bundle_list_error2 = Failed to get a single bundle to deploy [{0}]
view_bundle_list_error3 = \u52a0\u8f7dbundle\u5931\u8d25
+##view_bundle_list_error4 = No bundles found in this repository
view_bundle_list_loadFailure = Failed to load the bundle to be deployed [{0}]
view_bundle_list_loadWithLatestFailure = Failed to load bundle with the latest version data
view_bundle_list_singleLoadFailure = Failed to get a single bundle to be deployed [{0}]
@@ -1172,7 +1173,7 @@ view_configEdit_error_3 = \u65e0\u6cd5\u6dfb\u52a0\u540d\u4e3a[{0}]\u7684\u5c5e\
view_configEdit_files = \u6587\u4ef6
view_configEdit_hideAll = \u9690\u85cf\u6240\u6709
view_configEdit_jumpToSection = \u8df3\u81f3\u6a21\u5757
-##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
view_configEdit_msg_1 = \u589e\u52a0\u5c5e\u6027 [{0}]\u5230\u96c6\u5408.
view_configEdit_msg_2 = \u79fb\u9664\u96c6\u5408\u5185\u6240\u6709\u7684\u5c5e\u6027.
commit 8fb35be5c92397b282a582c754c6b71b8b277a60
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Aug 23 12:08:11 2012 +0200
Duplicating all the tests that use scripting language to have both javascript and python versions.
diff --git a/modules/enterprise/binding/pom.xml b/modules/enterprise/binding/pom.xml
index 7d37053..37959d2 100644
--- a/modules/enterprise/binding/pom.xml
+++ b/modules/enterprise/binding/pom.xml
@@ -45,6 +45,13 @@
</dependency>
<dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-scripting-python</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
<groupId>${project.groupId}</groupId>
<artifactId>rhq-core-domain</artifactId>
<version>${project.version}</version>
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java
index c3d5450..cf93afb 100644
--- a/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java
@@ -40,19 +40,24 @@ import org.rhq.bindings.util.PackageFinder;
*
* @author Lukas Krejci
*/
-@Test
-public class ScriptEngineTest {
+public class ScriptEngineTest extends ScriptedTestBase {
private static StandardBindings EMPTY_BINDINGS = new StandardBindings(new PrintWriter(System.out), new FakeRhqFacade());
@Test
- public void testFactory() throws ScriptException, IOException {
+ public void testFactory_javascript() throws ScriptException, IOException {
ScriptEngine engine = getScriptEngine();
assertNotNull(engine);
}
@Test
- public void testSandbox() throws ScriptException, IOException {
+ public void testFactory_python() throws ScriptException, IOException {
+ ScriptEngine engine = getScriptEngine();
+ assertNotNull(engine);
+ }
+
+ @Test
+ public void testSandbox_javascript() throws ScriptException, IOException {
ScriptEngine sandbox = getSecuredScriptEngine();
try {
@@ -76,7 +81,44 @@ public class ScriptEngineTest {
}
@Test
- public void testStandardBindings() throws ScriptException, IOException {
+ public void testSandbox_python() throws Exception {
+ ScriptEngine sandbox = getSecuredScriptEngine();
+
+ try {
+ sandbox.eval("import java.lang as foo\nfoo.System.exit(1)");
+ } catch (Exception e) {
+ assertSecurityExceptionPresent(e);
+ }
+
+ try {
+ //try hard to get to the System.exit()
+ sandbox.eval(
+ "import java.lang as l\n" +
+ "import java.lang.reflect as r\n" +
+ "import java.beans as b\n" +
+ "cls = l.Class.forName('java.lang.System')\n" +
+ "params = r.Array.newInstance(l.Class.forName('java.lang.Object'), 1)\n" +
+ "params[0] = l.Integer.valueOf('1')\n" +
+ "st = b.Statement(cls, 'exit', params)\n" +
+ "st.execute()");
+
+ } catch (Exception e) {
+ assertSecurityExceptionPresent(e);
+ }
+ }
+
+ @Test
+ public void testStandardBindings_javascript() throws ScriptException, IOException {
+ ScriptEngine scriptEngine = getScriptEngine();
+
+ for(String var : EMPTY_BINDINGS.keySet()) {
+ boolean hasVar = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE).containsKey(var);
+ assertTrue(hasVar, "The variable '" + var + "' is not present in the script context but should be.");
+ }
+ }
+
+ @Test
+ public void testStandardBindings_python() throws Exception {
ScriptEngine scriptEngine = getScriptEngine();
for(String var : EMPTY_BINDINGS.keySet()) {
@@ -86,13 +128,11 @@ public class ScriptEngineTest {
}
private ScriptEngine getScriptEngine() throws ScriptException, IOException {
- return ScriptEngineFactory.getScriptEngine("javascript", new PackageFinder(Collections.<File> emptyList()),
- EMPTY_BINDINGS);
+ return getScriptEngine(new PackageFinder(Collections.<File> emptyList()), EMPTY_BINDINGS);
}
private ScriptEngine getSecuredScriptEngine() throws ScriptException, IOException {
- return ScriptEngineFactory.getSecuredScriptEngine("javascript",
- new PackageFinder(Collections.<File> emptyList()), EMPTY_BINDINGS, new StandardScriptPermissions());
+ return getSecuredScriptEngine(new PackageFinder(Collections.<File> emptyList()), EMPTY_BINDINGS, new StandardScriptPermissions());
}
private void assertSecurityExceptionPresent(Throwable t) {
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptedTestBase.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptedTestBase.java
new file mode 100644
index 0000000..9bf09b5
--- /dev/null
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptedTestBase.java
@@ -0,0 +1,220 @@
+/*
+ * 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.bindings;
+
+import static org.testng.Assert.fail;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.security.PermissionCollection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+import org.testng.IHookCallBack;
+import org.testng.IHookable;
+import org.testng.ITestContext;
+import org.testng.ITestNGMethod;
+import org.testng.ITestResult;
+import org.testng.annotations.AfterClass;
+
+import org.rhq.bindings.util.PackageFinder;
+
+/**
+ * This is a base class for tests that need to test the some functionality using
+ * the scripting languages.
+ * <p>
+ * It enforces the naming convention for the tests:
+ * <code>
+ * @Test
+ * public void myTestMethod_language() ...
+ * </code>
+ * The language is to be replaced with the name of the scripting language that the test method
+ * uses (e.g. javacript, python). This class then makes sure that each test exists for all
+ * the scripting languages that are present on the classpath.
+ * <p>
+ * This class also provides the {@link #getScriptEngine(PackageFinder, StandardBindings)} and
+ * {@link #getSecuredScriptEngine(PackageFinder, StandardBindings, PermissionCollection)} methods
+ * that, if invoked from within a test method call-chain, will return the script engine for the
+ * correct language under test (determined by the test method name suffix).
+ *
+ * @author Lukas Krejci
+ */
+public abstract class ScriptedTestBase implements IHookable {
+
+ private String currentLanguage;
+
+ @AfterClass
+ public void checkTestImplsForEachLanguage(ITestContext ctx) {
+ Set<Method> methods = getAllTestMethods(getClass(), ctx);
+
+ Set<String> supportedLanguages = ScriptEngineFactory.getSupportedLanguages();
+
+ Map<String, Set<String>> methodBaseNamesByLanguage = new HashMap<String, Set<String>>();
+
+ for (String lang : supportedLanguages) {
+ methodBaseNamesByLanguage.put(lang, new HashSet<String>());
+ }
+
+ Set<Method> invalidTestMethods = new HashSet<Method>();
+
+ for (Method m : methods) {
+ //check that the method name ends with one of the supported language names
+ boolean valid = false;
+ for (String lang : supportedLanguages) {
+ String suffix = "_" + lang;
+
+ if (!m.getName().endsWith(suffix)) {
+ continue;
+ }
+
+ //now put the method "basename" into our mapping array
+ String baseName = m.getName().substring(0, m.getName().lastIndexOf("_"));
+ methodBaseNamesByLanguage.get(lang).add(baseName);
+
+ valid = true;
+ break;
+ }
+
+ if (!valid) {
+ invalidTestMethods.add(m);
+ }
+ }
+
+ Set<String> missingTests = new HashSet<String>();
+
+ //now check that all languages have all test methods
+ for (Map.Entry<String, Set<String>> a : methodBaseNamesByLanguage.entrySet()) {
+ for (Map.Entry<String, Set<String>> b : methodBaseNamesByLanguage.entrySet()) {
+ String alang = a.getKey();
+ String blang = b.getKey();
+ Set<String> amethods = a.getValue();
+ Set<String> bmethods = b.getValue();
+
+ if (alang.equals(blang)) {
+ continue;
+ }
+
+ addMissing(amethods, bmethods, alang, missingTests);
+ addMissing(bmethods, amethods, blang, missingTests);
+ }
+ }
+
+ if (!invalidTestMethods.isEmpty() || !missingTests.isEmpty()) {
+ StringBuilder msg = new StringBuilder("Scripted test " + getClass() + " is invalid:\n");
+
+ if (!invalidTestMethods.isEmpty()) {
+ msg.append("Invalid method names:\n");
+ for (Method m : invalidTestMethods) {
+ msg.append(m.getName()).append("\n");
+ }
+ }
+
+ if (!missingTests.isEmpty()) {
+ msg.append("\nMissing tests for languages:\n");
+ for (String m : missingTests) {
+ msg.append(m).append("\n");
+ }
+ }
+
+ fail(msg.toString());
+ }
+ }
+
+ @Override
+ public final void run(IHookCallBack callBack, ITestResult testResult) {
+ String methodName = testResult.getMethod().getMethodName();
+ int underScoreIdx = methodName.lastIndexOf('_');
+ if (underScoreIdx >= 0 && underScoreIdx < methodName.length() - 1) {
+ currentLanguage = methodName.substring(underScoreIdx + 1);
+ } else {
+ currentLanguage = null;
+ }
+
+ callBack.runTestMethod(testResult);
+
+ currentLanguage = null;
+ }
+
+ /**
+ * Returns a new script engine implementation for the current test method.
+ * <p>
+ * The script engine implementation is determined based on the test method's name
+ * suffix.
+ * <p>
+ * E.g. if the test method ends with "_javascript", this method will return the javascript
+ * script engine.
+ * <p>
+ * This method is calling {@link ScriptEngineFactory#getScriptEngine(String, PackageFinder, StandardBindings)}
+ * but determines the "language" parameter for you.
+ *
+ * @param packageFinder the package finder to use for the script engine initialization
+ * @param bindings the bindings to use in the script engine
+ * @return the script engine
+ * @throws ScriptException
+ * @throws IOException
+ */
+ protected ScriptEngine getScriptEngine(PackageFinder packageFinder, StandardBindings bindings)
+ throws ScriptException, IOException {
+
+ return ScriptEngineFactory.getScriptEngine(currentLanguage, packageFinder, bindings);
+ }
+
+ /**
+ * Similar to {@link #getScriptEngine(PackageFinder, StandardBindings)} but returns the
+ * secured version of the script engine.
+ *
+ * @param packageFinder the package finder to use for the script engine initialization
+ * @param bindings the bindings to use in the script engine
+ * @param perms the permissions to run the scripts with
+ * @return the script engine
+ * @throws ScriptException
+ * @throws IOException
+ */
+ protected ScriptEngine getSecuredScriptEngine(PackageFinder packageFinder, StandardBindings bindings,
+ PermissionCollection perms) throws ScriptException, IOException {
+
+ return ScriptEngineFactory.getSecuredScriptEngine(currentLanguage, packageFinder, bindings, perms);
+ }
+
+ private static Set<Method> getAllTestMethods(Class<?> cls, ITestContext ctx) {
+ HashSet<Method> ret = new HashSet<Method>();
+ for (ITestNGMethod m : ctx.getAllTestMethods()) {
+ if (m.getTestClass().getRealClass().equals(cls)) {
+ ret.add(m.getConstructorOrMethod().getMethod());
+ }
+ }
+
+ return ret;
+ }
+
+ private static void addMissing(Set<String> methods, Set<String> referenceMethods, String lang, Set<String> missing) {
+ for (String m : referenceMethods) {
+ if (!methods.contains(m)) {
+ String fullName = m + "_" + lang;
+ missing.add(fullName);
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java
index 1d7f657..97753e3 100644
--- a/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java
@@ -26,118 +26,247 @@ package org.rhq.bindings.util;
import static org.testng.Assert.fail;
import java.io.File;
+import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
-import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import org.rhq.bindings.FakeRhqFacade;
-import org.rhq.bindings.ScriptEngineFactory;
+import org.rhq.bindings.ScriptedTestBase;
import org.rhq.bindings.StandardBindings;
-public class ScriptAssertTest {
+public class ScriptAssertTest extends ScriptedTestBase {
- private ScriptEngine engine;
+ private ScriptEngine getScriptEngine() {
+ try {
+ return getScriptEngine(new PackageFinder(Collections.<File> emptyList()), new StandardBindings(
+ new PrintWriter(System.out), new FakeRhqFacade()));
+ } catch (ScriptException e) {
+ fail("Could not get the script engine.", e);
+ return null;
+ } catch (IOException e) {
+ fail("Could not get the script engine.", e);
+ return null;
+ }
+ }
- @BeforeTest
- public void verifyScriptEngineIsAvailable() throws Exception {
- StandardBindings bindings = new StandardBindings(new PrintWriter(System.out), new FakeRhqFacade());
- engine = ScriptEngineFactory.getScriptEngine("javascript", new PackageFinder(Collections.<File> emptyList()),
- bindings);
+ @Test
+ public void testAssertExists_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "var a = 1; assertExists('a');", "assertExists should succeed for a defined variable.");
+ testThrowsAssertion(engine, "assertExists('foo')", "assertExists should fail for an undefined variable.");
+ testWorks(engine, "function func() { return 42 }; assertExists('func');",
+ "assertExists should succeed for a defined function.");
}
@Test
- public void testAssertExists() {
- testWorks("var a = 1; assertExists('a');", "assertExists should succeed for a defined variable.");
- testThrowsAssertion("assertExists('foo')", "assertExists should fail for an undefined variable.");
- testWorks("function func() { return 42 }; assertExists('func');",
+ public void testAssertExists_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "a = 1\n" + "assertExists('a')", "assertExists should succeed for a defined variable.");
+ testThrowsAssertion(engine, "assertExists('foo')", "assertExists should fail for an undefined variable.");
+ testWorks(engine, "def func():\n" + " return 42\n" + "assertExists('func')",
"assertExists should succeed for a defined function.");
}
@Test
- public void testAssertTrue() {
- testWorks("var a = true; assertTrue(a);", "assertTrue of a true variable should succeed");
- testWorks("assertTrue(1 == 1)", "assertTrue on a true boolean expression should succeed");
- testThrowsAssertion("var a = false; assertTrue(a)", "assertTrue should fail on a false variable");
- testThrowsAssertion("assertTrue(1 == 2)", "assertTrue should fail on a false boolean expression");
+ public void testAssertTrue_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "var a = true; assertTrue(a);", "assertTrue of a true variable should succeed");
+ testWorks(engine, "assertTrue(1 == 1)", "assertTrue on a true boolean expression should succeed");
+ testThrowsAssertion(engine, "var a = false; assertTrue(a)", "assertTrue should fail on a false variable");
+ testThrowsAssertion(engine, "assertTrue(1 == 2)", "assertTrue should fail on a false boolean expression");
+ }
+
+ @Test
+ public void testAssertTrue_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "a = True\n" + "assertTrue(a)", "assertTrue of a true variable should succeed");
+ testWorks(engine, "assertTrue(1 == 1)", "assertTrue on a true boolean expression should succeed");
+ testThrowsAssertion(engine, "a = False\n" + "assertTrue(a)", "assertTrue should fail on a false variable");
+ testThrowsAssertion(engine, "assertTrue(1 == 2)", "assertTrue should fail on a false boolean expression");
+ }
+
+ @Test
+ public void testAssertFalse_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "var a = false; assertFalse(a)", "assertFalse of a false variable should succeed");
+ testWorks(engine, "assertFalse(1 == 2)", "assertFalse on a false boolean expression should succeed");
+ testThrowsAssertion(engine, "var a = true; assertFalse(a)", "assertFalse should fail on a true variable");
+ testThrowsAssertion(engine, "assertFalse(1 == 1)", "assertFalse should fail on a true boolean expression");
}
-
+
@Test
- public void testAssertFalse() {
- testWorks("var a = false; assertFalse(a);", "assertFalse of a false variable should succeed");
- testWorks("assertFalse(1 == 2)", "assertFalse on a false boolean expression should succeed");
- testThrowsAssertion("var a = true; assertFalse(a)", "assertFalse should fail on a true variable");
- testThrowsAssertion("assertFalse(1 == 1)", "assertFalse should fail on a true boolean expression");
+ public void testAssertFalse_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "a = False\n" + "assertFalse(a)", "assertFalse of a false variable should succeed");
+ testWorks(engine, "assertFalse(1 == 2)", "assertFalse on a false boolean expression should succeed");
+ testThrowsAssertion(engine, "a = True\n" + "assertFalse(a)", "assertFalse should fail on a true variable");
+ testThrowsAssertion(engine, "assertFalse(1 == 1)", "assertFalse should fail on a true boolean expression");
}
-
+
@Test
- public void testAssertNull() {
- testWorks("assertNull(foo)", "assertNull should succeed on an undefined variable");
- testWorks("var foo = null; assertNull(foo);", "assertNull should succeed on a null variable");
- testWorks("assertNull(null)", "assertNull should succeed on a null literal");
- testThrowsAssertion("assertNull(1)", "assertNull should fail on a number");
- testThrowsAssertion("var foo = '1'; assertNull(foo)", "assertNull should fail on a non-null variable");
+ public void testAssertNull_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "var foo = null; assertNull(foo);", "assertNull should succeed on a null variable");
+ testWorks(engine, "assertNull(null)", "assertNull should succeed on a null literal");
+ testThrowsAssertion(engine, "assertNull(1)", "assertNull should fail on a number");
+ testThrowsAssertion(engine, "var foo = '1'; assertNull(foo)", "assertNull should fail on a non-null variable");
}
-
+
@Test
- public void testAssertNotNull() {
- testWorks("assertNotNull(1)", "assertNotNull should succeed on a number");
- testWorks("var foo = '1'; assertNotNull(foo)", "assertNotNull should succeed on a non-null variable");
- testThrowsAssertion("assertNotNull(foo)", "assertNotNull should fail on an undefined variable");
- testThrowsAssertion("var foo = null; assertNotNull(foo);", "assertNotNull should fail on a null variable");
- testThrowsAssertion("assertNotNull(null)", "assertNotNull should fail on a null literal");
+ public void testAssertNull_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "foo = None\n" + "assertNull(foo)", "assertNull should succeed on a null variable");
+ testWorks(engine, "assertNull(None)", "assertNull should succeed on a null literal");
+ testThrowsAssertion(engine, "assertNull(1)", "assertNull should fail on a number");
+ testThrowsAssertion(engine, "foo = '1'\n" + "assertNull(foo)", "assertNull should fail on a non-null variable");
}
-
+
@Test
- public void testAssertEquals_Numbers() {
- testWorks("assertEquals(1, 1)", "1 == 1");
- testWorks("assertEquals(1.0, 1)", "1.0 == 1");
- testWorks("assertEquals(1.0, 1.0)", "1.0 == 1.0");
- testThrowsAssertion("assertEquals(1, 2)", "1 == 2");
+ public void testAssertNotNull_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertNotNull(1)", "assertNotNull should succeed on a number");
+ testWorks(engine, "var foo = '1'; assertNotNull(foo)", "assertNotNull should succeed on a non-null variable");
+ testThrowsAssertion(engine, "assertNotNull(foo)", "assertNotNull should fail on an undefined variable");
+ testThrowsAssertion(engine, "var foo = null; assertNotNull(foo);",
+ "assertNotNull should fail on a null variable");
+ testThrowsAssertion(engine, "assertNotNull(null)", "assertNotNull should fail on a null literal");
}
-
+
@Test
- public void testAssertEquals_Arrays() {
- testWorks("assertEquals(['a', 'b'], ['a', 'b'])", "native array comparison");
- testThrowsAssertion("assertEquals(['a', 'b'], ['c', 'd'])", "native array comparison with difference");
+ public void testAssertNotNull_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertNotNull(1)", "assertNotNull should succeed on a number");
+ testWorks(engine, "foo = '1'\n" + "assertNotNull(foo)", "assertNotNull should succeed on a non-null variable");
+ testThrowsAssertion(engine, "assertNotNull(foo)", "assertNotNull should fail on an undefined variable");
+ testThrowsAssertion(engine, "foo = None\n" + "assertNotNull(foo);",
+ "assertNotNull should fail on a null variable");
+ testThrowsAssertion(engine, "assertNotNull(None)", "assertNotNull should fail on a null literal");
}
@Test
- public void testAssertEquals_Collections() {
- testWorks("a = new java.util.ArrayList; " + "b = new java.util.ArrayList; " + "a.add('a'); " + "b.add('a'); "
- + "assertEquals(a, b)", "ArrayList comparison");
- testThrowsAssertion("a = new java.util.ArrayList; " + "b = new java.util.ArrayList; " + "a.add('a'); "
+ public void testAssertEquals_Numbers_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertEquals(1, 1)", "1 == 1");
+ testWorks(engine, "assertEquals(1.0, 1)", "1.0 == 1");
+ testWorks(engine, "assertEquals(1.0, 1.0)", "1.0 == 1.0");
+ testThrowsAssertion(engine, "assertEquals(1, 2)", "1 == 2");
+ }
+
+ @Test
+ public void testAssertEquals_Numbers_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertEquals(1, 1)", "1 == 1");
+ //Python distinguishes between ints and floats, so this
+ //won't work (even though "1.0 == 1" returns true in pure python)
+ //testWorks(engine, "assertEquals(1.0, 1)", "1.0 == 1");
+ testWorks(engine, "assertEquals(1.0, 1.0)", "1.0 == 1.0");
+ testThrowsAssertion(engine, "assertEquals(1, 2)", "1 == 2");
+ }
+
+ @Test
+ public void testAssertEquals_Arrays_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertEquals(['a', 'b'], ['a', 'b'])", "native array comparison");
+ testThrowsAssertion(engine, "assertEquals(['a', 'b'], ['c', 'd'])", "native array comparison with difference");
+ }
+
+ @Test
+ public void testAssertEquals_Arrays_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertEquals(['a', 'b'], ['a', 'b'])", "native array comparison");
+ testThrowsAssertion(engine, "assertEquals(['a', 'b'], ['c', 'd'])", "native array comparison with difference");
+ }
+
+ @Test
+ public void testAssertEquals_Collections_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "a = new java.util.ArrayList; " + "b = new java.util.ArrayList; " + "a.add('a'); "
+ + "b.add('a'); " + "assertEquals(a, b)", "ArrayList comparison");
+ testThrowsAssertion(engine, "a = new java.util.ArrayList; " + "b = new java.util.ArrayList; " + "a.add('a'); "
+ "b.add('b'); " + "assertEquals(a, b)", "ArrayList comparison with difference");
}
@Test
- public void testAssertEqualsNoOrder() {
- testWorks("assertEqualsNoOrder(['a', 'b'], ['b', 'a'])", "native array comparison");
+ public void testAssertEquals_Collections_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "import java.util as u\n" + "a = u.ArrayList()\n" + "b = u.ArrayList()\n" + "a.add('a')\n"
+ + "b.add('a')\n" + "assertEquals(a, b)", "ArrayList comparison");
+ testThrowsAssertion(engine, "import java.util as u\n" + "a = u.ArrayList()\n" + "b = u.ArrayList()\n" + "a.add('a')\n"
+ + "b.add('b')\n" + "assertEquals(a, b)", "ArrayList comparison with difference");
}
@Test
- public void testAssertSame() {
- testWorks("var a = '1'; assertSame(a, a)", "assertSame should succeed comparing one variable");
- testWorks("var a = '1'; b = a; assertSame(a, b)", "asserSame should succeed comparing 2 references of the same object");
- testWorks("assertSame(null, null);", "assertSame should succeed on null values");
- testThrowsAssertion("var a = '1'; b = '2'; assertSame(a, b)", "assertSame should fail comparing 2 different variables");
- testThrowsAssertion("var a = 1; assertSame(a, null)", "assertSame should fail comparing non-null variable with a null value");
+ public void testAssertEqualsNoOrder_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertEqualsNoOrder(['a', 'b'], ['b', 'a'])", "native array comparison");
}
-
+
+ @Test
+ public void testAssertEqualsNoOrder_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertEqualsNoOrder(['a', 'b'], ['b', 'a'])", "native array comparison");
+ }
+
@Test
- public void testAssertNotSame() {
- testThrowsAssertion("var a = '1'; assertNotSame(a, a)", "assertNotSame should fail comparing one variable");
- testThrowsAssertion("var a = '1'; b = a; assertNotSame(a, b)", "asserNotSame should fail comparing 2 references of the same object");
- testThrowsAssertion("assertNotSame(null, null);", "assertNotSame should fail on null values");
- testWorks("var a = '1'; b = '2'; assertNotSame(a, b)", "assertNotSame should succeed comparing 2 different variables");
- testWorks("var a = 1; assertNotSame(a, null)", "assertNotSame should succeed comparing non-null variable with a null value");
+ public void testAssertSame_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "var a = '1'; assertSame(a, a)", "assertSame should succeed comparing one variable");
+ testWorks(engine, "var a = '1'; b = a; assertSame(a, b)",
+ "asserSame should succeed comparing 2 references of the same object");
+ testWorks(engine, "assertSame(null, null);", "assertSame should succeed on null values");
+ testThrowsAssertion(engine, "var a = '1'; b = '2'; assertSame(a, b)",
+ "assertSame should fail comparing 2 different variables");
+ testThrowsAssertion(engine, "var a = 1; assertSame(a, null)",
+ "assertSame should fail comparing non-null variable with a null value");
}
-
- private void testWorks(String script, String message) {
+
+ @Test
+ public void testAssertSame_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "a = '1'\n" + "assertSame(a, a)", "assertSame should succeed comparing one variable");
+ testWorks(engine, "a = '1'\n" + "b = a\n" + "assertSame(a, b)",
+ "asserSame should succeed comparing 2 references of the same object");
+ testWorks(engine, "assertSame(None, None)", "assertSame should succeed on null values");
+ testThrowsAssertion(engine, "a = '1'\n" + "b = '2'\n" + "assertSame(a, b)",
+ "assertSame should fail comparing 2 different variables");
+ testThrowsAssertion(engine, "a = 1\n" + "assertSame(a, None)",
+ "assertSame should fail comparing non-null variable with a null value");
+ }
+
+ @Test
+ public void testAssertNotSame_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testThrowsAssertion(engine, "var a = '1'; assertNotSame(a, a)",
+ "assertNotSame should fail comparing one variable");
+ testThrowsAssertion(engine, "var a = '1'; b = a; assertNotSame(a, b)",
+ "asserNotSame should fail comparing 2 references of the same object");
+ testThrowsAssertion(engine, "assertNotSame(null, null);", "assertNotSame should fail on null values");
+ testWorks(engine, "var a = '1'; b = '2'; assertNotSame(a, b)",
+ "assertNotSame should succeed comparing 2 different variables");
+ testWorks(engine, "var a = 1; assertNotSame(a, null)",
+ "assertNotSame should succeed comparing non-null variable with a null value");
+ }
+
+ @Test
+ public void testAssertNotSame_python() {
+ ScriptEngine engine = getScriptEngine();
+ testThrowsAssertion(engine, "a = '1'\n" + "assertNotSame(a, a)",
+ "assertNotSame should fail comparing one variable");
+ testThrowsAssertion(engine, "a = '1'\n" + "b = a\n" + "assertNotSame(a, b)",
+ "asserNotSame should fail comparing 2 references of the same object");
+ testThrowsAssertion(engine, "assertNotSame(None, None)", "assertNotSame should fail on null values");
+ testWorks(engine, "a = '1'\n" + "b = '2'\n" + "assertNotSame(a, b)",
+ "assertNotSame should succeed comparing 2 different variables");
+ testWorks(engine, "a = 1\n" + "assertNotSame(a, None)",
+ "assertNotSame should succeed comparing non-null variable with a null value");
+ }
+
+ private void testWorks(ScriptEngine engine, String script, String message) {
try {
engine.eval(script);
} catch (ScriptException e) {
@@ -145,7 +274,7 @@ public class ScriptAssertTest {
}
}
- private void testThrowsAssertion(String script, String message) {
+ private void testThrowsAssertion(ScriptEngine engine, String script, String message) {
try {
engine.eval(script);
} catch (ScriptException e) {
commit e21a7eb14096c4b23b638ff9028eb04857710e64
Author: John Sanda <jsanda(a)Johns-MacBook-Pro.local>
Date: Wed Aug 22 15:22:43 2012 -0400
[BZ 802796] Do not report entire stack trace for display in UI
After some discussion it has been decied to *not* display the entire stack trace in the
resource creation error message. Instead we will display the new, detailed error message
along with the more brief exception message that reports the plugin component method in
which the time out occurred. The full stack trace can still however be obtained from the
agent logs with DEBUG logging enabled.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java
index b3c65bd..8d34e9f 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java
@@ -163,8 +163,15 @@ public class CreateResourceRunner implements Callable, Runnable {
status = CreateResourceStatus.TIMED_OUT;
errorMessage = "The time out has been exceeded; however, the deployment may have been successful. You " +
"may want to run a discovery scan to see if the deployment did complete successfully. Also consider " +
- "using a higher time out value for future deployments.\n\nRoot Cause:\n";
- errorMessage += ThrowableUtil.getStackAsString(e);
+ "using a higher time out value for future deployments.";
+
+ if (log.isDebugEnabled()) {
+ log.debug("Failed to create resource for " + report + ". " + errorMessage, e);
+ } else {
+ log.info("Failed to create resource for " + report + ". " + errorMessage, e);
+ }
+
+ errorMessage += "\n\nRoot Cause:\n" + e.getMessage();
} catch (Throwable t) {
status = CreateResourceStatus.FAILURE;
errorMessage = ThrowableUtil.getStackAsString(t);
commit 5ffd6e1eb155bf0208690cce526fb18b832ba344
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue Aug 21 16:04:42 2012 -0400
Make drift def sync more efficient, and possibly avoid an NPE that was
seen intermittently.
- DriftServerServiceImpl.getDriftDefinitions() now only generates
Map entries for resources with drift definitions, avoiding unnecessary
list creation and subsequent processing.
- Added jdoc to that effect
- Changed private DriftSyncManager.syncConfigs() to syncDriftDefinitions
for clarity.
diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/drift/DriftServerService.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/drift/DriftServerService.java
index a6df831..1b2d048 100644
--- a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/drift/DriftServerService.java
+++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/drift/DriftServerService.java
@@ -121,6 +121,11 @@ public interface DriftServerService {
@Asynchronous
void repeatChangeSet(int resourceId, String driftDefName, int version);
+ /**
+ * @param resourceIds The resourceIds for which to fetch definitions.
+ * @return A Map from resourceId to its list of DriftDefinitions. Resources without DriftDefinitions are not included
+ * in the Map.
+ */
Map<Integer, List<DriftDefinition>> getDriftDefinitions(Set<Integer> resourceIds);
DriftSnapshot getCurrentSnapshot(int driftDefinitionId);
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java
index b24849b..5f4ec36 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java
@@ -111,11 +111,11 @@ public class DriftSyncManager {
synchronizer = synchronizerFactory.getRuntimeSynchronizer(driftMgr);
}
- syncConfigs(synchronizer, resourceIds);
+ syncDriftDefinitions(synchronizer, resourceIds);
syncContent(synchronizer);
}
- private void syncConfigs(DriftSynchronizer synchronizer, Set<Integer> resourceIds) {
+ private void syncDriftDefinitions(DriftSynchronizer synchronizer, Set<Integer> resourceIds) {
log.info("Starting server sync for drift definitions...");
long startTime = System.currentTimeMillis();
@@ -127,15 +127,15 @@ public class DriftSyncManager {
int totalAdded = 0;
for (Integer resourceId : driftDefs.keySet()) {
- Set<DriftDefinition> resourceConfigsOnServer = new TreeSet<DriftDefinition>(comparator);
- resourceConfigsOnServer.addAll(driftDefs.get(resourceId));
+ Set<DriftDefinition> driftDefinitionsOnServer = new TreeSet<DriftDefinition>(comparator);
+ driftDefinitionsOnServer.addAll(driftDefs.get(resourceId));
List<DriftDefinition> deletedDefs = synchronizer.getDeletedDefinitions(resourceId,
- resourceConfigsOnServer);
+ driftDefinitionsOnServer);
totalDeleted += deletedDefs.size();
synchronizer.purgeFromLocalInventory(resourceId, deletedDefs);
- List<DriftDefinition> addedDefs = synchronizer.getAddedDefinitions(resourceId, resourceConfigsOnServer);
+ List<DriftDefinition> addedDefs = synchronizer.getAddedDefinitions(resourceId, driftDefinitionsOnServer);
totalAdded += addedDefs.size();
synchronizer.addToLocalInventory(resourceId, addedDefs);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftServerServiceImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftServerServiceImpl.java
index b22caa7..b206b54 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftServerServiceImpl.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftServerServiceImpl.java
@@ -84,17 +84,19 @@ public class DriftServerServiceImpl implements DriftServerService {
Subject overlord = getSubjectManager().getOverlord();
PageList<DriftDefinition> definitions = getDriftManager().findDriftDefinitionsByCriteria(overlord, criteria);
- Map<Integer, List<DriftDefinition>> map = new HashMap<Integer, List<DriftDefinition>>();
- for (Integer resourceId : resourceIds) {
- map.put(resourceId, new ArrayList<DriftDefinition>());
- }
- for (DriftDefinition c : definitions) {
- List<DriftDefinition> list = map.get(c.getResource().getId());
- list.add(c);
- map.put(c.getResource().getId(), list);
+ Map<Integer, List<DriftDefinition>> result = new HashMap<Integer, List<DriftDefinition>>();
+
+ for (DriftDefinition driftDef : definitions) {
+ Integer resourceId = driftDef.getResource().getId();
+ List<DriftDefinition> list = result.get(resourceId);
+ if (null == list) {
+ list = new ArrayList<DriftDefinition>();
+ result.put(resourceId, list);
+ }
+ list.add(driftDef);
}
- return map;
+ return result;
}
@Override
commit 1b9503fa343a8ae8add7a65757a7e21a96186a5b
Author: John Sanda <jsanda(a)redhat.com>
Date: Tue Aug 21 14:03:14 2012 -0400
Delete any old copy of AS 7 zip file to force download
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index a640c0541..ecd2295 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -303,6 +303,7 @@
</condition>
<property name="as7.zipfile"
location="${java.io.tmpdir}/jboss-${as7.product}-${as7.version}.zip"/>
+ <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"/>
commit d5ddeaababea5b8ba7573d4dc752c1636ae52f65
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Aug 21 09:38:38 2012 -0700
Remove Opera browser support from GWT compile. Will speed up compile times from elimination of 7 language permutations.
diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index a4b08b0..82292eb 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -43,17 +43,15 @@
ie9: IE9 (although for smartgwt we fallback to IE8)
ie8: IE8
- gecko: FF1 (NOTE: Support for this was dropped in GWT 2.1.)
gecko1_8: FF2 and later
safari: Safari/Chrome
- opera: Opera
*NOTE*: Since we specify the meta "X-UA-Compatible: IE=IE8" HTTP header in CoreGUI.html, IE9 and later
will emulate IE8.
Multiple agents can be specified as a comma-delimited list, as demonstrated by the default
value below.
-->
- <gwt.userAgent>ie8,ie9,gecko1_8,safari,opera</gwt.userAgent>
+ <gwt.userAgent>ie8,ie9,gecko1_8,safari</gwt.userAgent>
<!-- Change this to "true" via the mvn command line or your ~/.m2/settings.xml to speed
up gwt compilation. -->
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index c5c4391..f797482 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -11,11 +11,6 @@
<inherits name='com.smartgwt.SmartGwt' />
<inherits name="com.smartgwt.tools.SmartGwtTools"/>
- <!-- TODO: Consider uncommenting this instead of enabling compression in Tomcat's server.xml once we upgrade to GWT
- 2.1 or later. -->
- <!-- precompress .html, .js, and .css files -->
- <!--<inherits name="com.google.gwt.precompress.Precompress"/>-->
-
<inherits name='ca.nanometrics.gflot.GFlot'/>
@@ -66,7 +61,6 @@
ie9: IE9 (new support for IE9 with GWT 2.3.0+)
gecko1_8: FF2 and later
safari: Safari/Chrome
- opera: Opera
*NOTE*: Since we specify the meta "X-UA-Compatible: IE=IE8" HTTP header in CoreGUI.html, IE9 and later
will emulate IE8 (although the gwt IE9 js libs will still get loaded).
commit 963a082f73dd9cc4656998029bac99317b648424
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Tue Aug 21 15:21:55 2012 +0200
[BZ 818083 - [IE 8.0] GUI components not aligned properly on monitoring tab] Added invisible form item on the right side
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java
index 8bad3dd..9b39faa 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java
@@ -24,10 +24,12 @@ import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
+import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.widgets.form.fields.ButtonItem;
import com.smartgwt.client.widgets.form.fields.CheckboxItem;
import com.smartgwt.client.widgets.form.fields.DateTimeItem;
import com.smartgwt.client.widgets.form.fields.SelectItem;
+import com.smartgwt.client.widgets.form.fields.SpacerItem;
import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
@@ -62,6 +64,7 @@ public abstract class AbstractMeasurementRangeEditor extends LocatableDynamicFor
private boolean displayEnableButton = false;
private boolean displayRangeItemGrouping = false;
protected CheckboxItem enableRangeItem;
+ private SpacerItem space;
private ButtonItem setButton;
public static String ENABLE_RANGE_ITEM = "ENABLE_RANGE_ITEM";
@@ -83,8 +86,9 @@ public abstract class AbstractMeasurementRangeEditor extends LocatableDynamicFor
public AbstractMeasurementRangeEditor(String locatorId) {
super(locatorId);
- setNumCols(12);
+ setNumCols(10);
setWrapItemTitles(false);
+ setAlign(Alignment.LEFT);
}
/**
@@ -106,7 +110,6 @@ public abstract class AbstractMeasurementRangeEditor extends LocatableDynamicFor
setGroupTitle("Filter by: Time");
}
enableRangeItem = new CheckboxItem(ENABLE_RANGE_ITEM, "");
- enableRangeItem.setStartRow(true);
enableRangeItem.setShowTitle(false);
enableRangeItem.setShowLabel(false);
enableRangeItem.addChangeHandler(new ChangeHandler() {
@@ -119,35 +122,24 @@ public abstract class AbstractMeasurementRangeEditor extends LocatableDynamicFor
//combobox of last items
simpleLastValuesItem = new SelectItem(SIMPLE_VALUE_ITEM, MSG.view_measureRange_last());
- simpleLastValuesItem.setStartRow(false);
- simpleLastValuesItem.setEndRow(false);
simpleLastValuesItem.setValueMap(lastValues);
- simpleLastValuesItem.setWidth("*");
- simpleLastValuesItem.setRedrawOnChange(true);
+ simpleLastValuesItem.setTitleAlign(Alignment.LEFT);
//combobox of units of time
simpleLastUnitsItem = new SelectItem(SIMPLE_UNIT_ITEM);
- simpleLastUnitsItem.setStartRow(false);
- simpleLastUnitsItem.setEndRow(false);
simpleLastUnitsItem.setValueMap(lastUnits);
simpleLastUnitsItem.setShowTitle(false);
- simpleLastUnitsItem.setWidth("*");
- simpleLastUnitsItem.setRedrawOnChange(true);
//time range start from
advancedStartItem = new DateTimeItem(ADVANCED_START_ITEM, MSG.view_measureRange_start());
- advancedStartItem.setStartRow(false);
- advancedStartItem.setEndRow(false);
+ advancedStartItem.setTitleAlign(Alignment.LEFT);
//time range end
advancedEndItem = new DateTimeItem(ADVANCED_END_ITEM, MSG.common_title_end());
- advancedEndItem.setStartRow(false);
- advancedEndItem.setEndRow(false);
setButton = new ButtonItem(SET_ITEM, MSG.common_button_set());
setButton.setStartRow(false);
setButton.setEndRow(false);
- setButton.setShowTitle(false);
setButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
@@ -167,30 +159,31 @@ public abstract class AbstractMeasurementRangeEditor extends LocatableDynamicFor
advancedSimpleButton = new ButtonItem(ADVANCED_BUTTON_ITEM, MSG.common_button_advanced());
advancedSimpleButton.setStartRow(false);
advancedSimpleButton.setEndRow(false);
- advancedSimpleButton.setShowTitle(false);
advancedSimpleButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent clickEvent) {
advanced = !advanced;
update();
}
});
+
+ space = new SpacerItem();
+ space.setWidth(300);
MetricRangePreferences metricRangePrefs = getMetricRangePreferences();
if (metricRangePrefs != null) {
advanced = (metricRangePrefs.explicitBeginEnd);
}
-
+
if (displaySetButton) {
setItems(simpleLastValuesItem, simpleLastUnitsItem, advancedStartItem, advancedEndItem, setButton,
- advancedSimpleButton);
+ advancedSimpleButton, space);
} else {//not displaying Set button
if (displayEnableButton) {
setItems(enableRangeItem, simpleLastValuesItem, simpleLastUnitsItem, advancedStartItem,
- advancedEndItem, advancedSimpleButton);
- setNumCols(9);//extend to encompass expanded
+ advancedEndItem, advancedSimpleButton, space);
} else {
setItems(simpleLastValuesItem, simpleLastUnitsItem, advancedStartItem, advancedEndItem,
- advancedSimpleButton);
+ advancedSimpleButton, space);
}
}
update();
commit 2f1ce1944b3307fa790225f91889fc642abfcc0e
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Aug 21 10:57:28 2012 +0200
[BZ 840662] - Python scripting is now bundled by default with RHQ.
It can be excluded by explicitely switching off the "bundle-additional-script-languages" profile.
E.g. mvn clean install -P '!bundle-additional-script-languages'
diff --git a/modules/enterprise/remoting/cli/pom.xml b/modules/enterprise/remoting/cli/pom.xml
index 3924ff0..e0e4243 100644
--- a/modules/enterprise/remoting/cli/pom.xml
+++ b/modules/enterprise/remoting/cli/pom.xml
@@ -34,6 +34,13 @@
</dependency>
<dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-scripting-javascript</artifactId>
+ <version>${project.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
<groupId>${project.groupId}</groupId>
<artifactId>rhq-core-domain</artifactId>
<version>${project.version}</version>
@@ -131,6 +138,7 @@
<property name="persistence-api.version" value="${persistence-api.version}" />
<property name="rhq.client.build.exclude.cli.jar" value="${rhq.client.build.exclude.cli.jar}" />
<property name="rhq.client.build.include.client.jar" value="${rhq.client.build.include.client.jar}" />
+ <property name="rhq.bundle-additional-script-languages" value="${rhq.bundle-additional-script-languages}"/>
</ant>
</target>
</configuration>
@@ -220,6 +228,25 @@
<profiles>
+ <!-- NOTE: this profile HAS TO have the same activation policy as the profile with the same name in the root pom.xml of RHQ -->
+ <profile>
+ <id>bundle-additional-script-languages</id>
+ <activation>
+ <property>
+ <name>java.home</name>
+ </property>
+ </activation>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-scripting-python</artifactId>
+ <version>${project.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+
<!-- Unlike most of RHQ, this module requires JDK6, so replace the Java 5 bootclasspath that was added to the compiler args by the root POM with a bootclasspath based on the java.home sysprop (which should be Java 6 or later if the enforcer plugin did its job). -->
<profile>
<id>check-java-api</id>
diff --git a/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml b/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
index 808bd82..715bd9b 100644
--- a/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
+++ b/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
@@ -70,6 +70,15 @@
<copy file="${settings.localRepository}/org/rhq/rhq-scripting-api/${project.version}/rhq-scripting-api-${project.version}.jar" tofile="${lib.home}/rhq-scripting-api-${project.version}.jar" verbose="true" />
<copy file="${settings.localRepository}/org/rhq/rhq-scripting-javascript/${project.version}/rhq-scripting-javascript-${project.version}.jar" tofile="${lib.home}/rhq-scripting-javascript-${project.version}.jar" verbose="true" />
+
+ <echo>*** Including additional script languages: ${rhq.bundle-additional-script-languages}</echo>
+ <!-- Copy all the additional script language support jars if we are told to do so -->
+ <copy todir="${lib.home}" verbose="true">
+ <fileset dir="${settings.localRepository}/org/rhq">
+ <include if="${rhq.bundle-additional-script-languages}" name="**/rhq-scripting-python-${project.version}.jar"/>
+ </fileset>
+ <mapper type="flatten" />
+ </copy>
</target>
<target name="prepare-samples-dir">
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index 38ead44..adbe85a 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -22,6 +22,8 @@
<groupId>org.mozilla</groupId>
<artifactId>rhino</artifactId>
<version>1.7R4</version>
+ <!-- we actually repackage Rhino inside our jar -->
+ <scope>provided</scope>
</dependency>
</dependencies>
diff --git a/modules/enterprise/scripting/pom.xml b/modules/enterprise/scripting/pom.xml
index c786cdc..f439f11 100644
--- a/modules/enterprise/scripting/pom.xml
+++ b/modules/enterprise/scripting/pom.xml
@@ -17,11 +17,12 @@
</modules>
<profiles>
+ <!-- NOTE: this profile HAS TO have the same activation policy as the profile with the same name in the root pom.xml of RHQ -->
<profile>
- <id>experimental</id>
+ <id>bundle-additional-script-languages</id>
<activation>
<property>
- <name>experimental-script-languages</name>
+ <name>java.home</name>
</property>
</activation>
diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
index 39d3895..4b34699 100644
--- a/modules/enterprise/scripting/python/pom.xml
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -21,6 +21,8 @@
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.5.2</version>
+ <!-- we actually repackage jython inside our jar -->
+ <scope>provided</scope>
</dependency>
</dependencies>
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index 10b613e..0bed079 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -447,6 +447,26 @@
<profiles>
+ <!-- NOTE: this profile HAS TO have the same activation policy as the profile with the same name in the root pom.xml of RHQ -->
+ <profile>
+ <id>bundle-additional-script-languages</id>
+ <activation>
+ <property>
+ <!-- we want this always active but activeByDefault doesn't work -->
+ <!-- see http://maven.apache.org/guides/introduction/introduction-to-profiles.html -->
+ <name>java.home</name>
+ </property>
+ </activation>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-scripting-python</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </profile>
+
<profile>
<id>bundle-plugins</id>
<activation>
diff --git a/pom.xml b/pom.xml
index 36b9c62..f6bd80d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1171,6 +1171,25 @@
<profiles>
+ <!-- NOTE: This profile is extended upon in several other submodules.
+ If you need to change its activation policy, make sure to do that in
+ *ALL* the modules that define this profile. -->
+ <profile>
+ <id>bundle-additional-script-languages</id>
+ <activation>
+ <property>
+ <!-- we want this always active but activeByDefault doesn't work -->
+ <!-- see http://maven.apache.org/guides/introduction/introduction-to-profiles.html -->
+ <name>java.home</name>
+ </property>
+ </activation>
+
+ <!-- Can be used to pass a flag down to deployment composing ANT scripts and somesuch -->
+ <properties>
+ <rhq.bundle-additional-script-languages>true</rhq.bundle-additional-script-languages>
+ </properties>
+ </profile>
+
<profile>
<id>ojdbc-driver</id>
<activation>
commit 851461ab89dac1da41b9c85ae1d87eac54de2ef3
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon Aug 20 14:42:06 2012 -0500
[BZ 830841] Added a descriptive error message for cases where content is not available for a resource. The user is asked to try again in a few minutes if content was deployed recently since the deploy and discovery process might still be running.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
index 0199c77..7361fe8 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
@@ -576,19 +576,25 @@ public class ResourceClientProxy {
InstalledPackage installedPackage = getBackingContent();
- if (fileName == null )
- fileName = installedPackage.getPackageVersion().getFileName();
-
- File file = new File(fileName);
+ if (installedPackage != null) {
+ if (fileName == null) {
+ fileName = installedPackage.getPackageVersion().getFileName();
+ }
- byte[] data = remoteClient.getProxy(ContentManagerRemote.class).getPackageBytes(
- remoteClient.getSubject(), resourceClientProxy.resourceId, installedPackage.getId());
+ File file = new File(fileName);
- FileOutputStream fos = new FileOutputStream(file);
- try {
- fos.write(data);
- } finally {
- fos.close();
+ byte[] data = remoteClient.getProxy(ContentManagerRemote.class).getPackageBytes(
+ remoteClient.getSubject(), resourceClientProxy.resourceId, installedPackage.getId());
+
+ FileOutputStream fos = new FileOutputStream(file);
+ try {
+ fos.write(data);
+ } finally {
+ fos.close();
+ }
+ } else {
+ throw new RuntimeException(
+ "Content not available in the content repository. If you recently deployed content to this resource, then the content repository has not yet received the content or content information. The content for a resource is available only after the deployment and discovery process completes. Please try again in a few minutes.");
}
}
commit 414ccdf3fd964dc6d64abe511ec02f4e9170aa40
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Aug 20 14:59:13 2012 -0400
[Bug 849751 - RFE: protect resource tree from direct navigation to a resource with many siblings]
Apply the new ResourceManager.findResourcesByCriteriaBounded() method
to getResourceLineageAndSiblings() in order to similarly bound the initial
tree building fetch. Currently getResourceLineageAndSiblings() will use
the defaults applied to findResourcesByCriteriaBounded(), although we may
find that providing separate overrides will be useful.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
index 0fe906a..a016f8e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
@@ -113,6 +113,7 @@ import org.rhq.core.domain.resource.group.composite.AutoGroupComposite;
import org.rhq.core.domain.server.PersistenceUtility;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
import org.rhq.core.util.IntExtractor;
import org.rhq.core.util.collection.ArrayUtils;
import org.rhq.enterprise.server.RHQConstants;
@@ -796,14 +797,16 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage
// If the ancestor is not locked, include viewable children.
if (!ancestor.isLocked() || ancestor.getResource() == parent) {
- // Get all viewable committed children.
- PageList<Resource> children = findChildResourcesByCategoryAndInventoryStatus(subject,
- ancestor.getResource(), null, InventoryStatus.COMMITTED, PageControl.getUnlimitedInstance());
+ // Get viewable committed children, but bounded to ensure it's not an overwhelming return set
+ ResourceCriteria criteria = new ResourceCriteria();
+ criteria.addFilterParentResourceId(ancestor.getResource().getId());
+ criteria.addSortName(PageOrdering.ASC);
+ List<Resource> children = findResourcesByCriteriaBounded(subject, criteria, 0, 0);
// Remove any that are in the lineage to avoid repeated handling.
children.removeAll(rawResourceLineage);
for (Resource child : children) {
- // Ensure the parentResource field is fetched.
- //noinspection ConstantConditions
+ // Ensure the parentResource field is fetched. (do this here and not via criteria.fetchParentResource
+ // because that option would require inventory manager perm)
child.getParentResource().getId();
// The query only returned viewable children, so the composite should not be locked.
boolean isLocked = false;
commit 722b5c83eac64fd145863a154147f9bb0e1cf67a
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Aug 20 14:24:29 2012 -0400
trivial - fix some DriftManager logging
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java
index 0924288..8b54320 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java
@@ -479,7 +479,7 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
@Override
public void updateDriftDetection(int resourceId, DriftDefinition driftDefinition) {
- log.info("Recived request to update schedule for " + toString(resourceId, driftDefinition));
+ log.info("Received request to update schedule for " + toString(resourceId, driftDefinition));
DriftDetectionSchedule updatedSchedule = schedulesQueue.update(resourceId, driftDefinition);
if (updatedSchedule == null) {
@@ -696,7 +696,7 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
case pluginConfiguration: {
baseLocation = resource.getPluginConfiguration().getSimpleValue(baseDirValueName, null);
if (baseLocation == null) {
- throw new IllegalArgumentException("Cannot determine the bundle base deployment location - "
+ throw new IllegalArgumentException("Cannot determine the base directory - "
+ "there is no plugin configuration setting for [" + baseDirValueName + "]");
}
break;
@@ -704,7 +704,7 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
case resourceConfiguration: {
baseLocation = resource.getResourceConfiguration().getSimpleValue(baseDirValueName, null);
if (baseLocation == null) {
- throw new IllegalArgumentException("Cannot determine the bundle base deployment location - "
+ throw new IllegalArgumentException("Cannot determine the base directory - "
+ "there is no resource configuration setting for [" + baseDirValueName + "]");
}
break;
commit 155c66f5fa5ac816de6ce8693875cc746f80096d
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Aug 20 09:31:13 2012 -0700
[BZ 848529 - Creating a domain deployment spins and never uploads the WAR on IE8]. IE8 had issues registering the listener when the upload was complete. This was a regression caused by smartgwt3.0 upgrade.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/DynamicCallbackFormImplIE8.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/DynamicCallbackFormImplIE8.java
new file mode 100644
index 0000000..89c1615
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/DynamicCallbackFormImplIE8.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.rhq.enterprise.gui.coregui.client.components.upload;
+
+import com.google.gwt.dom.client.Element;
+
+/**
+ * Implementation class used by {@link com.google.gwt.user.client.ui.FormPanel}.
+ */
+public class DynamicCallbackFormImplIE8 extends DynamicCallbackFormImpl {
+
+ @Override
+ public native void hookEvents(Element iframe,
+ DynamicCallbackFormImplHost listener) /*-{
+ if (iframe) {
+ iframe.onreadystatechange = function() {
+ // If there is no __formAction yet, this is a spurious onreadystatechange
+ // generated when the iframe is first added to the DOM.
+ if (!iframe.__formAction)
+ return;
+
+ if (iframe.readyState == 'complete') {
+ // If the iframe's contentWindow has not navigated to the expected action
+ // url, then it must be an error, so we ignore it.
+ listener.@org.rhq.enterprise.gui.coregui.client.components.upload.DynamicCallbackFormImplHost::onFrameLoad()();
+ }
+ };
+ }
+ }-*/;
+
+ @Override
+ public native void unhookEvents(Element iframe) /*-{
+ if (iframe)
+ iframe.onreadystatechange = null;
+ }-*/;
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index 78db5af..c5c4391 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -39,6 +39,12 @@
<when-type-is class="org.rhq.enterprise.gui.coregui.client.components.upload.DynamicCallbackFormImpl"/>
</replace-with>
+ <!-- Special case for IE8 where upload onsubmit handlers need special registration code from other browsers -->
+ <replace-with class="org.rhq.enterprise.gui.coregui.client.components.upload.DynamicCallbackFormImplIE8">
+ <when-type-is class="org.rhq.enterprise.gui.coregui.client.components.upload.DynamicCallbackFormImpl"/>
+ <when-property-is name="user.agent" value="ie8"/>
+ </replace-with>
+
<generate-with class="org.rhq.enterprise.gui.coregui.user.rebind.rpc.TrackingServiceInterfaceProxyGenerator">
<when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService"/>
commit dc966bdbe0ef18915cba3a1cdd69c4167f5bd4c1
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri Aug 10 15:29:53 2012 -0700
Removed unused methods from ImageManager.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
index e50fe14..a15857e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
@@ -403,9 +403,6 @@ public class ImageManager {
return "subsystems/availability/availability_yellow_16.png";
}
- public static String getAvailabilityYellowLargeIcon() {
- return "subsystems/availability/availability_yellow_24.png";
- }
public static String getAvailBarImagePath(AvailabilityType availType) {
@@ -437,13 +434,6 @@ public class ImageManager {
return "subsystems/alert/Flag_blue_16.png";
}
- public static String getAlertLargeIcon() {
- return "subsystems/alert/Flag_blue_24.png";
- }
-
- public static String getAlertEditIcon() {
- return "subsystems/alert/Edit_Alert.png";
- }
public static String getMetricEditIcon() {
return "subsystems/monitor/Edit_Metric.png";
@@ -551,9 +541,6 @@ public class ImageManager {
return "subsystems/event/" + severity.name() + "_16.png";
}
- public static String getEventLargeIcon() {
- return "subsystems/event/Events_24.png";
- }
public static String getEventIcon() {
return "subsystems/event/Events_16.png";
@@ -563,45 +550,25 @@ public class ImageManager {
return "subsystems/monitor/Monitor_16.png";
}
- public static String getMonitorLargeIcon() {
- return "subsystems/monitor/Monitor_24.png";
- }
public static String getMonitorFailedIcon() {
return "subsystems/monitor/Monitor_failed_16.png";
}
- public static String getMonitorFailedLargeIcon() {
- return "subsystems/monitor/Monitor_failed_24.png";
- }
-
- public static String getOperationLargeIcon() {
- return "subsystems/control/Operation_24.png";
- }
-
public static String getOperationIcon() {
return "subsystems/control/Operation_16.png";
}
- public static String getActivityPackageLargeIcon() {
- return "subsystems/content/Package_24.png";
- }
public static String getActivityPackageIcon() {
return "subsystems/content/Package_16.png";
}
- public static String getBundleLargeIcon() {
- return "subsystems/content/Content_24.png";
- }
public static String getBundleIcon() {
return "subsystems/content/Content_16.png";
}
- public static String getConfigureLargeIcon() {
- return "subsystems/configure/Configure_24.png";
- }
public static String getConfigureIcon() {
return "subsystems/configure/Configure_16.png";
commit 8732f82745b97897372ce0d00a9b3ac0773fedea
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Aug 20 11:46:10 2012 -0400
Add unit test for new ResourceManager.findResourcesByCriteriaBounded().
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/LargeGroupCriteriaTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/LargeGroupCriteriaTest.java
index 93bb887..323cf5c 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/LargeGroupCriteriaTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/LargeGroupCriteriaTest.java
@@ -21,17 +21,21 @@ 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;
@@ -189,6 +193,57 @@ public class LargeGroupCriteriaTest extends LargeGroupTestBase {
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();
commit 8cd529eb7b04e785ded5c7a3fb6e633e6bc90cc4
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Aug 20 10:25:47 2012 -0400
Reformat only!
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java
index f0fe5b7..deac357 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java
@@ -113,102 +113,89 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase {
assert errors.size() == 0;
}
-
public void testResourceLineage() throws Exception {
- // given a resource id for the leaf resource in a resource hierarchy
- int leafResourceId = givenASampleResourceHierarchy();
+ // given a resource id for the leaf resource in a resource hierarchy
+ int leafResourceId = givenASampleResourceHierarchy();
- // when
- List<Resource> resourceLineage = resourceManager.getResourceLineage(leafResourceId);
+ // 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());
+
+ // 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--) {
+ 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, "",
+ 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 {
+ 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);
+ } 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 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();
@@ -257,7 +244,7 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase {
resourceManager.uninventoryResourceAsyncWork(superuser, deletedResourceId);
}
em.flush();
-
+
ResourceType type = em.find(ResourceType.class, resource.getResourceType().getId());
System.out.println("Removing " + type + "...");
em.remove(type);
commit 5d472dceb665ec2e4b8b8c528c59c8c8b354d40d
Author: John Sanda <jsanda(a)redhat.com>
Date: Mon Aug 20 11:39:51 2012 -0400
[BZ 848893] Only hide empty groups for availability queries/searches
This regression was introduced during the work for BZ 826493. While
testing the changes for this commit, I came across another, related
issue where an empty compatible group does not show up in the compatible
groups view. It does however show up in the mixed groups view. An empty
mixed group appears in the mixed group view. This issue is already
logged under BZ 708929.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
index e269475..a799311 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
@@ -50,7 +50,6 @@ import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
@@ -125,12 +124,16 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
processResponse(request.getRequestId(), response);
}
- private PageList<ResourceGroupComposite> filterEmptyMemberGroups(PageList<ResourceGroupComposite> result){
+ private PageList<ResourceGroupComposite> applyAvailabilitySearchFilter(
+ PageList<ResourceGroupComposite> result){
+ if (!isAvailabilitySearch(criteria)) {
+ return result;
+ }
PageList<ResourceGroupComposite> pageList = new PageList<ResourceGroupComposite>(result.getPageControl());
for (ResourceGroupComposite rgc : result) {
- if (rgc.getExplicitCount() > 0 ){
+ if (rgc.getExplicitCount() > 0) {
pageList.add(rgc);
}
}
@@ -139,7 +142,7 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
}
public void onSuccess(PageList<ResourceGroupComposite> result) {
- PageList<ResourceGroupComposite> filteredResult = filterEmptyMemberGroups(result);
+ PageList<ResourceGroupComposite> filteredResult = applyAvailabilitySearchFilter(result);
response.setData(buildRecords(filteredResult));
response.setTotalRows(filteredResult.getTotalSize()); // for paging to work we have to specify size of full result set
processResponse(request.getRequestId(), response);
@@ -147,6 +150,10 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
});
}
+ private boolean isAvailabilitySearch(ResourceGroupCriteria criteria) {
+ return criteria.getSearchExpression() != null && criteria.getSearchExpression().startsWith("availability");
+ }
+
@Override
protected ResourceGroupCriteria getFetchCriteria(final DSRequest request) {
ResourceGroupCriteria criteria = new ResourceGroupCriteria();
commit c62b143dd5f065b54caf6692d3c04929d8b4539f
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Fri Aug 17 14:30:35 2012 -0500
[BZ 841684] Add config option to the wrapper script.
diff --git a/modules/enterprise/agent/src/etc/rhq-agent-wrapper.sh b/modules/enterprise/agent/src/etc/rhq-agent-wrapper.sh
index 68d1856..f03c83a 100755
--- a/modules/enterprise/agent/src/etc/rhq-agent-wrapper.sh
+++ b/modules/enterprise/agent/src/etc/rhq-agent-wrapper.sh
@@ -246,6 +246,44 @@ case "$1" in
fi
;;
+'config')
+ prepare_pid_dir
+
+ if [ "$_RUNNING" = "1" ]; then
+ echo "Cannot run config - please stop the agent before running config"
+ echo $_STATUS
+ exit 0
+ fi
+
+ echo "Configure RHQ Agent..."
+
+ # Determine the command to execute when starting the agent
+ if [ -z "$RHQ_AGENT_START_COMMAND" ]; then
+ # Find out where the agent start script is located
+ _START_SCRIPT="${RHQ_AGENT_HOME}/bin/rhq-agent.sh"
+
+ if [ ! -f "$_START_SCRIPT" ]; then
+ echo "ERROR! Cannot find the RHQ Agent start script"
+ echo "Not found: $_START_SCRIPT"
+ exit 1
+ fi
+ debug_wrapper_msg "Start script found here: $_START_SCRIPT"
+
+ RHQ_AGENT_START_COMMAND="${_START_SCRIPT}"
+ fi
+
+ RHQ_AGENT_CMDLINE_OPTS="--cleanconfig --nostart --daemon --setup --advanced"
+ export RHQ_AGENT_CMDLINE_OPTS
+
+ # start the agent now!
+ if [ -n "$RHQ_AGENT_DEBUG" ] && [ "$RHQ_AGENT_DEBUG" != "false" ]; then
+ debug_wrapper_msg "Executing agent with command: ${RHQ_AGENT_START_COMMAND} ${RHQ_AGENT_CMDLINE_OPTS}"
+ fi
+
+ . $RHQ_AGENT_START_COMMAND
+
+ ;;
+
'stop')
prepare_pid_dir
@@ -326,7 +364,7 @@ case "$1" in
exit $?
;;
*)
- echo "Usage: $0 { start | stop | kill | restart | status }"
+ echo "Usage: $0 { start | stop | kill | restart | status | config }"
exit 1
;;
esac
commit 30c5e81759f5166873e49fd3486614c282203f47
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Fri Aug 17 19:20:48 2012 +0200
[BZ 834353] - Distinguish between BRMS 5.(1|2).0 and EWP 5.1.x by looking
for BRMS specific jars in the client directory.
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstallationInfo.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstallationInfo.java
index cae73f3..a45237d 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstallationInfo.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstallationInfo.java
@@ -23,6 +23,7 @@
package org.rhq.plugins.jbossas5.helper;
import java.io.File;
+import java.io.FilenameFilter;
import java.io.IOException;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
@@ -43,11 +44,11 @@ public class JBossInstallationInfo {
private static final String EPP_IMPL_VERSION_PREFIX = "JBoss-EPP";
private static final ComparableVersion VERSION_4_2 = new ComparableVersion("4.2");
- private final JBossProductType productType;
- private final String version;
- private final String defaultBindAddress;
- private final boolean isEap;
- private final String majorVersion;
+ private JBossProductType productType;
+ private String version;
+ private String defaultBindAddress;
+ private boolean isEap;
+ private String majorVersion;
public JBossInstallationInfo(File installationDir) throws IOException {
File binDir = new File(installationDir, "bin");
@@ -63,11 +64,47 @@ public class JBossInstallationInfo {
if (-1 == majorVersionIndex) {
throw new RuntimeException("Unexpected run.jar implementation version, can't parse: " + this.version);
}
+
+ fixProductTypeAndVersion(jarManifestAttributes, installationDir);
+
this.defaultBindAddress = getDefaultServerName(this.version);
this.isEap = determineEap(jarManifestAttributes);
this.majorVersion = version.substring(0, version.indexOf('.'));
}
+ /**
+ * Tries to make sense of the mess of JBoss product versioning.
+ *
+ * @param jarManifestAttributes
+ * @param installationDir
+ */
+ private void fixProductTypeAndVersion(Attributes jarManifestAttributes, File installationDir) {
+ //the main mess is with BRMS < 5.3.0 being advertised as EWP
+ if (productType == JBossProductType.EWP && version.startsWith("5.1")) {
+ //this still can be a BRMS server... We can check that by looking for drools jars
+ //in the client. Brittle you say? Yes, of course ;)
+ File client = new File(installationDir, "client");
+ if (client.exists() && client.isDirectory()) {
+ boolean containsBrmsJars = false;
+
+ for(String file : client.list()) {
+ if (file.endsWith("BRMS.jar")) {
+ containsBrmsJars = true;
+ break;
+ }
+ }
+
+ if (containsBrmsJars) {
+ productType = JBossProductType.BRMS;
+ if ("5.1.1".equals(version)) {
+ //BRMS 5.2.0 is based on EWP 5.1.1
+ version = "5.2.0";
+ }
+ }
+ }
+ }
+ }
+
public JBossProductType getProductType() {
return this.productType;
}
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java
index de5d837..312ea80 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java
@@ -54,7 +54,12 @@ public enum JBossProductType {
/**
* Determines the product type (AS, EAP, EWP, or SOA) based on the Implementation-Title MANIFEST.MF attribute.
- *
+ * <p>
+ * Note that this method is <b>NOT</b> always correct about the actual version of the product, because
+ * certain version of certain products don't advertise the correct product/version in the manifest.
+ * <p>
+ * Use {@link JBossInstallationInfo} for a more thorough detection of the type and version of a product.
+ *
* @param attributes the attributes from a manifest file (typically run.jar or jboss-j2ee.jar)
*
* @return the product type (AS, EAP, EWP, or SOA)
commit 32ad4e17b0f75fcccb84107e01956a519175670f
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Fri Aug 17 09:09:04 2012 -0500
[BZ 848800] Adding back old constructor signature for backwards compatibility reasons. Marked the old constructor as deprecated.
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java
index af18723..c5e85bb 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java
@@ -59,6 +59,19 @@ public class CreateChildResourceFacetDelegate implements CreateChildResourceFace
this.parentResourceContext = parentResourceContext;
}
+ /**
+ * @deprecated This constructor is deprecated because it does not handle properly the SHA256 computation for
+ * exploded content. If used, this constructor will lead to a calculation of the SHA256 for exploded content
+ * based on exploded files. This method of computation is not preferred due to changes in content archive
+ * matching. Replaced by (@link {@link #CreateChildResourceFacetDelegate(ProfileServiceComponent, ResourceContext)}
+ *
+ * @param component component
+ */
+ @Deprecated
+ public CreateChildResourceFacetDelegate(ProfileServiceComponent component) {
+ this.component = component;
+ }
+
public CreateResourceReport createResource(CreateResourceReport createResourceReport) {
// ProfileServiceFactory.refreshCurrentProfileView();
ResourceType resourceType = createResourceReport.getResourceType();
commit f0f52f180b65682996586b4a0438a1865cae8381
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Aug 16 16:06:57 2012 -0400
Adding perftest scenario support to help test bug 784571
diff --git a/modules/plugins/perftest/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/perftest/src/main/resources/META-INF/rhq-plugin.xml
index 72fae98..7a34f7e 100644
--- a/modules/plugins/perftest/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/perftest/src/main/resources/META-INF/rhq-plugin.xml
@@ -114,6 +114,14 @@
</resource-configuration>
</service>
+ <service name="service-gamma" class="PerfTestComponent" discovery="PerfTestDiscoveryComponent" description="Omega Service Gamma">
+ <plugin-configuration>
+ <c:simple-property name="gamma-property0"/>
+ </plugin-configuration>
+
+ <metric displayName="Gamma Metric 0" property="gamma-metric0" defaultOn="false"/>
+ </service>
+
</server>
<!-- try to make server-a and its children representative of "average" resources -->
diff --git a/modules/plugins/perftest/src/main/resources/configurable-7.xml b/modules/plugins/perftest/src/main/resources/configurable-7.xml
new file mode 100644
index 0000000..8c6051f
--- /dev/null
+++ b/modules/plugins/perftest/src/main/resources/configurable-7.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+
+<scenario xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:jboss.org:rhq-perftest">
+
+ <!--
+ Sets up "omega servers" that have three kinds of child services, "alpha", "beta" and "gamma".
+
+ This is currently for simple services, not all of the service featured are exposed, only numeric metrics.
+
+ Example:
+
+ -Drhq.perftest.scenario=configurable-7
+ -Drhq.perftest.server-omega-count=10
+ -Drhq.perftest.service-alpha-count=25
+ -Drhq.perftest.service-beta-count=2
+ -Drhq.perftest.service-gamma-count=10
+ -->
+
+ <resource type="server-omega">
+ <simpleResourceGenerator property="rhq.perftest.server-omega-count"/>
+ <simpleNumericMeasurementGenerator/>
+ </resource>
+
+ <resource type="service-alpha">
+ <simpleResourceGenerator property="rhq.perftest.service-alpha-count"/>
+ <simpleNumericMeasurementGenerator/>
+ </resource>
+
+ <resource type="service-beta">
+ <simpleResourceGenerator property="rhq.perftest.service-beta-count"/>
+ <simpleNumericMeasurementGenerator/>
+ </resource>
+
+ <resource type="service-gamma">
+ <simpleResourceGenerator property="rhq.perftest.service-gamma-count"/>
+ <simpleNumericMeasurementGenerator/>
+ </resource>
+
+</scenario>
commit 1ace95e35c4684847526df65f46e8ae4c559b92e
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu Aug 16 16:03:47 2012 -0400
BZ 844217 - do not "hardcode" the deployment directory at discovery time, but make it a trait so that changes the user is making will be relected.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
index 6eb19f6..573742e 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
@@ -18,7 +18,9 @@
*/
package org.rhq.modules.plugins.jbossas7;
+import java.io.File;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
@@ -27,6 +29,7 @@ import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.Property;
import org.rhq.core.domain.configuration.PropertyList;
import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.measurement.MeasurementDataTrait;
import org.rhq.core.domain.measurement.MeasurementReport;
import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
@@ -37,6 +40,7 @@ import org.rhq.core.pluginapi.operation.OperationResult;
import org.rhq.modules.plugins.jbossas7.json.Address;
import org.rhq.modules.plugins.jbossas7.json.Operation;
import org.rhq.modules.plugins.jbossas7.json.ReadAttribute;
+import org.rhq.modules.plugins.jbossas7.json.ReadResource;
import org.rhq.modules.plugins.jbossas7.json.Result;
/**
@@ -65,6 +69,8 @@ public class StandaloneASComponent<T extends ResourceComponent<?>> extends BaseS
collectConfigTrait(report, request);
} else if (requestName.equals("multicastAddress")) {
collectMulticastAddressTrait(report, request);
+ } else if (requestName.equals("deployDir")) {
+ resolveDeployDir(report,request);
} else {
leftovers.add(request); // handled below
}
@@ -73,6 +79,62 @@ public class StandaloneASComponent<T extends ResourceComponent<?>> extends BaseS
super.getValues(report, leftovers);
}
+ /**
+ * Try to determine the deployment directory (usually $as/standalone/deployments ).
+ * For JDG we return fake data, as JDG does not have such a directory.
+ * @param report Measurement report to tack the value on
+ * @param request Measurement request with the schedule id to use
+ */
+ private void resolveDeployDir(MeasurementReport report, MeasurementScheduleRequest request) {
+
+ if ("JDG".equals(pluginConfiguration.getSimpleValue("productType","AS7"))) {
+ log.debug("This is a JDG server, so there is no deployDir");
+ MeasurementDataTrait trait = new MeasurementDataTrait(request,"- not applicable to JDG -");
+ report.addData(trait);
+ return;
+ }
+
+ // So we have an AS7/EAP6
+ Address scanner = new Address("subsystem=deployment-scanner,scanner=default");
+ ReadResource op = new ReadResource(scanner);
+ Result res = getASConnection().execute(op);
+ if (res.isSuccess()) {
+ Map<String,String> scannerMap = (Map<String, String>) res.getResult();
+ String path = scannerMap.get("path");
+ String relativeTo = scannerMap.get("relative-to");
+ File basePath = resolveRelativePath(relativeTo);
+
+ // It is safe to use File.separator, as the agent we are running in, will also lay down the plugins
+ String deployDir = new File(basePath, path).getAbsolutePath();
+
+ MeasurementDataTrait trait = new MeasurementDataTrait(request,deployDir);
+ report.addData(trait);
+ }
+ else {
+ log.error("No default deployment scanner was found, returning no value");
+ }
+ }
+
+ private File resolveRelativePath(String relativeTo) {
+
+ Address addr = new Address("path",relativeTo);
+ ReadResource op = new ReadResource(addr);
+ Result res = getASConnection().execute(op);
+ if (res.isSuccess()) {
+ Map<String,String> pathMap = (Map<String, String>) res.getResult();
+ String path = pathMap.get("path");
+ String relativeToProp = pathMap.get("relative-to");
+ if (relativeToProp==null)
+ return new File(path);
+ else {
+ File basePath = resolveRelativePath(relativeToProp);
+ return new File(basePath, path);
+ }
+ }
+ log.warn("The requested path property " + relativeTo + " is not registered in the server, so not resolving it.");
+ return new File(relativeTo);
+ }
+
@Override
protected Address getServerAddress() {
return getAddress();
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java
index 9d93300..efa814d 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java
@@ -84,13 +84,6 @@ public class StandaloneASDiscovery extends BaseProcessDiscovery {
DiscoveredResourceDetails resourceDetails = super.buildResourceDetails(discoveryContext, process, commandLine);
Configuration pluginConfig = resourceDetails.getPluginConfiguration();
- // Set deployment directory, which only exists for standalone servers
- String baseDir = pluginConfig.getSimpleValue("baseDir");
- if (baseDir != null) {
- File deployDir = new File(baseDir, "deployments");
- pluginConfig.put(new PropertySimple("deployDir", deployDir.getPath()));
- }
-
return resourceDetails;
}
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 638f542..8143d04 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
@@ -1164,7 +1164,6 @@
<c:simple-property name="baseDir" type="file" description="Base directory for server content" displayName="Base Directory" readOnly="true" required="false"/>
<c:simple-property name="configDir" type="file" description="Base configuration directory" displayName="Configuration Directory" readOnly="true" required="false"/>
<c:simple-property name="logDir" type="file" description="the directory where log files will be written for this server" displayName="Log Directory" readOnly="true" required="false"/>
- <c:simple-property name="deployDir" type="file" description="Deploy directory for standalone servers" displayName="Deployment directory" readOnly="true" required="false"/>
<c:simple-property name="productType" type="string" readOnly="true" required="false" description="Server product type (e.g. AS or EAP)"/>
&startScriptPluginConfigGroup;
@@ -1224,6 +1223,8 @@
<metric property="config-file" dataType="trait" displayName="Server Config File" displayType="summary" defaultInterval="3600000"
description="The name of the server configuration file this server is using"/>
+ <metric property="deployDir" dataType="trait" displayName="Deploy Directory" defaultInterval="600000" defaultOn="true"
+ description="The deployment directory for bundles (usually 'standalone/deployments'"/>
<event name="logEntry" description="an entry in a log file"/>
@@ -1321,14 +1322,14 @@
name="Template-Deploy Files"
description="Monitor standalone deployment dir for drift. ">
<basedir>
- <value-context>pluginConfiguration</value-context>
+ <value-context>measurementTrait</value-context>
<value-name>deployDir</value-name>
</basedir>
</drift-definition>
<bundle-target>
<destination-base-dir name="Deploy Directory" description="The deployment directory for a standalone server">
- <value-context>pluginConfiguration</value-context>
+ <value-context>measurementTrait</value-context>
<value-name>deployDir</value-name>
</destination-base-dir>
</bundle-target>
commit 2e9bce71d9e26e1a7034650a56f6d3118b20ebaa
Author: John Sanda <jsanda(a)redhat.com>
Date: Thu Aug 16 13:18:09 2012 -0400
[BZ 826604] fix parsing of quoted named args
This commit addresses the parsing problems of using quoted strings with
named arguments.
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index c7f6bbf..e068272 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@ -431,6 +431,7 @@ public class ClientMain {
boolean keep_going = true;
boolean isScriptFileCommand = false;
+ boolean isNamedArgs = false;
// we don't want to parse numbers and we want ' to be a normal word
// character
@@ -471,12 +472,39 @@ public class ClientMain {
isScriptFileCommand = true;
}
args.add(strtok.sval);
+ if (strtok.sval.equals("--args-style=named")) {
+ isNamedArgs = true;
+ }
} else if (nextToken == '\"' || nextToken == '\'') {
args.add(strtok.sval);
} else if ((nextToken == java.io.StreamTokenizer.TT_EOF) || (nextToken == java.io.StreamTokenizer.TT_EOL)) {
keep_going = false;
}
}
+
+ if (isNamedArgs) {
+ List<String> newArgs = new ArrayList<String>();
+ int namedArgsIndex = args.indexOf("--args-style=named");
+
+ for (int i = 0; i <= namedArgsIndex; ++i) {
+ newArgs.add(args.get(i));
+ }
+
+ String namedArg = null;
+ for (int i = namedArgsIndex + 1; i < args.size(); ++i) {
+ if (namedArg == null && args.get(i).endsWith("=")) {
+ namedArg = args.get(i);
+ } else if (namedArg != null) {
+ newArgs.add(args.get(i - 1) + args.get(i));
+ namedArg = null;
+ } else {
+ newArgs.add(args.get(i));
+ }
+ }
+
+ return newArgs.toArray(new String[newArgs.size()]);
+ }
+
return args.toArray(new String[args.size()]);
}
commit 30a6818e7ae101dc8df7edc198c5ee9ac790683e
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Aug 16 12:39:22 2012 -0400
[Bug 784571 - Resource tree not complete when more than 200 children]
We decided not to allow an unlimited number of child resources be returned
when expanding a node in the tree. But there are major problems with
simply limiting the children to 200. This is what we do today, and the
results are unordered. Meaning you can lose any number of resources of
any types and it is not possible to know what you are missing. And we don't
indicate that the tree is incomplete. If we add ordering (alphabetical by
resource name) you still lose any number of resources, but always the same
ones. In this way it is much easier to realize that you are missing
child resources (and/or entire child types) because the resources returned
obviously stop as some lexigraphical point.
Still, we don't want to allow an unbounded fetch in the GUI. The solution
here is to move the unbounded fetch to the server side and to introduce
SLSB support to prune the results and return the pruned child set. In this
way we can limit the max child resources while returning a much more
reasonable resource set.
The way it works is as follows: There are two variable in use:
maxResources
Will not return more than this number of resources. If the original fetch
exceeds maxResources then maxResourcesByType will be enforced. If, after
trimming by type, maxResources is still exceeded, then the tail
resources (assuming a sorted set) will be removed to enforce the limit.
If <=0 the default (currently set to 1000) will be used.
maxResourcesByType
If maxResources is exceeded by the initial result set then members of each
type will be trimmed down to meet this limit.
If <=0 the default (currently set to 200) will be used.
The defaults may change after this check-in based on testing results. The
GUI will not set these values in the fetch, so the defaults will be applied.
The default values can be overriden (and applied to all fetches/sessions) by
setting the following system properties (in rhq-server.properties and restarting):
rhq.server.findResourcesByCriteriaBounded.maxResources
rhq.server.findResourcesByCriteriaBounded.maxResourcesByType
So, this allows us to:
- Avoid an unbounded fetch.
- Have any distribution of child resources of various types as long as the
maxResources limit is not exceeded.
- Apply an even and understandable pruning when necessary.
It does not yet allow us to indicate in the tree which resource types have
been pruned. This will be a future enhancement and tracked as
https://bugzilla.redhat.com/show_bug.cgi?id=848853.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java
index 59d96c6..1cdc64c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java
@@ -70,6 +70,9 @@ public interface ResourceGWTService extends RemoteService {
PageList<Resource> findResourcesByCriteria(ResourceCriteria criteria) throws RuntimeException;
+ List<Resource> findResourcesByCriteriaBounded(ResourceCriteria criteria, int maxResources, int maxResourcesByType)
+ throws RuntimeException;
+
PageList<ResourceComposite> findResourceCompositesByCriteria(ResourceCriteria criteria) throws RuntimeException;
List<ResourceError> findResourceErrors(int resourceId) throws RuntimeException;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
index 5c58a70..b6a5f5f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
@@ -44,8 +44,7 @@ import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceSubCategory;
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.domain.util.PageOrdering;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.ViewChangedException;
@@ -159,12 +158,16 @@ public class ResourceTreeDatasource extends DataSource {
} else {
Log.debug("ResourceTreeDatasource: Loading Resource [" + parentResourceId + "]...");
+ // This fetch limits the number of resources that can be returned to protect against fetching a massive
+ // number of children for a parent. Doing so may cause an unacceptably slow tree rendering, too much vertical
+ // scroll, or perhaps even hang the gui if it consumed too many resources. To see all children the
+ // user will need to visit the Inventory->Children view for the resource.
ResourceCriteria criteria = new ResourceCriteria();
criteria.addFilterParentResourceId(Integer.parseInt(parentResourceId));
- // we don't need sorting since we get everything and the tree nodes are already sorted
- criteria.setPageControl(PageControl.getUnlimitedInstance());
+ // we must sort the results to ensure that if cropped we at least show the same results each time
+ criteria.addSortName(PageOrdering.ASC);
- resourceService.findResourcesByCriteria(criteria, new AsyncCallback<PageList<Resource>>() {
+ resourceService.findResourcesByCriteriaBounded(criteria, -1, -1, new AsyncCallback<List<Resource>>() {
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_loadFailed_children(), caught);
response.setStatus(RPCResponse.STATUS_FAILURE);
@@ -173,7 +176,7 @@ public class ResourceTreeDatasource extends DataSource {
loadingLabel.hide();
}
- public void onSuccess(PageList<Resource> result) {
+ public void onSuccess(List<Resource> result) {
processIncomingData(result, response, requestId);
}
});
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java
index 17ccd78..4ee821b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java
@@ -145,6 +145,20 @@ public class ResourceGWTServiceImpl extends AbstractGWTServiceImpl implements Re
}
}
+ public List<Resource> findResourcesByCriteriaBounded(ResourceCriteria criteria, int maxResources,
+ int maxResourcesByType) throws RuntimeException {
+ try {
+ List<Resource> result = resourceManager.findResourcesByCriteriaBounded(getSessionSubject(), criteria,
+ maxResources, maxResourcesByType);
+
+ ObjectFilter.filterFieldsInCollection(result, importantFieldsSet);
+
+ return SerialUtility.prepare(result, "ResourceService.findResourcesByCriteriaBounded");
+ } catch (Throwable t) {
+ throw getExceptionToThrowToClient(t);
+ }
+ }
+
public PageList<ResourceComposite> findResourceCompositesByCriteria(ResourceCriteria criteria)
throws RuntimeException {
try {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
index dce2e23..0fe906a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
@@ -24,6 +24,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
@@ -142,6 +143,9 @@ import org.rhq.enterprise.server.util.QueryUtility;
public class ResourceManagerBean implements ResourceManagerLocal, ResourceManagerRemote {
private final Log log = LogFactory.getLog(ResourceManagerBean.class);
+ private final static String BOUNDED_MAX_RESOURCES = "1000";
+ private final static String BOUNDED_MAX_RESOURCES_BY_TYPE = "200";
+
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
private EntityManager entityManager;
@@ -2472,6 +2476,70 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage
return results;
}
+ @Override
+ public List<Resource> findResourcesByCriteriaBounded(Subject subject, ResourceCriteria criteria, int maxResources,
+ int maxResourcesByType) {
+
+ // find all of the requested resources but don't return them until they meet our bounded return requirements
+ // maintain any requested sorting
+ criteria.clearPaging();
+
+ // perform the requested criteria query
+ PageList<Resource> results = findResourcesByCriteria(subject, criteria);
+
+ // If not specified use the default maxResources
+ if (maxResources <= 0) {
+ try {
+ maxResources = Integer.parseInt(System.getProperty(
+ "rhq.server.findResourcesByCriteriaBounded.maxResources", BOUNDED_MAX_RESOURCES));
+ } catch (NumberFormatException e) {
+ }
+ if (maxResources <= 0) {
+ maxResources = Integer.parseInt(BOUNDED_MAX_RESOURCES);
+ }
+ }
+
+ if (results.getTotalSize() <= maxResources) {
+ return results;
+ }
+
+ // If not specified use the default maxResourcesByType
+ if (maxResourcesByType <= 0) {
+ try {
+ maxResourcesByType = Integer.parseInt(System.getProperty(
+ "rhq.server.findResourcesByCriteriaBounded.maxResourcesByType", BOUNDED_MAX_RESOURCES_BY_TYPE));
+ } catch (NumberFormatException e) {
+ }
+ if (maxResourcesByType <= 0) {
+ maxResourcesByType = Integer.parseInt(BOUNDED_MAX_RESOURCES_BY_TYPE);
+ }
+ }
+
+ // We need to trim the returned resources, enforce maxResourcesByType
+ Map<Integer, Integer> typeCounts = new HashMap<Integer, Integer>();
+
+ for (Iterator<Resource> i = results.iterator(); i.hasNext();) {
+ Resource r = i.next();
+ Integer typeId = r.getResourceType().getId();
+ Integer count = typeCounts.get(typeId);
+ if (null == count) {
+ count = 0;
+ }
+ typeCounts.put(typeId, ++count);
+ if (count > maxResourcesByType) {
+ i.remove();
+ }
+ }
+
+ // If after we've trimmed all types the results are still more than maxSize then we need to just chop
+ // keeping the most important (presumably the beginning of the list, if it's sorted)
+ while (maxResources < results.size()) {
+ results.remove(maxResources);
+ }
+
+ return results;
+ }
+
public Resource getPlaformOfResource(Subject subject, int resourceId) {
Resource resource = null;
Resource parent = null;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java
index fc075be..f555116 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java
@@ -446,6 +446,24 @@ public interface ResourceManagerLocal {
*/
public void updateAncestry(Subject subject, int resourceId);
+ /**
+ * This method exists to support the GUI resource tree, by not returning an unlimited number of resources
+ * but instead bounding the returned size. Note, this routine does not offer paging and any PageControl set in
+ * the Criteria is ignored. This is for use when paging is not required or possible, such as in a tree.
+ *
+ * @param subject
+ * @param criteria
+ * @param maxResources Will not return more than this number of resources. If the original fetch exceeds maxResources
+ * then maxResourcesByType will be enforced. If, after trimming by type, maxResources is still exceeded, then the least
+ * significant resources (the tail, assuming a sorted set) will be removed to enforce the limit. If <=0 the default
+ * will be used.
+ * @param maxResourcesByType If maxResources is exceeded by the initial result set then members of each type will be
+ * trimmed down to meet this limit. If <=0 the default will be used.
+ * @return The resulting resources, trimmed if necessary to meet the specify sizing bounds.
+ */
+ List<Resource> findResourcesByCriteriaBounded(Subject subject, ResourceCriteria criteria, int maxResources,
+ int maxResourcesByType);
+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// The following are shared with the Remote Interface
commit 10ad78d37ed54185afee537929c7411f0f40b694
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Thu Aug 16 11:03:47 2012 -0500
[BZ 824818] Removing required from keepalive-time because the validation rules on AS7 are too complex and not consistent with the resource definition.
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 a1eb285..638f542 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
@@ -2516,16 +2516,15 @@
</plugin-configuration>
<metric property="current-thread-count" description="The current number of threads in the pool."/>
- <metric property="keepalive-time:time" description="The time"/>
<metric property="largest-thread-count" description="The largest number of threads that have ever simultaneously been in the pool."/>
<metric property="rejected-count" description="The number of tasks that have been passed to the handoff-executor (if one is specified) or discarded."/>
<resource-configuration>
<c:simple-property name="allow-core-timeout" required="false" type="boolean" readOnly="true" defaultValue="false" displayName="Allow Core Timeout" description="Whether core threads may time out. The default value is false."/>
<c:simple-property name="core-threads:expr" required="false" type="integer" readOnly="true" displayName="Core Threads" description="The core thread pool size which is smaller than the maximum pool size. If undefined, the core thread pool size is the same as the maximum thread pool size."/>
- <c:map-property name="keepalive-time" required="true" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="true" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="true" description="The time unit"/>
+ <c:map-property name="keepalive-time" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
+ <c:simple-property name="time" type="long" readOnly="true" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="true" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="integer" readOnly="true" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" displayName="Name" description="The name of the thread pool."/>
@@ -2544,16 +2543,15 @@
</plugin-configuration>
<metric property="current-thread-count" description="The current number of threads in the pool."/>
- <metric property="keepalive-time:time" description="The time"/>
<metric property="largest-thread-count" description="The largest number of threads that have ever simultaneously been in the pool."/>
<metric property="rejected-count" description="The number of tasks that have been passed to the handoff-executor (if one is specified) or discarded."/>
<resource-configuration>
<c:simple-property name="allow-core-timeout" required="false" type="boolean" readOnly="true" defaultValue="false" displayName="Allow Core Timeout" description="Whether core threads may time out. The default value is false."/>
<c:simple-property name="core-threads:expr" required="false" type="integer" readOnly="true" displayName="Core Threads" description="The core thread pool size which is smaller than the maximum pool size. If undefined, the core thread pool size is the same as the maximum thread pool size."/>
- <c:map-property name="keepalive-time" required="true" readOnly="true" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="true" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="true" description="The time unit"/>
+ <c:map-property name="keepalive-time" readOnly="true" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
+ <c:simple-property name="time" type="long" readOnly="true" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="true" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="integer" readOnly="true" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" displayName="Name" description="The name of the thread pool."/>
@@ -2856,15 +2854,14 @@
<metric property="active-count" description="The approximate number of threads that are actively executing tasks."/>
<metric property="completed-task-count" description="The approximate total number of tasks that have completed execution."/>
<metric property="current-thread-count" description="The current number of threads in the pool."/>
- <metric property="keepalive-time:time" description="The time"/>
<metric property="largest-thread-count" description="The largest number of threads that have ever simultaneously been in the pool."/>
<metric property="rejected-count" description="The number of tasks that have been rejected."/>
<metric property="task-count" description="The approximate total number of tasks that have ever been scheduled for execution."/>
<resource-configuration>
<c:map-property name="keepalive-time" readOnly="true" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="true" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="true" description="The time unit"/>
+ <c:simple-property name="time" type="long" readOnly="true" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="true" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" displayName="Max Threads" required="false" type="string" readOnly="true" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="The name of the thread pool."/>
@@ -3081,8 +3078,8 @@
<resource-configuration>
<c:map-property name="keepalive-time" readOnly="false" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" readOnly="false" type="long" description="The time"/>
- <c:simple-property name="unit" required="true" readOnly="false" type="string" description="The time unit"/>
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="string" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="The name of the thread pool."/>
@@ -5499,9 +5496,9 @@
<resource-configuration>
<c:simple-property name="allow-core-timeout" required="false" type="boolean" readOnly="false" defaultValue="false" displayName="Allow Core Timeout" description="Whether core threads may time out. The default value is false."/>
<c:simple-property name="core-threads:expr" required="false" type="integer" readOnly="false" displayName="Core Threads" description="The core thread pool size which is smaller than the maximum pool size. If undefined, the core thread pool size is the same as the maximum thread pool size."/>
- <c:map-property name="keepalive-time" required="true" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="false" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="false" description="The time unit"/>
+ <c:map-property name="keepalive-time" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="integer" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" displayName="Name" description="The name of the thread pool."/>
@@ -5523,9 +5520,9 @@
<resource-configuration>
<c:simple-property name="allow-core-timeout" required="false" type="boolean" readOnly="false" defaultValue="false" displayName="Allow Core Timeout" description="Whether core threads may time out. The default value is false."/>
<c:simple-property name="core-threads:expr" required="false" type="integer" readOnly="false" displayName="Core Threads" description="The core thread pool size which is smaller than the maximum pool size. If undefined, the core thread pool size is the same as the maximum thread pool size."/>
- <c:map-property name="keepalive-time" required="true" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="false" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="false" description="The time unit"/>
+ <c:map-property name="keepalive-time" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="integer" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" displayName="Name" description="The name of the thread pool."/>
@@ -5711,8 +5708,8 @@
<resource-configuration>
<c:map-property name="keepalive-time" readOnly="false" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="false" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="false" description="The time unit"/>
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="false" type="string" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="The name of the thread pool."/>
@@ -5927,8 +5924,8 @@
<resource-configuration>
<c:map-property name="keepalive-time" readOnly="false" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" readOnly="false" type="long" description="The time"/>
- <c:simple-property name="unit" required="true" readOnly="false" type="string" description="The time unit"/>
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="string" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="The name of the thread pool."/>
@@ -10269,16 +10266,15 @@
</plugin-configuration>
<metric property="current-thread-count" description="The current number of threads in the pool."/>
- <metric property="keepalive-time:time" description="The time"/>
<metric property="largest-thread-count" description="The largest number of threads that have ever simultaneously been in the pool."/>
<metric property="rejected-count" description="The number of tasks that have been passed to the handoff-executor (if one is specified) or discarded."/>
<resource-configuration>
<c:simple-property name="allow-core-timeout" required="false" type="boolean" readOnly="false" defaultValue="false" displayName="Allow Core Timeout" description="Whether core threads may time out. The default value is false."/>
<c:simple-property name="core-threads:expr" required="false" type="integer" readOnly="false" displayName="Core Threads" description="The core thread pool size which is smaller than the maximum pool size. If undefined, the core thread pool size is the same as the maximum thread pool size."/>
- <c:map-property name="keepalive-time" required="true" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="false" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="false" description="The time unit"/>
+ <c:map-property name="keepalive-time" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="integer" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" displayName="Name" description="The name of the thread pool."/>
@@ -10298,16 +10294,15 @@
</plugin-configuration>
<metric property="current-thread-count" description="The current number of threads in the pool."/>
- <metric property="keepalive-time:time" description="The time"/>
<metric property="largest-thread-count" description="The largest number of threads that have ever simultaneously been in the pool."/>
<metric property="rejected-count" description="The number of tasks that have been passed to the handoff-executor (if one is specified) or discarded."/>
<resource-configuration>
<c:simple-property name="allow-core-timeout" required="false" type="boolean" readOnly="false" defaultValue="false" displayName="Allow Core Timeout" description="Whether core threads may time out. The default value is false."/>
<c:simple-property name="core-threads:expr" required="false" type="integer" readOnly="false" displayName="Core Threads" description="The core thread pool size which is smaller than the maximum pool size. If undefined, the core thread pool size is the same as the maximum thread pool size."/>
- <c:map-property name="keepalive-time" required="true" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="false" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="false" description="The time unit"/>
+ <c:map-property name="keepalive-time" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="integer" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" displayName="Name" description="The name of the thread pool."/>
@@ -10863,8 +10858,8 @@
<resource-configuration>
<c:map-property name="keepalive-time" readOnly="false" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" readOnly="false" type="long" description="The time"/>
- <c:simple-property name="unit" required="true" readOnly="false" type="string" description="The time unit"/>
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="string" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="The name of the thread pool."/>
@@ -10942,8 +10937,8 @@
<resource-configuration>
<c:map-property name="keepalive-time" readOnly="false" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="false" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="false" description="The time unit"/>
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="false" type="string" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="The name of the thread pool."/>
commit 8000e712dd98fd8ee8e1ff52940e15b07f11e782
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Wed Aug 15 20:13:14 2012 +0200
[BZ 845277] - quick fix: removed the doctype declaration and removed overcasting to int
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
index 3da090a..8445a46 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
@@ -312,7 +312,7 @@ public abstract class AbstractMetricGraphView extends LocatableVLayout {
for (MeasurementDataNumericHighLowComposite d : data) {
if (!Double.isNaN(d.getValue())) {
- handler.add(new DataPoint(d.getTimestamp(), (int) d.getValue()));
+ handler.add(new DataPoint(d.getTimestamp(), d.getValue()));
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
index a0a4d2a..6a78aab 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
+++ b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
@@ -1,4 +1,3 @@
-<!DOCTYPE html>
<html>
<head>
<!-- this forces us to emulate IE8 "quirks" mode regardless of IE browser version. It:
commit 5d243b30f5315f18329f6f4fa9db22ae47eb32bd
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Wed Aug 15 19:42:24 2012 +0200
[BZ 845277 - JBoss ON dashboard shows messed metric graph on IE 8/9] Version of gflot upgraded to 2.4.2 (it contains the excanvas library for IE8/9 support of HTML canvas el.), version of sparkline upgraded to 2.0, version of jquery upgraded to 1.7.2
diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index e3aca30..a4b08b0 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -143,9 +143,10 @@
to provide jquery explcitly for jquery.sparkline support. See CoreGUI.gwt.xml for the jquery.sparkline
declaration and coregui/webapp/js for the lib inclusion.) -->
<dependency>
- <groupId>ca.nanometrics</groupId>
+ <groupId>com.googlecode.gflot</groupId>
<artifactId>gflot</artifactId>
- <version>1.0.0</version>
+ <version>2.4.2</version>
+ <scope>provided</scope>
</dependency>
@@ -283,8 +284,8 @@
<configuration>
<noServer>true</noServer>
<inplace>false</inplace>
- <!-- <logLevel>INFO' -bindAddress 0.0.0.0 -logLevel 'INFO</logLevel> -->
- <logLevel>INFO</logLevel>
+<!-- <logLevel>INFO' -bindAddress 0.0.0.0 -logLevel 'INFO</logLevel> -->
+ <logLevel>INFO</logLevel>
<runTarget>${coreGuiRunTarget}</runTarget>
<extraJvmArgs>${gwt-plugin.extraJvmArgs}</extraJvmArgs>
<localWorkers>${gwt-plugin.localWorkers}</localWorkers>
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
index 224125d..3da090a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
@@ -23,14 +23,15 @@ import java.util.List;
import ca.nanometrics.gflot.client.Axis;
import ca.nanometrics.gflot.client.DataPoint;
-import ca.nanometrics.gflot.client.PlotItem;
import ca.nanometrics.gflot.client.PlotModel;
-import ca.nanometrics.gflot.client.PlotPosition;
import ca.nanometrics.gflot.client.SeriesHandler;
import ca.nanometrics.gflot.client.SimplePlot;
import ca.nanometrics.gflot.client.event.PlotHoverListener;
+import ca.nanometrics.gflot.client.event.PlotItem;
+import ca.nanometrics.gflot.client.event.PlotPosition;
import ca.nanometrics.gflot.client.jsni.Plot;
import ca.nanometrics.gflot.client.options.AxisOptions;
+import ca.nanometrics.gflot.client.options.GlobalSeriesOptions;
import ca.nanometrics.gflot.client.options.GridOptions;
import ca.nanometrics.gflot.client.options.LineSeriesOptions;
import ca.nanometrics.gflot.client.options.PlotOptions;
@@ -201,9 +202,11 @@ public abstract class AbstractMetricGraphView extends LocatableVLayout {
PlotModel model = new PlotModel();
PlotOptions plotOptions = new PlotOptions();
- plotOptions.setDefaultLineSeriesOptions(new LineSeriesOptions().setLineWidth(1).setShow(true));
- plotOptions.setDefaultPointsOptions(new PointsSeriesOptions().setRadius(2).setShow(true));
- plotOptions.setDefaultShadowSize(0);
+ GlobalSeriesOptions globalSeriesOptions = new GlobalSeriesOptions();
+ globalSeriesOptions.setLineSeriesOptions(new LineSeriesOptions().setLineWidth(1).setShow(true));
+ globalSeriesOptions.setPointsOptions(new PointsSeriesOptions().setRadius(2).setShow(true));
+ globalSeriesOptions.setShadowSize(0);
+ plotOptions.setGlobalSeriesOptions(globalSeriesOptions);
// You need make the grid hoverable <<<<<<<<<
plotOptions
@@ -308,10 +311,12 @@ public abstract class AbstractMetricGraphView extends LocatableVLayout {
SeriesHandler handler = model.addSeries(definition.getDisplayName(), "#007f00");
for (MeasurementDataNumericHighLowComposite d : data) {
- handler.add(new DataPoint(d.getTimestamp(), d.getValue()));
+ if (!Double.isNaN(d.getValue())) {
+ handler.add(new DataPoint(d.getTimestamp(), (int) d.getValue()));
+ }
}
- plotOptions.setYAxisOptions(new AxisOptions().setTicks(5).setLabelWidth(70)
+ plotOptions.addYAxisOptions(new AxisOptions().setTicks(5).setLabelWidth(70)
.setTickFormatter(new TickFormatter() {
public String formatTickValue(double v, Axis axis) {
return MeasurementConverterClient.format(v, definition.getUnits(), true);
@@ -323,7 +328,7 @@ public abstract class AbstractMetricGraphView extends LocatableVLayout {
int xTicks = getDefaultWidth() / 140;
- plotOptions.setXAxisOptions(new AxisOptions().setTicks(xTicks).setMinimum(min).setMaximum(max)
+ plotOptions.addXAxisOptions(new AxisOptions().setTicks(xTicks).setMinimum(min).setMaximum(max)
.setTickFormatter(new TickFormatter() {
public String formatTickValue(double tickValue, Axis axis) {
com.google.gwt.i18n.client.DateTimeFormat dateFormat = DateTimeFormat
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java
index edc1611..330eaf0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java
@@ -24,15 +24,16 @@ import java.util.Set;
import ca.nanometrics.gflot.client.Axis;
import ca.nanometrics.gflot.client.DataPoint;
-import ca.nanometrics.gflot.client.PlotItem;
import ca.nanometrics.gflot.client.PlotModel;
import ca.nanometrics.gflot.client.PlotModelStrategy;
-import ca.nanometrics.gflot.client.PlotPosition;
import ca.nanometrics.gflot.client.SeriesHandler;
import ca.nanometrics.gflot.client.SimplePlot;
import ca.nanometrics.gflot.client.event.PlotHoverListener;
+import ca.nanometrics.gflot.client.event.PlotItem;
+import ca.nanometrics.gflot.client.event.PlotPosition;
import ca.nanometrics.gflot.client.jsni.Plot;
import ca.nanometrics.gflot.client.options.AxisOptions;
+import ca.nanometrics.gflot.client.options.GlobalSeriesOptions;
import ca.nanometrics.gflot.client.options.GridOptions;
import ca.nanometrics.gflot.client.options.LineSeriesOptions;
import ca.nanometrics.gflot.client.options.PlotOptions;
@@ -133,9 +134,11 @@ public class LiveGraphView extends LocatableVLayout {
PlotModel model = new PlotModel();
PlotOptions plotOptions = new PlotOptions();
- plotOptions.setDefaultLineSeriesOptions(new LineSeriesOptions().setLineWidth(1).setShow(true));
- plotOptions.setDefaultPointsOptions(new PointsSeriesOptions().setRadius(2).setShow(true));
- plotOptions.setDefaultShadowSize(0);
+ GlobalSeriesOptions globalSeriesOptions = new GlobalSeriesOptions();
+ globalSeriesOptions.setLineSeriesOptions(new LineSeriesOptions().setLineWidth(1).setShow(true));
+ globalSeriesOptions.setPointsOptions(new PointsSeriesOptions().setRadius(2).setShow(true));
+ globalSeriesOptions.setShadowSize(0);
+ plotOptions.setGlobalSeriesOptions(globalSeriesOptions);
// You need make the grid hoverable <<<<<<<<<
plotOptions
@@ -258,7 +261,7 @@ public class LiveGraphView extends LocatableVLayout {
dataLoader.scheduleRepeating(1000);
- plotOptions.setYAxisOptions(new AxisOptions().setLabelWidth(70).setTicks(5)
+ plotOptions.addYAxisOptions(new AxisOptions().setLabelWidth(70).setTicks(5)
.setTickFormatter(new TickFormatter() {
public String formatTickValue(double v, Axis axis) {
return MeasurementConverterClient.format(v, definition.getUnits(), true);
@@ -268,7 +271,7 @@ public class LiveGraphView extends LocatableVLayout {
min = System.currentTimeMillis();
max = System.currentTimeMillis() + (1000L * 60);
- plotOptions.setXAxisOptions(new AxisOptions().setTicks(8).setTickFormatter(new TickFormatter() {
+ plotOptions.addXAxisOptions(new AxisOptions().setTicks(8).setTickFormatter(new TickFormatter() {
public String formatTickValue(double tickValue, Axis axis) {
DateTimeFormat dateFormat = DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_MEDIUM);
return dateFormat.format(new Date((long) tickValue));
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index 614e6f7..78db5af 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -46,12 +46,10 @@
<!-- External javascript libraries -->
<!-- jquery.sparkline requires jquery. We don't explicitly provide jquery here because it is already
- embedded in the GFlot JAR (the charting lib used for GraphPortlet). Furthermore, GFlot 1.0.0 requires
- its older, embedded version of jquery (1.3.2). Fortunately, sparkline is compatible with this older version.
- We will need to provide jquery explicitly (like the commented version below) if we remove GFlot.
- <script src="/coregui/js/jquery-1.4.4.js"/>
+ embedded in the GFlot JAR (the charting lib used for GraphPortlet). Furthermore, GFlot 2.4.2 requires
+ the version of jquery (1.7.2).
-->
- <script src="/coregui/js/jquery.sparkline-1.6.js"/>
+ <script src="/coregui/js/jquery.sparkline-2.0.min.js"/>
<!--
Limit compilation to your preferred browser(s) to speed up compile time.
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
index 2c6e285..a0a4d2a 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
+++ b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<!-- this forces us to emulate IE8 "quirks" mode regardless of IE browser version. It:
@@ -21,7 +22,8 @@
document.write("<meta name='gwt:property' content='locale="+lang +"'>");
}
</script>
-
+ <script src="/coregui/js/jquery-1.7.2.min.js"/>
+
<title>RHQ</title>
<link rel="icon" type="image/png" href="/images/favicon.png" />
<link rel="apple-touch-icon" href="/images/favicon.png" />
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.7.2.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.7.2.min.js
new file mode 100644
index 0000000..16ad06c
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.7.2.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.7.2 jquery.com | jquery.org/license */
+(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;
for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e
+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];
if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?
c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a
,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(
c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return th
is;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArra
y:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=a
rguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.a
ttachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(
q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:func
tion(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){v
ar d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b
)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test("Â ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.s
hift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progr
ess:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=ar
guments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.ge
tAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","
t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><
td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.
style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].dat
a)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return
b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a
!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(
){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.
each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.e
ach(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.val
Hooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!
==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:fu
nction(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a
,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.op
tSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(
+a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,gu
id:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p
.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArr
ay(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(ar
guments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);
return c.result}},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var
d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(
!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.cont
ains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this.
_just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!
="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"
**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):thi
s.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[]
,d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]
!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=
o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u
00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++)
{c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&
(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){re
turn a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toL
owerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,
j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f===
"$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compa
reDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.
ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagNam
e(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\
]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){va
r d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.co
ntains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,t
his)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNode
s)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|me
ta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a
))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&
this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f
+.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,"
"):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return
this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragm
ents[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e)
{var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]
&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+
.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch
(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,
f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=fun
ction(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement
("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.na
me,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String
,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once mem
ory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d
.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error
:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var
g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.
async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-Wit
h"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3)
,a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:functi
on(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidd
en");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue
===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.proto
type={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!=
=b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this
.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,l
eft:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position
==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFuncti
on(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(
d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-1.6.js b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-1.6.js
deleted file mode 100644
index d60cf18..0000000
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-1.6.js
+++ /dev/null
@@ -1,1271 +0,0 @@
-/**
-*
-* jquery.sparkline.js
-*
-* v1.6
-* (c) Splunk, Inc
-* Contact: Gareth Watts (gareth(a)splunk.com)
-* http://omnipotent.net/jquery.sparkline/
-*
-* Generates inline sparkline charts from data supplied either to the method
-* or inline in HTML
-*
-* Compatible with Internet Explorer 6.0+ and modern browsers equipped with the canvas tag
-* (Firefox 2.0+, Safari, Opera, etc)
-*
-* License: New BSD License
-*
-* Copyright (c) 2010, Splunk Inc.
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without modification,
-* are permitted provided that the following conditions are met:
-*
-* * Redistributions of source code must retain the above copyright notice,
-* this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above copyright notice,
-* this list of conditions and the following disclaimer in the documentation
-* and/or other materials provided with the distribution.
-* * Neither the name of Splunk Inc nor the names of its contributors may
-* be used to endorse or promote products derived from this software without
-* specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
-* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
-*
-* Usage:
-* $(selector).sparkline(values, options)
-*
-* If values is undefined or set to 'html' then the data values are read from the specified tag:
-* <p>Sparkline: <span class="sparkline">1,4,6,6,8,5,3,5</span></p>
-* $('.sparkline').sparkline();
-* There must be no spaces in the enclosed data set
-*
-* Otherwise values must be an array of numbers or null values
-* <p>Sparkline: <span id="sparkline1">This text replaced if the browser is compatible</span></p>
-* $('#sparkline1').sparkline([1,4,6,6,8,5,3,5])
-* $('#sparkline2').sparkline([1,4,6,null,null,5,3,5])
-*
-* Values can also be specified in an HTML comment, or as a values attribute:
-* <p>Sparkline: <span class="sparkline"><!--1,4,6,6,8,5,3,5 --></span></p>
-* <p>Sparkline: <span class="sparkline" values="1,4,6,6,8,5,3,5"></span></p>
-* $('.sparkline').sparkline();
-*
-* For line charts, x values can also be specified:
-* <p>Sparkline: <span class="sparkline">1:1,2.7:4,3.4:6,5:6,6:8,8.7:5,9:3,10:5</span></p>
-* $('#sparkline1').sparkline([ [1,1], [2.7,4], [3.4,6], [5,6], [6,8], [8.7,5], [9,3], [10,5] ])
-*
-* By default, options should be passed in as teh second argument to the sparkline function:
-* $('.sparkline').sparkline([1,2,3,4], {type: 'bar'})
-*
-* Options can also be set by passing them on the tag itself. This feature is disabled by default though
-* as there's a slight performance overhead:
-* $('.sparkline').sparkline([1,2,3,4], {enableTagOptions: true})
-* <p>Sparkline: <span class="sparkline" sparkType="bar" sparkBarColor="red">loading</span></p>
-* Prefix all options supplied as tag attribute with "spark" (configurable by setting tagOptionPrefix)
-*
-* Supported options:
-* lineColor - Color of the line used for the chart
-* fillColor - Color used to fill in the chart - Set to '' or false for a transparent chart
-* width - Width of the chart - Defaults to 3 times the number of values in pixels
-* height - Height of the chart - Defaults to the height of the containing element
-* chartRangeMin - Specify the minimum value to use for the Y range of the chart - Defaults to the minimum value supplied
-* chartRangeMax - Specify the maximum value to use for the Y range of the chart - Defaults to the maximum value supplied
-* chartRangeClip - Clip out of range values to the max/min specified by chartRangeMin and chartRangeMax
-* chartRangeMinX - Specify the minimum value to use for the X range of the chart - Defaults to the minimum value supplied
-* chartRangeMaxX - Specify the maximum value to use for the X range of the chart - Defaults to the maximum value supplied
-* composite - If true then don't erase any existing chart attached to the tag, but draw
-* another chart over the top - Note that width and height are ignored if an
-* existing chart is detected.
-* tagValuesAttribute - Name of tag attribute to check for data values - Defaults to 'values'
-* enableTagOptions - Whether to check tags for sparkline options
-* tagOptionPrefix - Prefix used for options supplied as tag attributes - Defaults to 'spark'
-*
-* There are 7 types of sparkline, selected by supplying a "type" option of 'line' (default),
-* 'bar', 'tristate', 'bullet', 'discrete', 'pie' or 'box'
-* line - Line chart. Options:
-* spotColor - Set to '' to not end each line in a circular spot
-* minSpotColor - If set, color of spot at minimum value
-* maxSpotColor - If set, color of spot at maximum value
-* spotRadius - Radius in pixels
-* lineWidth - Width of line in pixels
-* normalRangeMin
-* normalRangeMax - If set draws a filled horizontal bar between these two values marking the "normal"
-* or expected range of values
-* normalRangeColor - Color to use for the above bar
-* drawNormalOnTop - Draw the normal range above the chart fill color if true
-* defaultPixelsPerValue - Defaults to 3 pixels of width for each value in the chart
-*
-* bar - Bar chart. Options:
-* barColor - Color of bars for postive values
-* negBarColor - Color of bars for negative values
-* zeroColor - Color of bars with zero values
-* nullColor - Color of bars with null values - Defaults to omitting the bar entirely
-* barWidth - Width of bars in pixels
-* colorMap - Optional mappnig of values to colors to override the *BarColor values above
-* can be an Array of values to control the color of individual bars
-* barSpacing - Gap between bars in pixels
-* zeroAxis - Centers the y-axis around zero if true
-*
-* tristate - Charts values of win (>0), lose (<0) or draw (=0)
-* posBarColor - Color of win values
-* negBarColor - Color of lose values
-* zeroBarColor - Color of draw values
-* barWidth - Width of bars in pixels
-* barSpacing - Gap between bars in pixels
-* colorMap - Optional mappnig of values to colors to override the *BarColor values above
-* can be an Array of values to control the color of individual bars
-*
-* discrete - Options:
-* lineHeight - Height of each line in pixels - Defaults to 30% of the graph height
-* thesholdValue - Values less than this value will be drawn using thresholdColor instead of lineColor
-* thresholdColor
-*
-* bullet - Values for bullet graphs msut be in the order: target, performance, range1, range2, range3, ...
-* options:
-* targetColor - The color of the vertical target marker
-* targetWidth - The width of the target marker in pixels
-* performanceColor - The color of the performance measure horizontal bar
-* rangeColors - Colors to use for each qualitative range background color
-*
-* pie - Pie chart. Options:
-* sliceColors - An array of colors to use for pie slices
-* offset - Angle in degrees to offset the first slice - Try -90 or +90
-*
-* box - Box plot. Options:
-* raw - Set to true to supply pre-computed plot points as values
-* values should be: low_outlier, low_whisker, q1, median, q3, high_whisker, high_outlier
-* When set to false you can supply any number of values and the box plot will
-* be computed for you. Default is false.
-* showOutliers - Set to true (default) to display outliers as circles
-* outlierIRQ - Interquartile range used to determine outliers. Default 1.5
-* boxLineColor - Outline color of the box
-* boxFillColor - Fill color for the box
-* whiskerColor - Line color used for whiskers
-* outlierLineColor - Outline color of outlier circles
-* outlierFillColor - Fill color of the outlier circles
-* spotRadius - Radius of outlier circles
-* medianColor - Line color of the median line
-* target - Draw a target cross hair at the supplied value (default undefined)
-*
-*
-*
-* Examples:
-* $('#sparkline1').sparkline(myvalues, { lineColor: '#f00', fillColor: false });
-* $('.barsparks').sparkline('html', { type:'bar', height:'40px', barWidth:5 });
-* $('#tristate').sparkline([1,1,-1,1,0,0,-1], { type:'tristate' }):
-* $('#discrete').sparkline([1,3,4,5,5,3,4,5], { type:'discrete' });
-* $('#bullet').sparkline([10,12,12,9,7], { type:'bullet' });
-* $('#pie').sparkline([1,1,2], { type:'pie' });
-*/
-
-
-(function($) {
-
- /*
- * Default configuration settings
- */
- var defaults = {
- // Settings common to most/all chart types
- common: {
- type : 'line',
- lineColor : '#00f',
- fillColor : '#cdf',
- defaultPixelsPerValue : 3,
- width : 'auto',
- height : 'auto',
- composite : false,
- tagValuesAttribute: 'values',
- tagOptionsPrefix: 'spark',
- enableTagOptions: false
- },
- // Defaults for line charts
- line: {
- spotColor : '#f80',
- spotRadius : 1.5,
- minSpotColor : '#f80',
- maxSpotColor : '#f80',
- lineWidth: 1,
- normalRangeMin : undefined,
- normalRangeMax : undefined,
- normalRangeColor : '#ccc',
- drawNormalOnTop: false,
- chartRangeMin : undefined,
- chartRangeMax : undefined,
- chartRangeMinX : undefined,
- chartRangeMaxX : undefined
- },
- // Defaults for bar charts
- bar: {
- barColor : '#00f',
- negBarColor : '#f44',
- zeroColor: undefined,
- nullColor: undefined,
- zeroAxis : undefined,
- barWidth : 4,
- barSpacing : 1,
- chartRangeMax: undefined,
- chartRangeMin: undefined,
- chartRangeClip: false,
- colorMap : undefined
- },
- // Defaults for tristate charts
- tristate: {
- barWidth : 4,
- barSpacing : 1,
- posBarColor: '#6f6',
- negBarColor : '#f44',
- zeroBarColor : '#999',
- colorMap : {}
- },
- // Defaults for discrete charts
- discrete: {
- lineHeight: 'auto',
- thresholdColor: undefined,
- thresholdValue : 0,
- chartRangeMax: undefined,
- chartRangeMin: undefined,
- chartRangeClip: false
- },
- // Defaults for bullet charts
- bullet: {
- targetColor : 'red',
- targetWidth : 3, // width of the target bar in pixels
- performanceColor : 'blue',
- rangeColors : ['#D3DAFE', '#A8B6FF', '#7F94FF' ],
- base : undefined // set this to a number to change the base start number
- },
- // Defaults for pie charts
- pie: {
- sliceColors : ['#f00', '#0f0', '#00f']
- },
- // Defaults for box plots
- box: {
- raw: false,
- boxLineColor: 'black',
- boxFillColor: '#cdf',
- whiskerColor: 'black',
- outlierLineColor: '#333',
- outlierFillColor: 'white',
- medianColor: 'red',
- showOutliers: true,
- outlierIQR: 1.5,
- spotRadius: 1.5,
- target: undefined,
- targetColor: '#4a2',
- chartRangeMax: undefined,
- chartRangeMin: undefined
- }
- };
-
- // Provide a cross-browser interface to a few simple drawing primitives
- var VCanvas_base, VCanvas_canvas, VCanvas_vml;
- $.fn.simpledraw = function(width, height, use_existing) {
- if (use_existing && this[0].VCanvas) {
- return this[0].VCanvas;
- }
- if (width === undefined) {
- width=$(this).innerWidth();
- }
- if (height === undefined) {
- height=$(this).innerHeight();
- }
- if ($.browser.hasCanvas) {
- return new VCanvas_canvas(width, height, this);
- } else if ($.browser.msie) {
- return new VCanvas_vml(width, height, this);
- } else {
- return false;
- }
- };
-
- var pending = [];
-
-
- $.fn.sparkline = function(uservalues, userOptions) {
- return this.each(function() {
- var options = new $.fn.sparkline.options(this, userOptions);
- var render = function() {
- var values, width, height;
- if (uservalues==='html' || uservalues===undefined) {
- var vals = this.getAttribute(options.get('tagValuesAttribute'));
- if (vals===undefined || vals===null) {
- vals = $(this).html();
- }
- values = vals.replace(/(^\s*<!--)|(-->\s*$)|\s+/g, '').split(',');
- } else {
- values = uservalues;
- }
-
- width = options.get('width')=='auto' ? values.length*options.get('defaultPixelsPerValue') : options.get('width');
- if (options.get('height') == 'auto') {
- if (!options.get('composite') || !this.VCanvas) {
- // must be a better way to get the line height
- var tmp = document.createElement('span');
- tmp.innerHTML = 'a';
- $(this).html(tmp);
- height = $(tmp).innerHeight();
- $(tmp).remove();
- }
- } else {
- height = options.get('height');
- }
-
- $.fn.sparkline[options.get('type')].call(this, values, options, width, height);
- };
- // jQuery 1.3.0 completely changed the meaning of :hidden :-/
- if (($(this).html() && $(this).is(':hidden')) || ($.fn.jquery < "1.3.0" && $(this).parents().is(':hidden')) || !$(this).parents('body').length) {
- pending.push([this, render]);
- } else {
- render.call(this);
- }
- });
- };
-
- $.fn.sparkline.defaults = defaults;
-
-
- $.sparkline_display_visible = function() {
- for (var i=pending.length-1; i>=0; i--) {
- var el = pending[i][0];
- if ($(el).is(':visible') && !$(el).parents().is(':hidden')) {
- pending[i][1].call(el);
- pending.splice(i, 1);
- }
- }
- };
-
-
- /**
- * User option handler
- */
- var UNSET_OPTION = {};
- var normalizeValue = function(val) {
- switch(val) {
- case 'undefined':
- val = undefined;
- break;
- case 'null':
- val = null;
- break;
- case 'true':
- val = true;
- break;
- case 'false':
- val = false;
- break;
- default:
- var nf = parseFloat(val);
- if (val == nf) {
- val = nf;
- }
- }
- return val;
- };
- $.fn.sparkline.options = function(tag, userOptions) {
- var extendedOptions;
- this.userOptions = userOptions = userOptions || {};
- this.tag = tag;
- this.tagValCache = {};
- var defaults = $.fn.sparkline.defaults;
- var base = defaults.common;
- this.tagOptionsPrefix = userOptions.enableTagOptions && (userOptions.tagOptionsPrefix || base.tagOptionsPrefix);
-
- var tagOptionType = this.getTagSetting('type');
- if (tagOptionType === UNSET_OPTION) {
- extendedOptions = defaults[userOptions.type || base.type];
- } else {
- extendedOptions = defaults[tagOptionType];
- }
- this.mergedOptions = $.extend({}, base, extendedOptions, userOptions);
- };
-
-
- $.fn.sparkline.options.prototype.getTagSetting = function(key) {
- var val, i, prefix = this.tagOptionsPrefix;
- if (prefix === false || prefix === undefined) {
- return UNSET_OPTION;
- }
- if (this.tagValCache.hasOwnProperty(key)) {
- val = this.tagValCache.key;
- } else {
- val = this.tag.getAttribute(prefix + key);
- if (val === undefined || val === null) {
- val = UNSET_OPTION;
- } else if (val.substr(0, 1) == '[') {
- val = val.substr(1, val.length-2).split(',');
- for(i=val.length; i--;) {
- val[i] = normalizeValue(val[i].replace(/(^\s*)|(\s*$)/g, ''));
- }
- } else if (val.substr(0, 1) == '{') {
- var pairs= val.substr(1, val.length-2).split(',');
- val = {};
- for(i=pairs.length; i--;) {
- var keyval = pairs[i].split(':', 2);
- val[keyval[0].replace(/(^\s*)|(\s*$)/g, '')] = normalizeValue(keyval[1].replace(/(^\s*)|(\s*$)/g, ''));
- }
- } else {
- val = normalizeValue(val);
- }
- this.tagValCache.key = val;
- }
- return val;
- };
-
- $.fn.sparkline.options.prototype.get = function(key) {
- var tagOption = this.getTagSetting(key);
- if (tagOption !== UNSET_OPTION) {
- return tagOption;
- }
- return this.mergedOptions[key];
- };
-
-
- /**
- * Line charts
- */
- $.fn.sparkline.line = function(values, options, width, height) {
- var xvalues = [], yvalues = [], yminmax = [];
- for (var i=0; i<values.length; i++) {
- var val = values[i];
- var isstr = typeof(values[i])=='string';
- var isarray = typeof(values[i])=='object' && values[i] instanceof Array;
- var sp = isstr && values[i].split(':');
- if (isstr && sp.length == 2) { // x:y
- xvalues.push(Number(sp[0]));
- yvalues.push(Number(sp[1]));
- yminmax.push(Number(sp[1]));
- } else if (isarray) {
- xvalues.push(val[0]);
- yvalues.push(val[1]);
- yminmax.push(val[1]);
- } else {
- xvalues.push(i);
- if (values[i]===null || values[i]=='null') {
- yvalues.push(null);
- } else {
- yvalues.push(Number(val));
- yminmax.push(Number(val));
- }
- }
- }
- if (options.get('xvalues')) {
- xvalues = options.get('xvalues');
- }
-
- var maxy = Math.max.apply(Math, yminmax);
- var maxyval = maxy;
- var miny = Math.min.apply(Math, yminmax);
- var minyval = miny;
-
- var maxx = Math.max.apply(Math, xvalues);
- var minx = Math.min.apply(Math, xvalues);
-
- var normalRangeMin = options.get('normalRangeMin');
- var normalRangeMax = options.get('normalRangeMax');
-
- if (normalRangeMin!==undefined) {
- if (normalRangeMin<miny) {
- miny = normalRangeMin;
- }
- if (normalRangeMax>maxy) {
- maxy = normalRangeMax;
- }
- }
- if (options.get('chartRangeMin')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMin')<miny)) {
- miny = options.get('chartRangeMin');
- }
- if (options.get('chartRangeMax')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMax')>maxy)) {
- maxy = options.get('chartRangeMax');
- }
- if (options.get('chartRangeMinX')!==undefined && (options.get('chartRangeClipX') || options.get('chartRangeMinX')<minx)) {
- minx = options.get('chartRangeMinX');
- }
- if (options.get('chartRangeMaxX')!==undefined && (options.get('chartRangeClipX') || options.get('chartRangeMaxX')>maxx)) {
- maxx = options.get('chartRangeMaxX');
- }
- var rangex = maxx-minx === 0 ? 1 : maxx-minx;
- var rangey = maxy-miny === 0 ? 1 : maxy-miny;
- var vl = yvalues.length-1;
-
- if (vl<1) {
- this.innerHTML = '';
- return;
- }
-
- var target = $(this).simpledraw(width, height, options.get('composite'));
- if (target) {
- var canvas_width = target.pixel_width;
- var canvas_height = target.pixel_height;
- var canvas_top = 0;
- var canvas_left = 0;
-
- var spotRadius = options.get('spotRadius');
- if (spotRadius && (canvas_width < (spotRadius*4) || canvas_height < (spotRadius*4))) {
- spotRadius = 0;
- }
- if (spotRadius) {
- // adjust the canvas size as required so that spots will fit
- if (options.get('minSpotColor') || (options.get('spotColor') && yvalues[vl]==miny)) {
- canvas_height -= Math.ceil(spotRadius);
- }
- if (options.get('maxSpotColor') || (options.get('spotColor') && yvalues[vl]==maxy)) {
- canvas_height -= Math.ceil(spotRadius);
- canvas_top += Math.ceil(spotRadius);
- }
- if (options.get('minSpotColor') || options.get('maxSpotColor') && (yvalues[0]==miny || yvalues[0]==maxy)) {
- canvas_left += Math.ceil(spotRadius);
- canvas_width -= Math.ceil(spotRadius);
- }
- if (options.get('spotColor') || (options.get('minSpotColor') || options.get('maxSpotColor') && (yvalues[vl]==miny||yvalues[vl]==maxy))) {
- canvas_width -= Math.ceil(spotRadius);
- }
- }
-
-
- canvas_height--;
-
- var drawNormalRange = function() {
- if (normalRangeMin!==undefined) {
- var ytop = canvas_top+Math.round(canvas_height-(canvas_height*((normalRangeMax-miny)/rangey)));
- var height = Math.round((canvas_height*(normalRangeMax-normalRangeMin))/rangey);
- target.drawRect(canvas_left, ytop, canvas_width, height, undefined, options.get('normalRangeColor'));
- }
- };
-
- if (!options.get('drawNormalOnTop')) {
- drawNormalRange();
- }
-
- var path = [];
- var paths = [path];
- var x, y, vlen=yvalues.length;
- for(i=0; i<vlen; i++) {
- x=xvalues[i];
- y=yvalues[i];
- if (y===null) {
- if (i) {
- if (yvalues[i-1]!==null) {
- path = [];
- paths.push(path);
- }
- }
- } else {
- if (y < miny) {
- y=miny;
- }
- if (y > maxy) {
- y=maxy;
- }
- if (!path.length) {
- // previous value was null
- path.push([canvas_left+Math.round((x-minx)*(canvas_width/rangex)), canvas_top+canvas_height]);
- }
- path.push([canvas_left+Math.round((x-minx)*(canvas_width/rangex)), canvas_top+Math.round(canvas_height-(canvas_height*((y-miny)/rangey)))]);
- }
- }
- var lineshapes = [];
- var fillshapes = [];
- var plen=paths.length;
- for(i=0; i<plen; i++) {
- path = paths[i];
- if (!path.length) {
- continue; // last value was null
- }
- if (options.get('fillColor')) {
- path.push([path[path.length-1][0], canvas_top+canvas_height-1]);
- fillshapes.push(path.slice(0));
- path.pop();
- }
- // if there's only a single point in this path, then we want to display it as a vertical line
- // which means we keep path[0] as is
- if (path.length>2) {
- // else we want the first value
- path[0] = [ path[0][0], path[1][1] ];
- }
- lineshapes.push(path);
- }
-
- // draw the fill first, then optionally the normal range, then the line on top of that
- plen = fillshapes.length;
- for(i=0; i<plen; i++) {
- target.drawShape(fillshapes[i], undefined, options.get('fillColor'));
- }
-
- if (options.get('drawNormalOnTop')) {
- drawNormalRange();
- }
-
- plen = lineshapes.length;
- for(i=0; i<plen; i++) {
- target.drawShape(lineshapes[i], options.get('lineColor'), undefined, options.get('lineWidth'));
- }
-
- if (spotRadius && options.get('spotColor')) {
- target.drawCircle(canvas_left+Math.round(xvalues[xvalues.length-1]*(canvas_width/rangex)), canvas_top+Math.round(canvas_height-(canvas_height*((yvalues[vl]-miny)/rangey))), spotRadius, undefined, options.get('spotColor'));
- }
- if (maxy!=minyval) {
- if (spotRadius && options.get('minSpotColor')) {
- x = xvalues[$.inArray(minyval, yvalues)];
- target.drawCircle(canvas_left+Math.round((x-minx)*(canvas_width/rangex)), canvas_top+Math.round(canvas_height-(canvas_height*((minyval-miny)/rangey))), spotRadius, undefined, options.get('minSpotColor'));
- }
- if (spotRadius && options.get('maxSpotColor')) {
- x = xvalues[$.inArray(maxyval, yvalues)];
- target.drawCircle(canvas_left+Math.round((x-minx)*(canvas_width/rangex)), canvas_top+Math.round(canvas_height-(canvas_height*((maxyval-miny)/rangey))), spotRadius, undefined, options.get('maxSpotColor'));
- }
- }
-
- } else {
- // Remove the tag contents if sparklines aren't supported
- this.innerHTML = '';
- }
- };
-
-
- /**
- * Bar charts
- */
- $.fn.sparkline.bar = function(values, options, width, height) {
- width = (values.length * options.get('barWidth')) + ((values.length-1) * options.get('barSpacing'));
- var num_values = [];
- for(var i=0, vlen=values.length; i<vlen; i++) {
- if (values[i]=='null' || values[i]===null) {
- values[i] = null;
- } else {
- values[i] = Number(values[i]);
- num_values.push(Number(values[i]));
- }
- }
- var max = Math.max.apply(Math, num_values),
- min = Math.min.apply(Math, num_values);
- if (options.get('chartRangeMin')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMin')<min)) {
- min = options.get('chartRangeMin');
- }
- if (options.get('chartRangeMax')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMax')>max)) {
- max = options.get('chartRangeMax');
- }
- var zeroAxis = options.get('zeroAxis');
- if (zeroAxis === undefined) {
- zeroAxis = min<0;
- }
- var range = max-min === 0 ? 1 : max-min;
-
- var colorMapByIndex, colorMapByValue;
- if ($.isArray(options.get('colorMap'))) {
- colorMapByIndex = options.get('colorMap');
- colorMapByValue = null;
- } else {
- colorMapByIndex = null;
- colorMapByValue = options.get('colorMap');
- }
-
- var target = $(this).simpledraw(width, height, options.get('composite'));
- if (target) {
- var color,
- canvas_height = target.pixel_height,
- yzero = min<0 && zeroAxis ? canvas_height-Math.round(canvas_height * (Math.abs(min)/range))-1 : canvas_height-1;
-
- for(i=values.length; i--;) {
- var x = i*(options.get('barWidth')+options.get('barSpacing')),
- y,
- val = values[i];
- if (val===null) {
- if (options.get('nullColor')) {
- color = options.get('nullColor');
- val = (zeroAxis && min<0) ? 0 : min;
- height = 1;
- y = (zeroAxis && min<0) ? yzero : canvas_height - height;
- } else {
- continue;
- }
- } else {
- if (val < min) {
- val=min;
- }
- if (val > max) {
- val=max;
- }
- color = (val < 0) ? options.get('negBarColor') : options.get('barColor');
- if (zeroAxis && min<0) {
- height = Math.round(canvas_height*((Math.abs(val)/range)))+1;
- y = (val < 0) ? yzero : yzero-height;
- } else {
- height = Math.round(canvas_height*((val-min)/range))+1;
- y = canvas_height-height;
- }
- if (val===0 && options.get('zeroColor')!==undefined) {
- color = options.get('zeroColor');
- }
- if (colorMapByValue && colorMapByValue[val]) {
- color = colorMapByValue[val];
- } else if (colorMapByIndex && colorMapByIndex.length>i) {
- color = colorMapByIndex[i];
- }
- if (color===null) {
- continue;
- }
- }
- target.drawRect(x, y, options.get('barWidth')-1, height-1, color, color);
- }
- } else {
- // Remove the tag contents if sparklines aren't supported
- this.innerHTML = '';
- }
- };
-
-
- /**
- * Tristate charts
- */
- $.fn.sparkline.tristate = function(values, options, width, height) {
- values = $.map(values, Number);
- width = (values.length * options.get('barWidth')) + ((values.length-1) * options.get('barSpacing'));
-
- var colorMapByIndex, colorMapByValue;
- if ($.isArray(options.get('colorMap'))) {
- colorMapByIndex = options.get('colorMap');
- colorMapByValue = null;
- } else {
- colorMapByIndex = null;
- colorMapByValue = options.get('colorMap');
- }
-
- var target = $(this).simpledraw(width, height, options.get('composite'));
- if (target) {
- var canvas_height = target.pixel_height,
- half_height = Math.round(canvas_height/2);
-
- for(var i=values.length; i--;) {
- var x = i*(options.get('barWidth')+options.get('barSpacing')),
- y, color;
- if (values[i] < 0) {
- y = half_height;
- height = half_height-1;
- color = options.get('negBarColor');
- } else if (values[i] > 0) {
- y = 0;
- height = half_height-1;
- color = options.get('posBarColor');
- } else {
- y = half_height-1;
- height = 2;
- color = options.get('zeroBarColor');
- }
- if (colorMapByValue && colorMapByValue[values[i]]) {
- color = colorMapByValue[values[i]];
- } else if (colorMapByIndex && colorMapByIndex.length>i) {
- color = colorMapByIndex[i];
- }
- if (color===null) {
- continue;
- }
- target.drawRect(x, y, options.get('barWidth')-1, height-1, color, color);
- }
- } else {
- // Remove the tag contents if sparklines aren't supported
- this.innerHTML = '';
- }
- };
-
-
- /**
- * Discrete charts
- */
- $.fn.sparkline.discrete = function(values, options, width, height) {
- values = $.map(values, Number);
- width = options.get('width')=='auto' ? values.length*2 : width;
- var interval = Math.floor(width / values.length);
-
- var target = $(this).simpledraw(width, height, options.get('composite'));
- if (target) {
- var canvas_height = target.pixel_height,
- line_height = options.get('lineHeight') == 'auto' ? Math.round(canvas_height * 0.3) : options.get('lineHeight'),
- pheight = canvas_height - line_height,
- min = Math.min.apply(Math, values),
- max = Math.max.apply(Math, values);
- if (options.get('chartRangeMin')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMin')<min)) {
- min = options.get('chartRangeMin');
- }
- if (options.get('chartRangeMax')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMax')>max)) {
- max = options.get('chartRangeMax');
- }
- var range = max-min;
-
- for(var i=values.length; i--;) {
- var val = values[i];
- if (val < min) {
- val=min;
- }
- if (val > max) {
- val=max;
- }
- var x = (i*interval),
- ytop = Math.round(pheight-pheight*((val-min)/range));
- target.drawLine(x, ytop, x, ytop+line_height, (options.get('thresholdColor') && val < options.get('thresholdValue')) ? options.get('thresholdColor') : options.get('lineColor'));
- }
- } else {
- // Remove the tag contents if sparklines aren't supported
- this.innerHTML = '';
- }
-
- };
-
-
- /**
- * Bullet charts
- */
- $.fn.sparkline.bullet = function(values, options, width, height) {
- values = $.map(values, Number);
- // target, performance, range1, range2, range3
-
- width = options.get('width')=='auto' ? '4.0em' : width;
-
- var target = $(this).simpledraw(width, height, options.get('composite'));
- if (target && values.length>1) {
- var canvas_width = target.pixel_width-Math.ceil(options.get('targetWidth')/2),
- canvas_height = target.pixel_height,
- min = Math.min.apply(Math, values),
- max = Math.max.apply(Math, values);
-
- if (options.get('base') === undefined) {
- min = min < 0 ? min : 0;
- } else {
- min = options.get('base');
- }
- var range = max-min;
-
- // draw range values
- for(var i=2, vlen=values.length; i<vlen; i++) {
- var rangeval = values[i],
- rangewidth = Math.round(canvas_width*((rangeval-min)/range));
- target.drawRect(0, 0, rangewidth-1, canvas_height-1, options.get('rangeColors')[i-2], options.get('rangeColors')[i-2]);
- }
-
- // draw the performance bar
- var perfval = values[1],
- perfwidth = Math.round(canvas_width*((perfval-min)/range));
- target.drawRect(0, Math.round(canvas_height*0.3), perfwidth-1, Math.round(canvas_height*0.4)-1, options.get('performanceColor'), options.get('performanceColor'));
-
- // draw the target line
- var targetval = values[0],
- x = Math.round(canvas_width*((targetval-min)/range)-(options.get('targetWidth')/2)),
- targettop = Math.round(canvas_height*0.10),
- targetheight = canvas_height-(targettop*2);
- target.drawRect(x, targettop, options.get('targetWidth')-1, targetheight-1, options.get('targetColor'), options.get('targetColor'));
- } else {
- // Remove the tag contents if sparklines aren't supported
- this.innerHTML = '';
- }
- };
-
-
- /**
- * Pie charts
- */
- $.fn.sparkline.pie = function(values, options, width, height) {
- values = $.map(values, Number);
- width = options.get('width')=='auto' ? height : width;
-
- var target = $(this).simpledraw(width, height, options.get('composite'));
- if (target && values.length>1) {
- var canvas_width = target.pixel_width,
- canvas_height = target.pixel_height,
- radius = Math.floor(Math.min(canvas_width, canvas_height)/2),
- total = 0,
- next = 0,
- circle = 2*Math.PI;
-
- for(var i=values.length; i--;) {
- total += values[i];
- }
-
- if (options.get('offset')) {
- next += (2*Math.PI)*(options.get('offset')/360);
- }
- var vlen = values.length;
- for(i=0; i<vlen; i++) {
- var start = next;
- var end = next;
- if (total > 0) { // avoid divide by zero
- end = next + (circle*(values[i]/total));
- }
- target.drawPieSlice(radius, radius, radius, start, end, undefined, options.get('sliceColors')[i % options.get('sliceColors').length]);
- next = end;
- }
- }
- };
-
-
- /**
- * Box plots
- */
- var quartile = function(values, q) {
- if (q==2) {
- var vl2 = Math.floor(values.length/2);
- return values.length % 2 ? values[vl2] : (values[vl2]+values[vl2+1])/2;
- } else {
- var vl4 = Math.floor(values.length/4);
- return values.length % 2 ? (values[vl4*q]+values[vl4*q+1])/2 : values[vl4*q];
- }
- };
-
- $.fn.sparkline.box = function(values, options, width, height) {
- values = $.map(values, Number);
- width = options.get('width')=='auto' ? '4.0em' : width;
-
- var minvalue = options.get('chartRangeMin')===undefined ? Math.min.apply(Math, values) : options.get('chartRangeMin'),
- maxvalue = options.get('chartRangeMax')===undefined ? Math.max.apply(Math, values) : options.get('chartRangeMax'),
- target = $(this).simpledraw(width, height, options.get('composite')),
- vlen = values.length,
- lwhisker, loutlier, q1, q2, q3, rwhisker, routlier;
-
- if (target && values.length>1) {
- var canvas_width = target.pixel_width,
- canvas_height = target.pixel_height;
- if (options.get('raw')) {
- if (options.get('showOutliers') && values.length>5) {
- loutlier=values[0]; lwhisker=values[1]; q1=values[2]; q2=values[3]; q3=values[4]; rwhisker=values[5]; routlier=values[6];
- } else {
- lwhisker=values[0]; q1=values[1]; q2=values[2]; q3=values[3]; rwhisker=values[4];
- }
- } else {
- values.sort(function(a, b) { return a-b; });
- q1 = quartile(values, 1);
- q2 = quartile(values, 2);
- q3 = quartile(values, 3);
- var iqr = q3-q1;
- if (options.get('showOutliers')) {
- lwhisker=undefined; rwhisker=undefined;
- for(var i=0; i<vlen; i++) {
- if (lwhisker===undefined && values[i] > q1-(iqr*options.get('outlierIQR'))) {
- lwhisker = values[i];
- }
- if (values[i] < q3+(iqr*options.get('outlierIQR'))) {
- rwhisker = values[i];
- }
- }
- loutlier = values[0];
- routlier = values[vlen-1];
- } else {
- lwhisker = values[0];
- rwhisker = values[vlen-1];
- }
- }
-
- var unitsize = canvas_width / (maxvalue-minvalue+1),
- canvas_left = 0;
- if (options.get('showOutliers')) {
- canvas_left = Math.ceil(options.get('spotRadius'));
- canvas_width -= 2*Math.ceil(options.get('spotRadius'));
- unitsize = canvas_width / (maxvalue-minvalue+1);
- if (loutlier < lwhisker) {
- target.drawCircle((loutlier-minvalue)*unitsize+canvas_left, canvas_height/2, options.get('spotRadius'), options.get('outlierLineColor'), options.get('outlierFillColor'));
- }
- if (routlier > rwhisker) {
- target.drawCircle((routlier-minvalue)*unitsize+canvas_left, canvas_height/2, options.get('spotRadius'), options.get('outlierLineColor'), options.get('outlierFillColor'));
- }
- }
-
- // box
- target.drawRect(
- Math.round((q1-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height*0.1),
- Math.round((q3-q1)*unitsize),
- Math.round(canvas_height*0.8),
- options.get('boxLineColor'),
- options.get('boxFillColor'));
- // left whisker
- target.drawLine(
- Math.round((lwhisker-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height/2),
- Math.round((q1-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height/2),
- options.get('lineColor'));
- target.drawLine(
- Math.round((lwhisker-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height/4),
- Math.round((lwhisker-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height-canvas_height/4),
- options.get('whiskerColor'));
- // right whisker
- target.drawLine(Math.round((rwhisker-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height/2),
- Math.round((q3-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height/2),
- options.get('lineColor'));
- target.drawLine(
- Math.round((rwhisker-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height/4),
- Math.round((rwhisker-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height-canvas_height/4),
- options.get('whiskerColor'));
- // median line
- target.drawLine(
- Math.round((q2-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height*0.1),
- Math.round((q2-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height*0.9),
- options.get('medianColor'));
- if (options.get('target')) {
- var size = Math.ceil(options.get('spotRadius'));
- target.drawLine(
- Math.round((options.get('target')-minvalue)*unitsize+canvas_left),
- Math.round((canvas_height/2)-size),
- Math.round((options.get('target')-minvalue)*unitsize+canvas_left),
- Math.round((canvas_height/2)+size),
- options.get('targetColor'));
- target.drawLine(
- Math.round((options.get('target')-minvalue)*unitsize+canvas_left-size),
- Math.round(canvas_height/2),
- Math.round((options.get('target')-minvalue)*unitsize+canvas_left+size),
- Math.round(canvas_height/2),
- options.get('targetColor'));
- }
- } else {
- // Remove the tag contents if sparklines aren't supported
- this.innerHTML = '';
- }
- };
-
-
- // Setup a very simple "virtual canvas" to make drawing the few shapes we need easier
- // This is accessible as $(foo).simpledraw()
-
- if ($.browser.msie && !document.namespaces.v) {
- document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', '#default#VML');
- }
-
- if ($.browser.hasCanvas === undefined) {
- var t = document.createElement('canvas');
- $.browser.hasCanvas = t.getContext!==undefined;
- }
-
- VCanvas_base = function(width, height, target) {
- };
-
- VCanvas_base.prototype = {
- init : function(width, height, target) {
- this.width = width;
- this.height = height;
- this.target = target;
- if (target[0]) {
- target=target[0];
- }
- target.VCanvas = this;
- },
-
- drawShape : function(path, lineColor, fillColor, lineWidth) {
- alert('drawShape not implemented');
- },
-
- drawLine : function(x1, y1, x2, y2, lineColor, lineWidth) {
- return this.drawShape([ [x1,y1], [x2,y2] ], lineColor, lineWidth);
- },
-
- drawCircle : function(x, y, radius, lineColor, fillColor) {
- alert('drawCircle not implemented');
- },
-
- drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor) {
- alert('drawPieSlice not implemented');
- },
-
- drawRect : function(x, y, width, height, lineColor, fillColor) {
- alert('drawRect not implemented');
- },
-
- getElement : function() {
- return this.canvas;
- },
-
- _insert : function(el, target) {
- $(target).html(el);
- }
- };
-
- VCanvas_canvas = function(width, height, target) {
- return this.init(width, height, target);
- };
-
- VCanvas_canvas.prototype = $.extend(new VCanvas_base(), {
- _super : VCanvas_base.prototype,
-
- init : function(width, height, target) {
- this._super.init(width, height, target);
- this.canvas = document.createElement('canvas');
- if (target[0]) {
- target=target[0];
- }
- target.VCanvas = this;
- $(this.canvas).css({ display:'inline-block', width:width, height:height, verticalAlign:'top' });
- this._insert(this.canvas, target);
- this.pixel_height = $(this.canvas).height();
- this.pixel_width = $(this.canvas).width();
- this.canvas.width = this.pixel_width;
- this.canvas.height = this.pixel_height;
- $(this.canvas).css({width: this.pixel_width, height: this.pixel_height});
- },
-
- _getContext : function(lineColor, fillColor, lineWidth) {
- var context = this.canvas.getContext('2d');
- if (lineColor !== undefined) {
- context.strokeStyle = lineColor;
- }
- context.lineWidth = lineWidth===undefined ? 1 : lineWidth;
- if (fillColor !== undefined) {
- context.fillStyle = fillColor;
- }
- return context;
- },
-
- drawShape : function(path, lineColor, fillColor, lineWidth) {
- var context = this._getContext(lineColor, fillColor, lineWidth);
- context.beginPath();
- context.moveTo(path[0][0]+0.5, path[0][1]+0.5);
- for(var i=1, plen=path.length; i<plen; i++) {
- context.lineTo(path[i][0]+0.5, path[i][1]+0.5); // the 0.5 offset gives us crisp pixel-width lines
- }
- if (lineColor !== undefined) {
- context.stroke();
- }
- if (fillColor !== undefined) {
- context.fill();
- }
- },
-
- drawCircle : function(x, y, radius, lineColor, fillColor) {
- var context = this._getContext(lineColor, fillColor);
- context.beginPath();
- context.arc(x, y, radius, 0, 2*Math.PI, false);
- if (lineColor !== undefined) {
- context.stroke();
- }
- if (fillColor !== undefined) {
- context.fill();
- }
- },
-
- drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor) {
- var context = this._getContext(lineColor, fillColor);
- context.beginPath();
- context.moveTo(x, y);
- context.arc(x, y, radius, startAngle, endAngle, false);
- context.lineTo(x, y);
- context.closePath();
- if (lineColor !== undefined) {
- context.stroke();
- }
- if (fillColor) {
- context.fill();
- }
- },
-
- drawRect : function(x, y, width, height, lineColor, fillColor) {
- return this.drawShape([ [x,y], [x+width, y], [x+width, y+height], [x, y+height], [x, y] ], lineColor, fillColor);
- }
-
- });
-
- VCanvas_vml = function(width, height, target) {
- return this.init(width, height, target);
- };
-
- VCanvas_vml.prototype = $.extend(new VCanvas_base(), {
- _super : VCanvas_base.prototype,
-
- init : function(width, height, target) {
- this._super.init(width, height, target);
- if (target[0]) {
- target=target[0];
- }
- target.VCanvas = this;
- this.canvas = document.createElement('span');
- $(this.canvas).css({ display:'inline-block', position: 'relative', overflow:'hidden', width:width, height:height, margin:'0px', padding:'0px', verticalAlign: 'top'});
- this._insert(this.canvas, target);
- this.pixel_height = $(this.canvas).height();
- this.pixel_width = $(this.canvas).width();
- this.canvas.width = this.pixel_width;
- this.canvas.height = this.pixel_height;
- var groupel = '<v:group coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'"' +
- ' style="position:absolute;top:0;left:0;width:'+this.pixel_width+'px;height='+this.pixel_height+'px;"></v:group>';
- this.canvas.insertAdjacentHTML('beforeEnd', groupel);
- this.group = $(this.canvas).children()[0];
- },
-
- drawShape : function(path, lineColor, fillColor, lineWidth) {
- var vpath = [];
- for(var i=0, plen=path.length; i<plen; i++) {
- vpath[i] = ''+(path[i][0])+','+(path[i][1]);
- }
- var initial = vpath.splice(0,1);
- lineWidth = lineWidth === undefined ? 1 : lineWidth;
- var stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="'+lineWidth+'" strokeColor="'+lineColor+'" ';
- var fill = fillColor === undefined ? ' filled="false"' : ' fillColor="'+fillColor+'" filled="true" ';
- var closed = vpath[0] == vpath[vpath.length-1] ? 'x ' : '';
- var vel = '<v:shape coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'" ' +
- stroke +
- fill +
- ' style="position:absolute;left:0px;top:0px;height:'+this.pixel_height+'px;width:'+this.pixel_width+'px;padding:0px;margin:0px;" ' +
- ' path="m '+initial+' l '+vpath.join(', ')+' '+closed+'e">' +
- ' </v:shape>';
- this.group.insertAdjacentHTML('beforeEnd', vel);
- },
-
- drawCircle : function(x, y, radius, lineColor, fillColor) {
- x -= radius+1;
- y -= radius+1;
- var stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="1" strokeColor="'+lineColor+'" ';
- var fill = fillColor === undefined ? ' filled="false"' : ' fillColor="'+fillColor+'" filled="true" ';
- var vel = '<v:oval ' +
- stroke +
- fill +
- ' style="position:absolute;top:'+y+'px; left:'+x+'px; width:'+(radius*2)+'px; height:'+(radius*2)+'px"></v:oval>';
- this.group.insertAdjacentHTML('beforeEnd', vel);
-
- },
-
- drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor) {
- if (startAngle == endAngle) {
- return; // VML seems to have problem when start angle equals end angle.
- }
- if ((endAngle - startAngle) == (2*Math.PI)) {
- startAngle = 0.0; // VML seems to have a problem when drawing a full circle that doesn't start 0
- endAngle = (2*Math.PI);
- }
-
- var startx = x + Math.round(Math.cos(startAngle) * radius);
- var starty = y + Math.round(Math.sin(startAngle) * radius);
- var endx = x + Math.round(Math.cos(endAngle) * radius);
- var endy = y + Math.round(Math.sin(endAngle) * radius);
-
- // Prevent very small slices from being mistaken as a whole pie
- if (startx==endx && starty==endy && (endAngle-startAngle) < Math.PI) {
- return;
- }
-
- var vpath = [ x-radius, y-radius, x+radius, y+radius, startx, starty, endx, endy ];
- var stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="1" strokeColor="'+lineColor+'" ';
- var fill = fillColor === undefined ? ' filled="false"' : ' fillColor="'+fillColor+'" filled="true" ';
- var vel = '<v:shape coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'" ' +
- stroke +
- fill +
- ' style="position:absolute;left:0px;top:0px;height:'+this.pixel_height+'px;width:'+this.pixel_width+'px;padding:0px;margin:0px;" ' +
- ' path="m '+x+','+y+' wa '+vpath.join(', ')+' x e">' +
- ' </v:shape>';
- this.group.insertAdjacentHTML('beforeEnd', vel);
- },
-
- drawRect : function(x, y, width, height, lineColor, fillColor) {
- return this.drawShape( [ [x, y], [x, y+height], [x+width, y+height], [x+width, y], [x, y] ], lineColor, fillColor);
- }
- });
-
-})(jQuery);
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-2.0.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-2.0.min.js
new file mode 100644
index 0000000..ea174b6
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-2.0.min.js
@@ -0,0 +1,5 @@
+/* jquery.sparkline 2.0 - http://omnipotent.net/jquery.sparkline/
+** Licensed under the New BSD License - see above site for details */
+
+(function(a){"use strict";var b={},c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I=0;c=function(){return{common:{type:"line",lineColor:"#00f",fillColor:"#cdf",defaultPixelsPerValue:3,width:"auto",height:"auto",composite:!1,tagValuesAttribute:"values",tagOptionsPrefix:"spark",enableTagOptions:!1,enableHighlight:!0,highlightLighten:1.4,tooltipSkipNull:!0,tooltipPrefix:"",tooltipSuffix:"",disableHiddenCheck:!1,numberFormatter:!1,numberDigitGroupCount:3,numberDigitGroupSep:",",numberDecimalMark:".",disableTooltips:!1,disableInteraction:!1},line:{spotColor:"#f80",highlightSpotColor:"#5f5",highlightLineColor:"#f22",spotRadius:1.5,minSpotColor:"#f80",maxSpotColor:"#f80",lineWidth:1,normalRangeMin:undefined,normalRangeMax:undefined,normalRangeColor:"#ccc",drawNormalOnTop:!1,chartRangeMin:undefined,chartRangeMax:undefined,chartRangeMinX:undefined,chartRangeMaxX:undefined,tooltipFormat:new e('<span style="color: {{color}}">●</span> {{prefix}}{{y}}{{suffix}}')},
bar:{barColor:"#3366cc",negBarColor:"#f44",stackedBarColor:["#3366cc","#dc3912","#ff9900","#109618","#66aa00","#dd4477","#0099c6","#990099"],zeroColor:undefined,nullColor:undefined,zeroAxis:!0,barWidth:4,barSpacing:1,chartRangeMax:undefined,chartRangeMin:undefined,chartRangeClip:!1,colorMap:undefined,tooltipFormat:new e('<span style="color: {{color}}">●</span> {{prefix}}{{value}}{{suffix}}')},tristate:{barWidth:4,barSpacing:1,posBarColor:"#6f6",negBarColor:"#f44",zeroBarColor:"#999",colorMap:{},tooltipFormat:new e('<span style="color: {{color}}">●</span> {{value:map}}'),tooltipValueLookups:{map:{"-1":"Loss",0:"Draw",1:"Win"}}},discrete:{lineHeight:"auto",thresholdColor:undefined,thresholdValue:0,chartRangeMax:undefined,chartRangeMin:undefined,chartRangeClip:!1,tooltipFormat:new e("{{prefix}}{{value}}{{suffix}}")},bullet:{targetColor:"#f33",targetWidth:3,performanceColor:"#33f",rangeColors:["#d3dafe","#a8b6ff","#7f94ff"],base:undefined,tooltipFormat:new e("{{field
key:fields}} - {{value}}"),tooltipValueLookups:{fields:{r:"Range",p:"Performance",t:"Target"}}},pie:{offset:0,sliceColors:["#3366cc","#dc3912","#ff9900","#109618","#66aa00","#dd4477","#0099c6","#990099"],borderWidth:0,borderColor:"#000",tooltipFormat:new e('<span style="color: {{color}}">●</span> {{value}} ({{percent.1}}%)')},box:{raw:!1,boxLineColor:"#000",boxFillColor:"#cdf",whiskerColor:"#000",outlierLineColor:"#333",outlierFillColor:"#fff",medianColor:"#f00",showOutliers:!0,outlierIQR:1.5,spotRadius:1.5,target:undefined,targetColor:"#4a2",chartRangeMax:undefined,chartRangeMin:undefined,tooltipFormat:new e("{{field:fields}}: {{value}}"),tooltipFormatFieldlistKey:"field",tooltipValueLookups:{fields:{lq:"Lower Quartile",med:"Median",uq:"Upper Quartile",lo:"Left Outlier",ro:"Right Outlier",lw:"Left Whisker",rw:"Right Whisker"}}}}},B='.jqstooltip { position: absolute;left: 0px;top: 0px;visibility: hidden;background: rgb(0, 0, 0) transparent;background-color: rgba(0,0,0,
0.6);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";color: white;font: 10px arial, san serif;text-align: left;white-space: nowrap;padding: 5px;border: 1px solid white;}.jqsfield { color: white;font: 10px arial, san serif;text-align: left;}',C=function(){n(B)},a(C),d=function(){var b,c;return b=function(){this.init.apply(this,arguments)},arguments.length>1?(arguments[0]?(b.prototype=a.extend(new arguments[0],arguments[arguments.length-1]),b._super=arguments[0].prototype):b.prototype=arguments[arguments.length-1],arguments.length>2&&(c=Array.prototype.slice.call(arguments,1,-1),c.unshift(b.prototype),a.extend.apply(a,c))):b.prototype=arguments[0],b.prototype.cls=b,b},a.SPFormatClass=e=d({fre:/\{\{([\w.]+?)(:(.+?))?\}\}/g,precre:/(\w+)\.(\d+)/,init:function(a,b){this.format=a,this.fclass=b},render:function(a,b,c){var d=this,
e=a,f,g,h,i,j;return this.format.replace(this.fre,function(){var a;return g=arguments[1],h=arguments[3],f=d.precre.exec(g),f?(j=f[2],g=f[1]):j=!1,i=e[g],i===undefined?"":h&&b&&b[h]?(a=b[h],a.get?b[h].get(i)||i:b[h][i]||i):(k(i)&&(c.get("numberFormatter")?i=c.get("numberFormatter")(i):i=p(i,j,c.get("numberDigitGroupCount"),c.get("numberDigitGroupSep"),c.get("numberDecimalMark"))),i)})}}),a.spformat=function(a,b){return new e(a,b)},f=function(a,b,c){return a<b?b:a>c?c:a},g=function(a,b){var c;return b===2?(c=Math.floor(a.length/2),a.length%2?a[c]:(a[c]+a[c+1])/2):(c=Math.floor(a.length/4),a.length%2?(a[c*b]+a[c*b+1])/2:a[c*b])},h=function(a){var b;switch(a){case"undefined":a=undefined;break;case"null":a=null;break;case"true":a=!0;break;case"false":a=!1;break;default:b=parseFloat(a),a==b&&(a=b)}return a},i=function(a){var b,c=[];for(b=a.length;b--;)c[b]=h(a[b]);return c},j=function(a,b){var c,d,e=[];for(c=0,d=a.length;c<d;c++)a[c]!==b&&e.push(a[c]);return e},k=function(a){retur
n!isNaN(parseFloat(a))&&isFinite(a)},p=function(b,c,d,e,f){var g,h;b=(c===!1?parseFloat(b).toString():b.toFixed(c)).split(""),g=(g=a.inArray(".",b))<0?b.length:g,g<b.length&&(b[g]=f);for(h=g-d;h>0;h-=d)b.splice(h,0,e);return b.join("")},l=function(a,b,c){var d;for(d=b.length;d--;)if(b[d]!==a||!c&&a===null)return!1;return!0},m=function(a){var b=0,c;for(c=a.length;c--;)b+=typeof a[c]=="number"?a[c]:0;return b},o=function(b){return a.isArray(b)?b:[b]},n=function(a){var b;document.createStyleSheet?document.createStyleSheet().cssText=a:(b=document.createElement("style"),b.type="text/css",document.getElementsByTagName("head")[0].appendChild(b),b[typeof document.body.style.WebkitAppearance=="string"?"innerText":"innerHTML"]=a)},a.fn.simpledraw=function(b,c,d,e){var f,g;if(d&&(f=this.data("_jqs_vcanvas")))return f;b===undefined&&(b=a(this).innerWidth()),c===undefined&&(c=a(this).innerHeight());if(a.browser.hasCanvas)f=new F(b,c,this,e);else{if(!a.browser.msie)return!1;f=new G(b,c,th
is)}return g=a(this).data("_jqs_mhandler"),g&&g.registerCanvas(f),f},a.fn.cleardraw=function(){var a=this.data("_jqs_vcanvas");a&&a.reset()},a.RangeMapClass=q=d({init:function(a){var b,c,d=[];for(b in a)a.hasOwnProperty(b)&&typeof b=="string"&&b.indexOf(":")>-1&&(c=b.split(":"),c[0]=c[0].length===0?-Infinity:parseFloat(c[0]),c[1]=c[1].length===0?Infinity:parseFloat(c[1]),c[2]=a[b],d.push(c));this.map=a,this.rangelist=d||!1},get:function(a){var b=this.rangelist,c,d,e;if((e=this.map[a])!==undefined)return e;if(b)for(c=b.length;c--;){d=b[c];if(d[0]<=a&&d[1]>=a)return d[2]}return undefined}}),a.range_map=function(a){return new q(a)},r=d({init:function(b,c){var d=a(b);this.$el=d,this.options=c,this.currentPageX=0,this.currentPageY=0,this.el=b,this.splist=[],this.tooltip=null,this.over=!1,this.displayTooltips=!c.get("disableTooltips"),this.highlightEnabled=!c.get("disableHighlight")},registerSparkline:function(a){this.splist.push(a),this.over&&this.updateDisplay()},registerCanvas:
function(b){var c=a(b.canvas);this.canvas=b,this.$canvas=c,c.mouseenter(a.proxy(this.mouseenter,this)),c.mouseleave(a.proxy(this.mouseleave,this)),c.click(a.proxy(this.mouseclick,this))},reset:function(a){this.splist=[],this.tooltip&&a&&(this.tooltip.remove(),this.tooltip=undefined)},mouseclick:function(b){var c=a.Event("sparklineClick");c.originalEvent=b,c.sparklines=this.splist,this.$el.trigger(c)},mouseenter:function(b){a(document.body).unbind("mousemove.jqs"),a(document.body).bind("mousemove.jqs",a.proxy(this.mousemove,this)),this.over=!0,this.currentPageX=b.pageX,this.currentPageY=b.pageY,this.currentEl=b.target,!this.tooltip&&this.displayTooltips&&(this.tooltip=new s(this.options),this.tooltip.updatePosition(b.pageX,b.pageY)),this.updateDisplay()},mouseleave:function(){a(document.body).unbind("mousemove.jqs");var b=this.splist,c=b.length,d=!1,e,f;this.over=!1,this.currentEl=null,this.tooltip&&(this.tooltip.remove(),this.tooltip=null);for(f=0;f<c;f++)e=b[f],e.clearRegio
nHighlight()&&(d=!0);d&&this.canvas.render()},mousemove:function(a){this.currentPageX=a.pageX,this.currentPageY=a.pageY,this.currentEl=a.target,this.tooltip&&this.tooltip.updatePosition(a.pageX,a.pageY),this.updateDisplay()},updateDisplay:function(){var b=this.splist,c=b.length,d=!1,e=this.$canvas.offset(),f=this.currentPageX-e.left,g=this.currentPageY-e.top,h,i,j,k,l;if(!this.over)return;for(j=0;j<c;j++)i=b[j],k=i.setRegionHighlight(this.currentEl,f,g),k&&(d=!0);if(d){l=a.Event("sparklineRegionChange"),l.sparklines=this.splist,this.$el.trigger(l);if(this.tooltip){h="";for(j=0;j<c;j++)i=b[j],h+=i.getCurrentRegionTooltip();this.tooltip.setContent(h)}this.disableHighlight||this.canvas.render()}k===null&&this.mouseleave()}}),s=d({sizeStyle:"position: static !important;display: block !important;visibility: hidden !important;float: left !important;",init:function(b){var c=b.get("tooltipClassname","jqstooltip"),d=this.sizeStyle,e;this.container=b.get("tooltipContainer")||document.
body,this.tooltipOffsetX=b.get("tooltipOffsetX",10),this.tooltipOffsetY=b.get("tooltipOffsetY",12),a("#jqssizetip").remove(),a("#jqstooltip").remove(),this.sizetip=a("<div/>",{id:"jqssizetip",style:d,"class":c}),this.tooltip=a("<div/>",{id:"jqstooltip","class":c}).appendTo(this.container),e=this.tooltip.offset(),this.offsetLeft=e.left,this.offsetTop=e.top,this.hidden=!0,a(window).unbind("resize.jqs scroll.jqs"),a(window).bind("resize.jqs scroll.jqs",a.proxy(this.updateWindowDims,this)),this.updateWindowDims()},updateWindowDims:function(){this.scrollTop=a(window).scrollTop(),this.scrollLeft=a(window).scrollLeft(),this.scrollRight=this.scrollLeft+a(window).width(),this.updatePosition()},getSize:function(a){this.sizetip.html(a).appendTo(this.container),this.width=this.sizetip.width()+1,this.height=this.sizetip.height(),this.sizetip.remove()},setContent:function(a){if(!a){this.tooltip.css("visibility","hidden"),this.hidden=!0;return}this.getSize(a),this.tooltip.html(a).css({widt
h:this.width,height:this.height,visibility:"visible"}),this.hidden&&(this.hidden=!1,this.updatePosition())},updatePosition:function(a,b){if(a===undefined){if(this.mousex===undefined)return;a=this.mousex-this.offsetLeft,b=this.mousey-this.offsetTop}else this.mousex=a-=this.offsetLeft,this.mousey=b-=this.offsetTop;if(!this.height||!this.width||this.hidden)return;b-=this.height+this.tooltipOffsetY,a+=this.tooltipOffsetX,b<this.scrollTop&&(b=this.scrollTop),a<this.scrollLeft?a=this.scrollLeft:a+this.width>this.scrollRight&&(a=this.scrollRight-this.width),this.tooltip.css({left:a,top:b})},remove:function(){this.tooltip.remove(),this.sizetip.remove(),this.sizetip=this.tooltip=undefined,a(window).unbind("resize.jqs scroll.jqs")}}),H=[],a.fn.sparkline=function(b,c){return this.each(function(){var d=new a.fn.sparkline.options(this,c),e=a(this),f,g;f=function(){var c,f,g,h,i,j,k;if(b==="html"||b===undefined){k=this.getAttribute(d.get("tagValuesAttribute"));if(k===undefined||k===null)k
=e.html();c=k.replace(/(^\s*<!--)|(-->\s*$)|\s+/g,"").split(",")}else c=b;f=d.get("width")==="auto"?c.length*d.get("defaultPixelsPerValue"):d.get("width");if(d.get("height")==="auto"){if(!d.get("composite")||!a.data(this,"_jqs_vcanvas"))h=document.createElement("span"),h.innerHTML="a",e.html(h),g=a(h).innerHeight()||a(h).height(),a(h).remove(),h=null}else g=d.get("height");d.get("disableInteraction")?i=!1:(i=a.data(this,"_jqs_mhandler"),i?d.get("composite")||i.reset():(i=new r(this,d),a.data(this,"_jqs_mhandler",i)));if(d.get("composite")&&!a.data(this,"_jqs_vcanvas")){a.data(this,"_jqs_errnotify")||(alert("Attempted to attach a composite sparkline to an element with no existing sparkline"),a.data(this,"_jqs_errnotify",!0));return}j=new(a.fn.sparkline[d.get("type")])(this,c,d,f,g),j.render(),i&&i.registerSparkline(j)};if(a(this).html()&&!d.get("disableHiddenCheck")&&a(this).is(":hidden")||a.fn.jquery<"1.3.0"&&a(this).parents().is(":hidden")||!a(this).parents("body").length){
if(!d.get("composite")&&a.data(this,"_jqs_pending"))for(g=H.length;g;g--)H[g-1][0]==this&&H.splice(g-1,1);H.push([this,f]),a.data(this,"_jqs_pending",!0)}else f.call(this)})},a.fn.sparkline.defaults=c(),a.sparkline_display_visible=function(){var b,c,d,e=[];for(c=0,d=H.length;c<d;c++)b=H[c][0],a(b).is(":visible")&&!a(b).parents().is(":hidden")?(H[c][1].call(b),a.data(H[c][0],"_jqs_pending",!1),e.push(c)):!a(b).closest("html").length&&!a.data(b,"_jqs_pending")&&(a.data(H[c][0],"_jqs_pending",!1),e.push(c));for(c=e.length;c;c--)H.splice(e[c-1],1)},a.fn.sparkline.options=d({init:function(c,d){var e,f,g,h;this.userOptions=d=d||{},this.tag=c,this.tagValCache={},f=a.fn.sparkline.defaults,g=f.common,this.tagOptionsPrefix=d.enableTagOptions&&(d.tagOptionsPrefix||g.tagOptionsPrefix),h=this.getTagSetting("type"),h===b?e=f[d.type||g.type]:e=f[h],this.mergedOptions=a.extend({},g,e,d)},getTagSetting:function(a){var c=this.tagOptionsPrefix,d,e,f,g;if(c===!1||c===undefined)return b;if(this.
tagValCache.hasOwnProperty(a))d=this.tagValCache.key;else{d=this.tag.getAttribute(c+a);if(d===undefined||d===null)d=b;else if(d.substr(0,1)==="["){d=d.substr(1,d.length-2).split(",");for(e=d.length;e--;)d[e]=h(d[e].replace(/(^\s*)|(\s*$)/g,""))}else if(d.substr(0,1)==="{"){f=d.substr(1,d.length-2).split(","),d={};for(e=f.length;e--;)g=f[e].split(":",2),d[g[0].replace(/(^\s*)|(\s*$)/g,"")]=h(g[1].replace(/(^\s*)|(\s*$)/g,""))}else d=h(d);this.tagValCache.key=d}return d},get:function(a,c){var d=this.getTagSetting(a),e;return d!==b?d:(e=this.mergedOptions[a])===undefined?c:e}}),a.fn.sparkline._base=d({disabled:!1,init:function(b,c,d,e,f){this.el=b,this.$el=a(b),this.values=c,this.options=d,this.width=e,this.height=f,this.currentRegion=undefined},initTarget:function(){var a=!this.options.get("disableInteraction");(this.target=this.$el.simpledraw(this.width,this.height,this.options.get("composite"),a))?(this.canvasWidth=this.target.pixelWidth,this.canvasHeight=this.target.pixelHe
ight):this.disabled=!0},render:function(){return this.disabled?(this.el.innerHTML="",!1):!0},getRegion:function(a,b){},setRegionHighlight:function(a,b,c){var d=this.currentRegion,e=!this.options.get("disableHighlight"),f;return b>this.canvasWidth||c>this.canvasHeight||b<0||c<0?null:(f=this.getRegion(a,b,c),d!==f?(d!==undefined&&e&&this.removeHighlight(),this.currentRegion=f,f!==undefined&&e&&this.renderHighlight(),!0):!1)},clearRegionHighlight:function(){return this.currentRegion!==undefined?(this.removeHighlight(),this.currentRegion=undefined,!0):!1},renderHighlight:function(){this.changeHighlight(!0)},removeHighlight:function(){this.changeHighlight(!1)},changeHighlight:function(a){},getCurrentRegionTooltip:function(){var b=this.options,c="",d=[],f,g,h,i,j,k,l,m,n,o,p,q,r,s;if(this.currentRegion===undefined)return"";f=this.getCurrentRegionFields(),p=b.get("tooltipFormatter");if(p)return p(this,b,f);b.get("tooltipChartTitle")&&(c+='<div class="jqs jqstitle">'+b.get("tooltipC
hartTitle")+"</div>\n"),g=this.options.get("tooltipFormat");if(!g)return"";a.isArray(g)||(g=[g]),a.isArray(f)||(f=[f]),l=this.options.get("tooltipFormatFieldlist"),m=this.options.get("tooltipFormatFieldlistKey");if(l&&m){n=[];for(k=f.length;k--;)o=f[k][m],(s=a.inArray(o,l))!=-1&&(n[s]=f[k]);f=n}h=g.length,r=f.length;for(k=0;k<h;k++){q=g[k],typeof q=="string"&&(q=new e(q)),i=q.fclass||"jqsfield";for(s=0;s<r;s++)if(!f[s].isNull||!b.get("tooltipSkipNull"))a.extend(f[s],{prefix:b.get("tooltipPrefix"),suffix:b.get("tooltipSuffix")}),j=q.render(f[s],b.get("tooltipValueLookups"),b),d.push('<div class="'+i+'">'+j+"</div>")}return d.length?c+d.join("\n"):""},getCurrentRegionFields:function(){},calcHighlightColor:function(a,b){var c=b.get("highlightColor"),d=b.get("highlightLighten"),e,g,h,i;if(c)return c;if(d){e=/^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(a)||/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(a);if(e){h=[],g=a.length===4?16:1;for(i=0;i<3;i++)h[i]=f(Math.round(parseInt(
e[i+1],16)*g*d),0,255);return"rgb("+h.join(",")+")"}}return a}}),t={changeHighlight:function(b){var c=this.currentRegion,d=this.target,e=this.regionShapes[c],f;e&&(f=this.renderRegion(c,b),a.isArray(f)||a.isArray(e)?(d.replaceWithShapes(e,f),this.regionShapes[c]=a.map(f,function(a){return a.id})):(d.replaceWithShape(e,f),this.regionShapes[c]=f.id))},render:function(){var b=this.values,c=this.target,d=this.regionShapes,e,f,g,h;if(!this.cls._super.render.call(this))return;for(g=b.length;g--;){e=this.renderRegion(g);if(e)if(a.isArray(e)){f=[];for(h=e.length;h--;)e[h].append(),f.push(e[h].id);d[g]=f}else e.append(),d[g]=e.id;else d[g]=null}c.render()}},a.fn.sparkline.line=u=d(a.fn.sparkline._base,{type:"line",init:function(a,b,c,d,e){u._super.init.call(this,a,b,c,d,e),this.vertices=[],this.regionMap=[],this.xvalues=[],this.yvalues=[],this.yminmax=[],this.hightlightSpotId=null,this.lastShapeId=null,this.initTarget()},getRegion:function(a,b,c){var d,e=this.regionMap;for(d=e.length
;d--;)if(e[d]!==null&&b>=e[d][0]&&b<=e[d][1])return e[d][2];return undefined},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.yvalues[a]===null,x:this.xvalues[a],y:this.yvalues[a],color:this.options.get("lineColor"),fillColor:this.options.get("fillColor"),offset:a}},renderHighlight:function(){var a=this.currentRegion,b=this.target,c=this.vertices[a],d=this.options,e=d.get("spotRadius"),f=d.get("highlightSpotColor"),g=d.get("highlightLineColor"),h,i;if(!c)return;e&&f&&(h=b.drawCircle(c[0],c[1],e,undefined,f),this.highlightSpotId=h.id,b.insertAfterShape(this.lastShapeId,h)),g&&(i=b.drawLine(c[0],this.canvasTop,c[0],this.canvasTop+this.canvasHeight,g),this.highlightLineId=i.id,b.insertAfterShape(this.lastShapeId,i))},removeHighlight:function(){var a=this.target;this.highlightSpotId&&(a.removeShapeId(this.highlightSpotId),this.highlightSpotId=null),this.highlightLineId&&(a.removeShapeId(this.highlightLineId),this.highlightLineId=null)},scanValues:fu
nction(){var a=this.values,b=a.length,c=this.xvalues,d=this.yvalues,e=this.yminmax,f,g,h,i,j;for(f=0;f<b;f++)g=a[f],h=typeof a[f]=="string",i=typeof a[f]=="object"&&a[f]instanceof Array,j=h&&a[f].split(":"),h&&j.length===2?(c.push(Number(j[0])),d.push(Number(j[1])),e.push(Number(j[1]))):i?(c.push(g[0]),d.push(g[1]),e.push(g[1])):(c.push(f),a[f]===null||a[f]==="null"?d.push(null):(d.push(Number(g)),e.push(Number(g))));this.options.get("xvalues")&&(c=this.options.get("xvalues")),this.maxy=this.maxyorg=Math.max.apply(Math,e),this.miny=this.minyorg=Math.min.apply(Math,e),this.maxx=Math.max.apply(Math,c),this.minx=Math.min.apply(Math,c),this.xvalues=c,this.yvalues=d,this.yminmax=e},processRangeOptions:function(){var a=this.options,b=a.get("normalRangeMin"),c=a.get("normalRangeMax");b!==undefined&&(b<this.miny&&(this.miny=b),c>this.maxy&&(this.maxy=c)),a.get("chartRangeMin")!==undefined&&(a.get("chartRangeClip")||a.get("chartRangeMin")<this.miny)&&(this.miny=a.get("chartRangeMin")
),a.get("chartRangeMax")!==undefined&&(a.get("chartRangeClip")||a.get("chartRangeMax")>this.maxy)&&(this.maxy=a.get("chartRangeMax")),a.get("chartRangeMinX")!==undefined&&(a.get("chartRangeClipX")||a.get("chartRangeMinX")<this.minx)&&(this.minx=a.get("chartRangeMinX")),a.get("chartRangeMaxX")!==undefined&&(a.get("chartRangeClipX")||a.get("chartRangeMaxX")>this.maxx)&&(this.maxx=a.get("chartRangeMaxX"))},drawNormalRange:function(a,b,c,d,e){var f=this.options.get("normalRangeMin"),g=this.options.get("normalRangeMax"),h=b+Math.round(c-c*((g-this.miny)/e)),i=Math.round(c*(g-f)/e);this.target.drawRect(a,h,d,i,undefined,this.options.get("normalRangeColor")).append()},render:function(){var b=this.options,c=this.target,d=this.canvasWidth,e=this.canvasHeight,f=this.vertices,g=b.get("spotRadius"),h=this.regionMap,i,j,k,l,m,n,o,p,r,s,t,v,w,x,y,z,A,B,C,D,E,F,G,H;if(!u._super.render.call(this))return;this.scanValues(),this.processRangeOptions(),F=this.xvalues,G=this.yvalues;if(!this.ymin
max.length||this.yvalues.length<2)return;l=m=0,i=this.maxx-this.minx===0?1:this.maxx-this.minx,j=this.maxy-this.miny===0?1:this.maxy-this.miny,k=this.yvalues.length-1,g&&(d<g*4||e<g*4)&&(g=0);if(g){if(b.get("minSpotColor")||b.get("spotColor")&&G[k]===this.miny)e-=Math.ceil(g);if(b.get("maxSpotColor")||b.get("spotColor")&&G[k]===this.maxy)e-=Math.ceil(g),l+=Math.ceil(g);(b.get("minSpotColor")||b.get("maxSpotColor"))&&(G[0]===this.miny||G[0]===this.maxy)&&(m+=Math.ceil(g),d-=Math.ceil(g));if(b.get("spotColor")||b.get("minSpotColor")||b.get("maxSpotColor")&&(G[k]===this.miny||G[k]===this.maxy))d-=Math.ceil(g)}e--,b.get("normalRangeMin")&&!b.get("drawNormalOnTop")&&this.drawNormalRange(m,l,e,d,j),o=[],p=[o],x=y=null,z=G.length;for(H=0;H<z;H++)r=F[H],t=F[H+1],s=G[H],v=m+Math.round((r-this.minx)*(d/i)),w=H<z-1?m+Math.round((t-this.minx)*(d/i)):d,y=v+(w-v)/2,h[H]=[x||0,y,H],x=y,s===null?H&&G[H-1]!==null&&(o=[],p.push(o),f.push(null)):(s<this.miny&&(s=this.miny),s>this.maxy&&(s=this
.maxy),o.length||o.push([v,l+e]),n=[v,l+Math.round(e-e*((s-this.miny)/j))],o.push(n),f.push(n));A=[],B=[],C=p.length;for(H=0;H<C;H++)o=p[H],o.length&&(b.get("fillColor")&&(o.push([o[o.length-1][0],l+e]),B.push(o.slice(0)),o.pop()),o.length>2&&(o[0]=[o[0][0],o[1][1]]),A.push(o));C=B.length;for(H=0;H<C;H++)c.drawShape(B[H],b.get("fillColor"),b.get("fillColor")).append();b.get("normalRangeMin")&&b.get("drawNormalOnTop")&&this.drawNormalRange(m,l,e,d,j),C=A.length;for(H=0;H<C;H++)c.drawShape(A[H],b.get("lineColor"),undefined,b.get("lineWidth")).append();if(g&&b.get("valueSpots")){D=b.get("valueSpots"),D.get===undefined&&(D=new q(D));for(H=0;H<z;H++)E=D.get(G[H]),E&&c.drawCircle(m+Math.round((F[H]-this.minx)*(d/i)),l+Math.round(e-e*((G[H]-this.miny)/j)),g,undefined,E).append()}g&&b.get("spotColor")&&c.drawCircle(m+Math.round((F[F.length-1]-this.minx)*(d/i)),l+Math.round(e-e*((G[k]-this.miny)/j)),g,undefined,b.get("spotColor")).append(),this.maxy!==this.minyorg&&(g&&b.get("minSpot
Color")&&(r=F[a.inArray(this.minyorg,G)],c.drawCircle(m+Math.round((r-this.minx)*(d/i)),l+Math.round(e-e*((this.minyorg-this.miny)/j)),g,undefined,b.get("minSpotColor")).append()),g&&b.get("maxSpotColor")&&(r=F[a.inArray(this.maxyorg,G)],c.drawCircle(m+Math.round((r-this.minx)*(d/i)),l+Math.round(e-e*((this.maxyorg-this.miny)/j)),g,undefined,b.get("maxSpotColor")).append())),this.lastShapeId=c.getLastShapeId(),this.canvasTop=l,c.render()}}),a.fn.sparkline.bar=v=d(a.fn.sparkline._base,t,{type:"bar",init:function(b,c,d,e,g){var k=parseInt(d.get("barWidth"),10),l=parseInt(d.get("barSpacing"),10),m=d.get("chartRangeMin"),n=d.get("chartRangeMax"),o=d.get("chartRangeClip"),p=Infinity,r=-Infinity,s,t,u,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P;v._super.init.call(this,b,c,d,e,g);for(y=0,z=c.length;y<z;y++){M=c[y],s=typeof M=="string"&&M.indexOf(":")>-1;if(s||a.isArray(M))H=!0,s&&(M=c[y]=i(M.split(":"))),M=j(M,null),t=Math.min.apply(Math,M),u=Math.max.apply(Math,M),t<p&&(p=t),u>r&&(r=u
)}this.stacked=H,this.regionShapes={},this.barWidth=k,this.barSpacing=l,this.totalBarWidth=k+l,this.width=e=c.length*k+(c.length-1)*l,this.initTarget(),o&&(F=m===undefined?-Infinity:m,G=n===undefined?Infinity:n),x=[],w=H?[]:x;var Q=[],R=[];for(y=0,z=c.length;y<z;y++)if(H){I=c[y],c[y]=L=[],Q[y]=0,w[y]=R[y]=0;for(J=0,K=I.length;J<K;J++)M=L[J]=o?f(I[J],F,G):I[J],M!==null&&(M>0&&(Q[y]+=M),p<0&&r>0?M<0?R[y]+=Math.abs(M):w[y]+=M:w[y]+=Math.abs(M-(M<0?r:p)),x.push(M))}else M=o?f(c[y],F,G):c[y],M=c[y]=h(M),M!==null&&x.push(M);this.max=E=Math.max.apply(Math,x),this.min=D=Math.min.apply(Math,x),this.stackMax=r=H?Math.max.apply(Math,Q):E,this.stackMin=p=H?Math.min.apply(Math,x):D,d.get("chartRangeMin")!==undefined&&(d.get("chartRangeClip")||d.get("chartRangeMin")<D)&&(D=d.get("chartRangeMin")),d.get("chartRangeMax")!==undefined&&(d.get("chartRangeClip")||d.get("chartRangeMax")>E)&&(E=d.get("chartRangeMax")),this.zeroAxis=B=d.get("zeroAxis",!0),D<=0&&E>=0&&B?C=0:B==0?C=D:D>0?C=D:C=E,thi
s.xaxisOffset=C,A=H?Math.max.apply(Math,w)+Math.max.apply(Math,R):E-D,this.canvasHeightEf=B&&D<0?this.canvasHeight-2:this.canvasHeight-1,D<C?(O=H&&E>=0?r:E,N=(O-C)/A*this.canvasHeight,N!==Math.ceil(N)&&(this.canvasHeightEf-=2,N=Math.ceil(N))):N=this.canvasHeight,this.yoffset=N,a.isArray(d.get("colorMap"))?(this.colorMapByIndex=d.get("colorMap"),this.colorMapByValue=null):(this.colorMapByIndex=null,this.colorMapByValue=d.get("colorMap"),this.colorMapByValue&&this.colorMapByValue.get===undefined&&(this.colorMapByValue=new q(this.colorMapByValue))),this.range=A},getRegion:function(a,b,c){var d=Math.floor(b/this.totalBarWidth);return d<0||d>=this.values.length?undefined:d},getCurrentRegionFields:function(){var a=this.currentRegion,b=o(this.values[a]),c=[],d,e;for(e=b.length;e--;)d=b[e],c.push({isNull:d===null,value:d,color:this.calcColor(e,d,a),offset:a});return c},calcColor:function(b,c,d){var e=this.colorMapByIndex,f=this.colorMapByValue,g=this.options,h,i;return this.stacked?
h=g.get("stackedBarColor"):h=c<0?g.get("negBarColor"):g.get("barColor"),c===0&&g.get("zeroColor")!==undefined&&(h=g.get("zeroColor")),f&&(i=f.get(c))?h=i:e&&e.length>d&&(h=e[d]),a.isArray(h)?h[b%h.length]:h},renderRegion:function(b,c){var d=this.values[b],e=this.options,f=this.xaxisOffset,g=[],h=this.range,i=this.stacked,j=this.target,k=b*this.totalBarWidth,m=this.canvasHeightEf,n=this.yoffset,o,p,q,r,s,t,u,v,w,x;d=a.isArray(d)?d:[d],u=d.length,v=d[0],r=l(null,d),x=l(f,d,!0);if(r)return e.get("nullColor")?(q=c?e.get("nullColor"):this.calcHighlightColor(e.get("nullColor"),e),o=n>0?n-1:n,j.drawRect(k,o,this.barWidth-1,0,q,q)):undefined;s=n;for(t=0;t<u;t++){v=d[t];if(i&&v===f){if(!x||w)continue;w=!0}h>0?p=Math.floor(m*(Math.abs(v-f)/h))+1:p=1,v<f||v===f&&n===0?(o=s,s+=p):(o=n-p,n-=p),q=this.calcColor(t,v,b),c&&(q=this.calcHighlightColor(q,e)),g.push(j.drawRect(k,o,this.barWidth-1,p-1,q,q))}return g.length===1?g[0]:g}}),a.fn.sparkline.tristate=w=d(a.fn.sparkline._base,t,{type:"t
ristate",init:function(b,c,d,e,f){var g=parseInt(d.get("barWidth"),10),h=parseInt(d.get("barSpacing"),10);w._super.init.call(this,b,c,d,e,f),this.regionShapes={},this.barWidth=g,this.barSpacing=h,this.totalBarWidth=g+h,this.values=a.map(c,Number),this.width=e=c.length*g+(c.length-1)*h,a.isArray(d.get("colorMap"))?(this.colorMapByIndex=d.get("colorMap"),this.colorMapByValue=null):(this.colorMapByIndex=null,this.colorMapByValue=d.get("colorMap"),this.colorMapByValue&&this.colorMapByValue.get===undefined&&(this.colorMapByValue=new q(this.colorMapByValue))),this.initTarget()},getRegion:function(a,b,c){return Math.floor(b/this.totalBarWidth)},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===undefined,value:this.values[a],color:this.calcColor(this.values[a],a),offset:a}},calcColor:function(a,b){var c=this.values,d=this.options,e=this.colorMapByIndex,f=this.colorMapByValue,g,h;return f&&(h=f.get(a))?g=h:e&&e.length>b?g=e[b]:c[b]<0?g=d.get("n
egBarColor"):c[b]>0?g=d.get("posBarColor"):g=d.get("zeroBarColor"),g},renderRegion:function(a,b){var c=this.values,d=this.options,e=this.target,f,g,h,i,j,k;f=e.pixelHeight,h=Math.round(f/2),i=a*this.totalBarWidth,c[a]<0?(j=h,g=h-1):c[a]>0?(j=0,g=h-1):(j=h-1,g=2),k=this.calcColor(c[a],a);if(k===null)return;return b&&(k=this.calcHighlightColor(k,d)),e.drawRect(i,j,this.barWidth-1,g-1,k,k)}}),a.fn.sparkline.discrete=x=d(a.fn.sparkline._base,t,{type:"discrete",init:function(b,c,d,e,f){x._super.init.call(this,b,c,d,e,f),this.regionShapes={},this.values=c=a.map(c,Number),this.min=Math.min.apply(Math,c),this.max=Math.max.apply(Math,c),this.range=this.max-this.min,this.width=e=d.get("width")==="auto"?c.length*2:this.width,this.interval=Math.floor(e/c.length),this.itemWidth=e/c.length,d.get("chartRangeMin")!==undefined&&(d.get("chartRangeClip")||d.get("chartRangeMin")<this.min)&&(this.min=d.get("chartRangeMin")),d.get("chartRangeMax")!==undefined&&(d.get("chartRangeClip")||d.get("cha
rtRangeMax")>this.max)&&(this.max=d.get("chartRangeMax")),this.initTarget(),this.target&&(this.lineHeight=d.get("lineHeight")==="auto"?Math.round(this.canvasHeight*.3):d.get("lineHeight"))},getRegion:function(a,b,c){return Math.floor(b/this.itemWidth)},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===undefined,value:this.values[a],offset:a}},renderRegion:function(a,b){var c=this.values,d=this.options,e=this.min,g=this.max,h=this.range,i=this.interval,j=this.target,k=this.canvasHeight,l=this.lineHeight,m=k-l,n,o,p,q;return o=f(c[a],e,g),q=a*i,n=Math.round(m-m*((o-e)/h)),p=d.get("thresholdColor")&&o<d.get("thresholdValue")?d.get("thresholdColor"):d.get("lineColor"),b&&(p=this.calcHighlightColor(p,d)),j.drawLine(q,n,q,n+l,p)}}),a.fn.sparkline.bullet=y=d(a.fn.sparkline._base,{type:"bullet",init:function(b,c,d,e,f){var g,h;y._super.init.call(this,b,c,d,e,f),c=a.map(c,Number),g=Math.min.apply(Math,c),h=Math.max.apply(Math,c),d.get("base")==
=undefined?g=g<0?g:0:g=d.get("base"),this.min=g,this.max=h,this.range=h-g,this.shapes={},this.valueShapes={},this.regiondata={},this.width=e=d.get("width")==="auto"?"4.0em":e,this.target=this.$el.simpledraw(e,f,d.get("composite")),c.length||(this.disabled=!0),this.initTarget()},getRegion:function(a,b,c){var d=this.target.getShapeAt(a,b,c);return d!==undefined&&this.shapes[d]!==undefined?this.shapes[d]:undefined},getCurrentRegionFields:function(){var a=this.currentRegion;return{fieldkey:a.substr(0,1),value:this.values[a.substr(1)],region:a}},changeHighlight:function(a){var b=this.currentRegion,c=this.valueShapes[b],d;delete this.shapes[c];switch(b.substr(0,1)){case"r":d=this.renderRange(b.substr(1),a);break;case"p":d=this.renderPerformance(a);break;case"t":d=this.renderTarget(a)}this.valueShapes[b]=d.id,this.shapes[d.id]=b,this.target.replaceWithShape(c,d)},renderRange:function(a,b){var c=this.values[a],d=Math.round(this.canvasWidth*((c-this.min)/this.range)),e=this.options.g
et("rangeColors")[a-2];return b&&(e=this.calcHighlightColor(e,this.options)),this.target.drawRect(0,0,d-1,this.canvasHeight-1,e,e)},renderPerformance:function(a){var b=this.values[1],c=Math.round(this.canvasWidth*((b-this.min)/this.range)),d=this.options.get("performanceColor");return a&&(d=this.calcHighlightColor(d,this.options)),this.target.drawRect(0,Math.round(this.canvasHeight*.3),c-1,Math.round(this.canvasHeight*.4)-1,d,d)},renderTarget:function(a){var b=this.values[0],c=Math.round(this.canvasWidth*((b-this.min)/this.range)-this.options.get("targetWidth")/2),d=Math.round(this.canvasHeight*.1),e=this.canvasHeight-d*2,f=this.options.get("targetColor");return a&&(f=this.calcHighlightColor(f,this.options)),this.target.drawRect(c,d,this.options.get("targetWidth")-1,e-1,f,f)},render:function(){var a=this.values.length,b=this.target,c,d;if(!y._super.render.call(this))return;for(c=2;c<a;c++)d=this.renderRange(c).append(),this.shapes[d.id]="r"+c,this.valueShapes["r"+c]=d.id;d=t
his.renderPerformance().append(),this.shapes[d.id]="p1",this.valueShapes.p1=d.id,d=this.renderTarget().append(),this.shapes[d.id]="t0",this.valueShapes.t0=d.id,b.render()}}),a.fn.sparkline.pie=z=d(a.fn.sparkline._base,{type:"pie",init:function(b,c,d,e,f){var g=0,h;z._super.init.call(this,b,c,d,e,f),this.shapes={},this.valueShapes={},this.values=c=a.map(c,Number),d.get("width")==="auto"&&(this.width=this.height);if(c.length>0)for(h=c.length;h--;)g+=c[h];this.total=g,this.initTarget(),this.radius=Math.floor(Math.min(this.canvasWidth,this.canvasHeight)/2)},getRegion:function(a,b,c){var d=this.target.getShapeAt(a,b,c);return d!==undefined&&this.shapes[d]!==undefined?this.shapes[d]:undefined},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===undefined,value:this.values[a],percent:this.values[a]/this.total*100,color:this.options.get("sliceColors")[a%this.options.get("sliceColors").length],offset:a}},changeHighlight:function(a){var b=this.cur
rentRegion,c=this.renderSlice(b,a),d=this.valueShapes[b];delete this.shapes[d],this.target.replaceWithShape(d,c),this.valueShapes[b]=c.id,this.shapes[c.id]=b},renderSlice:function(a,b){var c=this.target,d=this.options,e=this.radius,f=d.get("borderWidth"),g=d.get("offset"),h=2*Math.PI,i=this.values,j=this.total,k=g?2*Math.PI*(g/360):0,l,m,n,o,p;o=i.length;for(n=0;n<o;n++){l=k,m=k,j>0&&(m=k+h*(i[n]/j));if(a===n)return p=d.get("sliceColors")[n%d.get("sliceColors").length],b&&(p=this.calcHighlightColor(p,d)),c.drawPieSlice(e,e,e-f,l,m,undefined,p);k=m}},render:function(){var a=this.target,b=this.values,c=this.options,d=this.radius,e=c.get("borderWidth"),f,g;if(!z._super.render.call(this))return;e&&a.drawCircle(d,d,Math.floor(d-e/2),c.get("borderColor"),undefined,e).append();for(g=b.length;g--;)f=this.renderSlice(g).append(),this.valueShapes[g]=f.id,this.shapes[f.id]=g;a.render()}}),a.fn.sparkline.box=A=d(a.fn.sparkline._base,{type:"box",init:function(b,c,d,e,f){A._super.init.cal
l(this,b,c,d,e,f),this.values=a.map(c,Number),this.width=d.get("width")==="auto"?"4.0em":e,this.initTarget(),this.values.length||(this
+.disabled=1)},getRegion:function(){return 1},getCurrentRegionFields:function(){var a=[{field:"lq",value:this.quartiles[0]},{field:"med",value:this.quartiles[1]},{field:"uq",value:this.quartiles[2]},{field:"lo",value:this.loutlier},{field:"ro",value:this.routlier}];return this.lwhisker!==undefined&&a.push({field:"lw",value:this.lwhisker}),this.rwhisker!==undefined&&a.push({field:"rw",value:this.rwhisker}),a},render:function(){var a=this.target,b=this.values,c=b.length,d=this.options,e=this.canvasWidth,f=this.canvasHeight,h=d.get("chartRangeMin")===undefined?Math.min.apply(Math,b):d.get("chartRangeMin"),i=d.get("chartRangeMax")===undefined?Math.max.apply(Math,b):d.get("chartRangeMax"),j=0,k,l,m,n,o,p,q,r,s,t,u;if(!A._super.render.call(this))return;if(d.get("raw"))d.get("showOutliers")&&b.length>5?(l=b[0],k=b[1],n=b[2],o=b[3],p=b[4],q=b[5],r=b[6]):(k=b[0],n=b[1],o=b[2],p=b[3],q=b[4]);else{b.sort(function(a,b){return a-b}),n=g(b,1),o=g(b,2),p=g(b,3),m=p-n;if(d.get("showOutliers"
)){k=q=undefined;for(s=0;s<c;s++)k===undefined&&b[s]>n-m*d.get("outlierIQR")&&(k=b[s]),b[s]<p+m*d.get("outlierIQR")&&(q=b[s]);l=b[0],r=b[c-1]}else k=b[0],q=b[c-1]}this.quartiles=[n,o,p],this.lwhisker=k,this.rwhisker=q,this.loutlier=l,this.routlier=r,u=e/(i-h+1),d.get("showOutliers")&&(j=Math.ceil(d.get("spotRadius")),e-=2*Math.ceil(d.get("spotRadius")),u=e/(i-h+1),l<k&&a.drawCircle((l-h)*u+j,f/2,d.get("spotRadius"),d.get("outlierLineColor"),d.get("outlierFillColor")).append(),r>q&&a.drawCircle((r-h)*u+j,f/2,d.get("spotRadius"),d.get("outlierLineColor"),d.get("outlierFillColor")).append()),a.drawRect(Math.round((n-h)*u+j),Math.round(f*.1),Math.round((p-n)*u),Math.round(f*.8),d.get("boxLineColor"),d.get("boxFillColor")).append(),a.drawLine(Math.round((k-h)*u+j),Math.round(f/2),Math.round((n-h)*u+j),Math.round(f/2),d.get("lineColor")).append(),a.drawLine(Math.round((k-h)*u+j),Math.round(f/4),Math.round((k-h)*u+j),Math.round(f-f/4),d.get("whiskerColor")).append(),a.drawLine(Math
.round((q-h)*u+j),Math.round(f/2),Math.round((p-h)*u+j),Math.round(f/2),d.get("lineColor")).append(),a.drawLine(Math.round((q-h)*u+j),Math.round(f/4),Math.round((q-h)*u+j),Math.round(f-f/4),d.get("whiskerColor")).append(),a.drawLine(Math.round((o-h)*u+j),Math.round(f*.1),Math.round((o-h)*u+j),Math.round(f*.9),d.get("medianColor")).append(),d.get("target")&&(t=Math.ceil(d.get("spotRadius")),a.drawLine(Math.round((d.get("target")-h)*u+j),Math.round(f/2-t),Math.round((d.get("target")-h)*u+j),Math.round(f/2+t),d.get("targetColor")).append(),a.drawLine(Math.round((d.get("target")-h)*u+j-t),Math.round(f/2),Math.round((d.get("target")-h)*u+j+t),Math.round(f/2),d.get("targetColor")).append()),a.render()}}),a.browser.msie&&!document.namespaces.v&&document.namespaces.add("v","urn:schemas-microsoft-com:vml","#default#VML"),a.browser.hasCanvas===undefined&&(a.browser.hasCanvas=document.createElement("canvas").getContext!==undefined),D=d({init:function(a,b,c,d){this.target=a,this.id=b,th
is.type=c,this.args=d},append:function(){return this.target.appendShape(this),this}}),E=d({_pxregex:/(\d+)(px)?\s*$/i,init:function(b,c,d){if(!b)return;this.width=b,this.height=c,this.target=d,this.lastShapeId=null,d[0]&&(d=d[0]),a.data(d,"_jqs_vcanvas",this)},drawLine:function(a,b,c,d,e,f){return this.drawShape([[a,b],[c,d]],e,f)},drawShape:function(a,b,c,d){return this._genShape("Shape",[a,b,c,d])},drawCircle:function(a,b,c,d,e,f){return this._genShape("Circle",[a,b,c,d,e,f])},drawPieSlice:function(a,b,c,d,e,f,g){return this._genShape("PieSlice",[a,b,c,d,e,f,g])},drawRect:function(a,b,c,d,e,f){return this._genShape("Rect",[a,b,c,d,e,f])},getElement:function(){return this.canvas},getLastShapeId:function(){return this.lastShapeId},reset:function(){alert("reset not implemented")},_insert:function(b,c){a(c).html(b)},_calculatePixelDims:function(b,c,d){var e;e=this._pxregex.exec(c),e?this.pixelHeight=e[1]:this.pixelHeight=a(d).height(),e=this._pxregex.exec(b),e?this.pixelWidth=
e[1]:this.pixelWidth=a(d).width()},_genShape:function(a,b){var c=I++;return b.unshift(c),new D(this,c,a,b)},appendShape:function(a){alert("appendShape not implemented")},replaceWithShape:function(a,b){alert("replaceWithShape not implemented")},insertAfterShape:function(a,b){alert("insertAfterShape not implemented")},removeShapeId:function(a){alert("removeShapeId not implemented")},getShapeAt:function(a,b,c){alert("getShapeAt not implemented")},render:function(){alert("render not implemented")}}),F=d(E,{init:function(b,c,d,e){F._super.init.call(this,b,c,d),this.canvas=document.createElement("canvas"),d[0]&&(d=d[0]),a.data(d,"_jqs_vcanvas",this),a(this.canvas).css({display:"inline-block",width:b,height:c,verticalAlign:"top"}),this._insert(this.canvas,d),this._calculatePixelDims(b,c,this.canvas),this.canvas.width=this.pixelWidth,this.canvas.height=this.pixelHeight,this.interact=e,this.shapes={},this.shapeseq=[],this.currentTargetShapeId=undefined,a(this.canvas).css({width:this.
pixelWidth,height:this.pixelHeight})},_getContext:function(a,b,c){var d=this.canvas.getContext("2d");return a!==undefined&&(d.strokeStyle=a),d.lineWidth=c===undefined?1:c,b!==undefined&&(d.fillStyle=b),d},reset:function(){var a=this._getContext();a.clearRect(0,0,this.pixelWidth,this.pixelHeight),this.shapes={},this.shapeseq=[],this.currentTargetShapeId=undefined},_drawShape:function(a,b,c,d,e){var f=this._getContext(c,d,e),g,h;f.beginPath(),f.moveTo(b[0][0]+.5,b[0][1]+.5);for(g=1,h=b.length;g<h;g++)f.lineTo(b[g][0]+.5,b[g][1]+.5);c!==undefined&&f.stroke(),d!==undefined&&f.fill(),this.targetX!==undefined&&this.targetY!==undefined&&f.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a)},_drawCircle:function(a,b,c,d,e,f,g){var h=this._getContext(e,f,g);h.beginPath(),h.arc(b,c,d,0,2*Math.PI,!1),this.targetX!==undefined&&this.targetY!==undefined&&h.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a),e!==undefined&&h.stroke(),f!==undefined&&h
.fill()},_drawPieSlice:function(a,b,c,d,e,f,g,h){var i=this._getContext(g,h);i.beginPath(),i.moveTo(b,c),i.arc(b,c,d,e,f,!1),i.lineTo(b,c),i.closePath(),g!==undefined&&i.stroke(),h&&i.fill(),this.targetX!==undefined&&this.targetY!==undefined&&i.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a)},_drawRect:function(a,b,c,d,e,f,g){return this._drawShape(a,[[b,c],[b+d,c],[b+d,c+e],[b,c+e],[b,c]],f,g)},appendShape:function(a){return this.shapes[a.id]=a,this.shapeseq.push(a.id),this.lastShapeId=a.id,a.id},replaceWithShape:function(a,b){var c=this.shapeseq,d;this.shapes[b.id]=b;for(d=c.length;d--;)c[d]==a&&(c[d]=b.id);delete this.shapes[a]},replaceWithShapes:function(a,b){var c=this.shapeseq,d={},e,f,g;for(f=a.length;f--;)d[a[f]]=!0;for(f=c.length;f--;)e=c[f],d[e]&&(c.splice(f,1),delete this.shapes[e],g=f);for(f=b.length;f--;)c.splice(g,0,b[f].id),this.shapes[b[f].id]=b[f]},insertAfterShape:function(a,b){var c=this.shapeseq,d;for(d=c.length;d--;)if(c[d]===a){c
.splice(d+1,0,b.id),this.shapes[b.id]=b;return}},removeShapeId:function(a){var b=this.shapeseq,c;for(c=b.length;c--;)if(b[c]===a){b.splice(c,1);break}delete this.shapes[a]},getShapeAt:function(a,b,c){return this.targetX=b,this.targetY=c,this.render(),this.currentTargetShapeId},render:function(){var a=this.shapeseq,b=this.shapes,c=a.length,d=this._getContext(),e,f,g;d.clearRect(0,0,this.pixelWidth,this.pixelHeight);for(g=0;g<c;g++)e=a[g],f=b[e],this["_draw"+f.type].apply(this,f.args);this.interact||(this.shapes={},this.shapeseq=[])}}),G=d(E,{init:function(b,c,d){var e;G._super.init.call(this,b,c,d),d[0]&&(d=d[0]),a.data(d,"_jqs_vcanvas",this),this.canvas=document.createElement("span"),a(this.canvas).css({display:"inline-block",position:"relative",overflow:"hidden",width:b,height:c,margin:"0px",padding:"0px",verticalAlign:"top"}),this._insert(this.canvas,d),this._calculatePixelDims(b,c,this.canvas),this.canvas.width=this.pixelWidth,this.canvas.height=this.pixelHeight,e='<v:gro
up coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'"'+' style="position:absolute;top:0;left:0;width:'+this.pixelWidth+"px;height="+this.pixelHeight+'px;"></v:group>',this.canvas.insertAdjacentHTML("beforeEnd",e),this.group=a(this.canvas).children()[0],this.rendered=!1,this.prerender=""},_drawShape:function(a,b,c,d,e){var f=[],g,h,i,j,k,l,m;for(m=0,l=b.length;m<l;m++)f[m]=""+b[m][0]+","+b[m][1];return g=f.splice(0,1),e=e===undefined?1:e,h=c===undefined?' stroked="false" ':' strokeWeight="'+e+'px" strokeColor="'+c+'" ',i=d===undefined?' filled="false"':' fillColor="'+d+'" filled="true" ',j=f[0]===f[f.length-1]?"x ":"",k='<v:shape coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'" '+' id="jqsshape'+a+'" '+h+i+' style="position:absolute;left:0px;top:0px;height:'+this.pixelHeight+"px;width:"+this.pixelWidth+'px;padding:0px;margin:0px;" '+' path="m '+g+" l "+f.join(", ")+" "+j+'e">'+" </v:shape>",k},_drawCircle:function(a,b,c,d,e,f,g){var h
,i,j;return b-=d,c-=d,h=e===undefined?' stroked="false" ':' strokeWeight="'+g+'px" strokeColor="'+e+'" ',i=f===undefined?' filled="false"':' fillColor="'+f+'" filled="true" ',j='<v:oval id="jqsshape'+a+'" '+h+i+' style="position:absolute;top:'+c+"px; left:"+b+"px; width:"+d*2+"px; height:"+d*2+'px"></v:oval>',j},_drawPieSlice:function(a,b,c,d,e,f,g,h){var i,j,k,l,m,n,o,p;if(e===f)return;f-e===2*Math.PI&&(e=0,f=2*Math.PI),j=b+Math.round(Math.cos(e)*d),k=c+Math.round(Math.sin(e)*d),l=b+Math.round(Math.cos(f)*d),m=c+Math.round(Math.sin(f)*d);if(j===l&&k===m&&f-e<Math.PI)return;return i=[b-d,c-d,b+d,c+d,j,k,l,m],n=g===undefined?' stroked="false" ':' strokeWeight="1px" strokeColor="'+g+'" ',o=h===undefined?' filled="false"':' fillColor="'+h+'" filled="true" ',p='<v:shape coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'" '+' id="jqsshape'+a+'" '+n+o+' style="position:absolute;left:0px;top:0px;height:'+this.pixelHeight+"px;width:"+this.pixelWidth+'px;padding:0
px;margin:0px;" '+' path="m '+b+","+c+" wa "+i.join(", ")+' x e">'+" </v:shape>",p},_drawRect:function(a,b,c,d,e,f,g){return this._drawShape(a,[[b,c],[b,c+e],[b+d,c+e],[b+d,c],[b,c]],f,g)},reset:function(){this.group.innerHTML=""},appendShape:function(a){var b=this["_draw"+a.type].apply(this,a.args);return this.rendered?this.group.insertAdjacentHTML("beforeEnd",b):this.prerender+=b,this.lastShapeId=a.id,a.id},replaceWithShape:function(b,c){var d=a("#jqsshape"+b),e=this["_draw"+c.type].apply(this,c.args);d[0].outerHTML=e},replaceWithShapes:function(b,c){var d=a("#jqsshape"+b[0]),e="",f=c.length,g;for(g=0;g<f;g++)e+=this["_draw"+c[g].type].apply(this,c[g].args);d[0].outerHTML=e;for(g=1;g<b.length;g++)a("#jqsshape"+b[g]).remove()},insertAfterShape:function(b,c){var d=a("#jqsshape"+b),e=this["_draw"+c.type].apply(this,c.args);d[0].insertAdjacentHTML("afterEnd",e)},removeShapeId:function(b){var c=a("#jqsshape"+b);this.group.removeChild(c[0])},getShapeAt:function(a,b,c){var d=a.id
.substr(8);return d},render:function(){this.rendered||(this.group.innerHTML=this.prerender,this.rendered=!0)}})})(jQuery);
\ No newline at end of file
commit 12250e1e39fa3e4b48ca42c17eb561eff3d4d4bd
Author: John Sanda <jsanda(a)redhat.com>
Date: Wed Aug 15 13:24:37 2012 -0400
[BZ 802796] Provide more details for time outs
This commit add more details to the timeout help message.
CreateResourceRunner has also been updated so that it sets the status of
the respone to TIMED_OUT. Previously timed out deployments were getting
flagged as just a FAILURE. The error message in the response now also
contains additional details indicating that the deployment might still
succeed and that the user may want to run a discovery scan to see if it
did.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java
index 7a01b88..b3c65bd 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java
@@ -22,22 +22,22 @@
*/
package org.rhq.core.pc.inventory;
- import org.rhq.core.clientapi.agent.inventory.CreateResourceResponse;
- import org.rhq.core.clientapi.server.discovery.InventoryReport;
- import org.rhq.core.clientapi.server.inventory.ResourceFactoryServerService;
- import org.rhq.core.domain.configuration.Configuration;
- import org.rhq.core.domain.resource.CreateResourceStatus;
- import org.rhq.core.domain.resource.Resource;
- import org.rhq.core.pc.PluginContainer;
- import org.rhq.core.pluginapi.inventory.CreateChildResourceFacet;
- import org.rhq.core.pluginapi.inventory.CreateResourceReport;
- import org.rhq.core.util.exception.ThrowableUtil;
-
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
-
import java.util.concurrent.Callable;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.clientapi.agent.inventory.CreateResourceResponse;
+import org.rhq.core.clientapi.server.discovery.InventoryReport;
+import org.rhq.core.clientapi.server.inventory.ResourceFactoryServerService;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.resource.CreateResourceStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.pc.PluginContainer;
+import org.rhq.core.pluginapi.inventory.CreateChildResourceFacet;
+import org.rhq.core.pluginapi.inventory.CreateResourceReport;
+import org.rhq.core.util.exception.ThrowableUtil;
+
/**
* Runnable implementation to process Resource create requests.
*
@@ -159,9 +159,15 @@ public class CreateResourceRunner implements Callable, Runnable {
// If we still don't have an error message, populate it from the exception
errorMessage = (errorMessage != null) ? (errorMessage + " - Cause: " + messages) : messages;
}
+ } catch(TimeoutException e) {
+ status = CreateResourceStatus.TIMED_OUT;
+ errorMessage = "The time out has been exceeded; however, the deployment may have been successful. You " +
+ "may want to run a discovery scan to see if the deployment did complete successfully. Also consider " +
+ "using a higher time out value for future deployments.\n\nRoot Cause:\n";
+ errorMessage += ThrowableUtil.getStackAsString(e);
} catch (Throwable t) {
- errorMessage = ThrowableUtil.getStackAsString(t);
status = CreateResourceStatus.FAILURE;
+ errorMessage = ThrowableUtil.getStackAsString(t);
}
// Send results back to the server
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index f9b75f3..cfa1f6d 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -2035,8 +2035,8 @@ widget_resourceFactoryWizard_infoStepName = Resource Information
widget_resourceFactoryWizard_infoStep_loadFail = Failed to get available Architectures
widget_resourceFactoryWizard_namePrompt = New Resource Name
widget_resourceFactoryWizard_templatePrompt = Connection Settings Template
-widget_resourceFactoryWizard_timeoutFailure = Timed out. Note that it is possible that the deployment may still succeed.
-widget_resourceFactoryWizard_timeoutHelp = A timeout duration. If specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. Useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure.
+widget_resourceFactoryWizard_timeoutFailure = Timed out
+widget_resourceFactoryWizard_timeoutHelp = A timeout duration that if specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. A higher value may be useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure. Note that if there is a timeout failure, it is still possible that the resource deployment succeeded. In the event of a timeout you may want to execute a discovery scan before attempting to redeploy the resource.
widget_resourceFactoryWizard_uploadFailure = Failed to upload file
widget_resourceFactoryWizard_uploadFileStepName = Upload Resource Content File
widget_resourceFactoryWizard_uploadInProgress = The upload is in progress... This can take several minutes to complete for large distribution files.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index 11c4488..5be0d57 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -2052,8 +2052,8 @@ widget_resourceFactoryWizard_infoStepName = Informace o zdroji
widget_resourceFactoryWizard_infoStep_loadFail = NepodaÅilo se zÃskat dostupné architektury
widget_resourceFactoryWizard_namePrompt = Nové jméno zdroje
widget_resourceFactoryWizard_templatePrompt = Å ablona pro nastavenà pÅipojenÃ
-##widget_resourceFactoryWizard_timeoutFailure = Timed out. Note that it is possible that the deployment may still succeed.
-##widget_resourceFactoryWizard_timeoutHelp = A timeout duration. If specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. Useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure.
+##widget_resourceFactoryWizard_timeoutFailure = Timed out
+##widget_resourceFactoryWizard_timeoutHelp = A timeout duration that if specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. A higher value may be useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure. Note that if there is a timeout failure, it is still possible that the resource deployment succeeded. In the event of a timeout you may want to execute a discovery scan before attempting to redeploy the resource.
widget_resourceFactoryWizard_uploadFailure = NepodaÅilo se nahrát soubor
widget_resourceFactoryWizard_uploadFileStepName = Nahrát obsah souboru zdroje
widget_resourceFactoryWizard_uploadInProgress = Upload právÄ probÃhá... Můşe to trvat nÄkolik minut.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 71d8367..d39f16a 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -1815,9 +1815,9 @@ widget_resourceFactoryWizard_infoStepName = Information ÃŒber die Ressource
widget_resourceFactoryWizard_infoStep_loadFail = Konnte die verfÃŒgbaren Architekturen nicht ermitteln
widget_resourceFactoryWizard_namePrompt = Name der neuen Ressource
widget_resourceFactoryWizard_templatePrompt = Vorlage fÃŒr die Verbindungseinstellungen
-##widget_resourceFactoryWizard_timeoutHelp = A timeout duration. If specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. Useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure.
+##widget_resourceFactoryWizard_timeoutHelp = A timeout duration that if specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. A higher value may be useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure. Note that if there is a timeout failure, it is still possible that the resource deployment succeeded. In the event of a timeout you may want to execute a discovery scan before attempting to redeploy the resource.
widget_resourceFactoryWizard_uploadFailure = Konnte die Datei nicht hochladen
-###widget_resourceFactoryWizard_timeoutFailure = Timed out. Note that it is possible that the deployment may still succeed.
+###widget_resourceFactoryWizard_timeoutFailure = Timed out
##widget_resourceFactoryWizard_uploadFileStepName = Upload Resource Content File
##widget_resourceFactoryWizard_uploadInProgress = The upload is in progress... This can take several minutes to complete for large distribution files.
widget_resourceFactoryWizard_versionPrompt = Paketversion
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index 33e39c8..6c2044a 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -2022,8 +2022,8 @@ widget_resourceFactoryWizard_infoStepName = ãªãœãŒã¹æ
å ±
widget_resourceFactoryWizard_infoStep_loadFail = ã¢ãŒããã¯ãã£ãŒãå©çšå¯èœã«ããã®ã«å€±æããŸãã
widget_resourceFactoryWizard_namePrompt = æ°èŠãªãœãŒã¹å
widget_resourceFactoryWizard_templatePrompt = ã³ãã¯ã·ã§ã³èšå®ãã³ãã¬ãŒã
-###widget_resourceFactoryWizard_timeoutFailure = Timed out. Note that it is possible that the deployment may still succeed.
-##widget_resourceFactoryWizard_timeoutHelp = A timeout duration. If specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. Useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure.
+###widget_resourceFactoryWizard_timeoutFailure = Timed out
+##widget_resourceFactoryWizard_timeoutHelp = A timeout duration that if specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. A higher value may be useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure. Note that if there is a timeout failure, it is still possible that the resource deployment succeeded. In the event of a timeout you may want to execute a discovery scan before attempting to redeploy the resource.
widget_resourceFactoryWizard_uploadFailure = ãã¡ã€ã«ã¢ããããŒãã®å€±æ
widget_resourceFactoryWizard_uploadFileStepName = ãªãœãŒã¹ã³ã³ãã³ããã¡ã€ã«ã®ã¢ããããŒã
widget_resourceFactoryWizard_uploadInProgress = ã¢ããããŒãã¯åŠçäžã§ã... 倧ããªãã¡ã€ã«ãé
åžããã«ã¯æ°åãããããšããããŸãã
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 2c1af7e..9f00c55 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -2137,8 +2137,8 @@ widget_resourceFactoryWizard_infoStepName = Informa\u00E7\u00E3o do Recurso
widget_resourceFactoryWizard_infoStep_loadFail = Falha ao recuperar Arquiteturas dispon\u00EDveis.
widget_resourceFactoryWizard_namePrompt = Novo Nome do Recurso
widget_resourceFactoryWizard_templatePrompt = Modelo de Propriedades para Conex\u00E3o
-##widget_resourceFactoryWizard_timeoutFailure = Timed out. Note that it is possible that the deployment may still succeed.
-##widget_resourceFactoryWizard_timeoutHelp = A timeout duration. If specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. Useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure.
+##widget_resourceFactoryWizard_timeoutFailure = Timed out
+##widget_resourceFactoryWizard_timeoutHelp = A timeout duration that if specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. A higher value may be useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure. Note that if there is a timeout failure, it is still possible that the resource deployment succeeded. In the event of a timeout you may want to execute a discovery scan before attempting to redeploy the resource.
widget_resourceFactoryWizard_uploadFailure = Falha ao realizar o upload do arquivo
widget_resourceFactoryWizard_uploadFileStepName = Upload do Arquivo do Recurso
widget_resourceFactoryWizard_uploadInProgress = Upload em andamento... Esse processo pode demorar alguns minutos para ser finalizado em caso de arquivos muito grandes.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 29a3fa6..25671e1 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -2014,8 +2014,8 @@
#widget_resourceFactoryWizard_infoStep_loadFail = Failed to get available Architectures
#widget_resourceFactoryWizard_namePrompt = New Resource Name
#widget_resourceFactoryWizard_templatePrompt = Connection Settings Template
-#widget_resourceFactoryWizard_timeoutHelp = A timeout duration. If specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. Useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure.
-#widget_resourceFactoryWizard_timeoutFailure = Timed out. Note that it is possible that the deployment may still succeed.
+#widget_resourceFactoryWizard_timeoutHelp = A timeout duration that if specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. A higher value may be useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure. Note that if there is a timeout failure, it is still possible that the resource deployment succeeded. In the event of a timeout you may want to execute a discovery scan before attempting to redeploy the resource.
+#widget_resourceFactoryWizard_timeoutFailure = Timed out
#widget_resourceFactoryWizard_uploadFailure = Failed to upload file
#widget_resourceFactoryWizard_uploadFileStepName = Upload Resource Content File
#widget_resourceFactoryWizard_uploadInProgress = The upload is in progress... This can take several minutes to complete for large distribution files.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index cd7f97f..827e01b 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -2020,8 +2020,8 @@ widget_resourceFactoryWizard_infoStepName = \u8d44\u6e90\u6d88\u606f
widget_resourceFactoryWizard_infoStep_loadFail = \u65e0\u6cd5\u53d6\u5f97\u67b6\u6784
widget_resourceFactoryWizard_namePrompt = \u65b0\u8d44\u6e90\u540d
widget_resourceFactoryWizard_templatePrompt = \u8fde\u63a5\u8bbe\u7f6e\u6a21\u677f
-#widget_resourceFactoryWizard_timeoutHelp = A timeout duration. If specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. Useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure.
-#widget_resourceFactoryWizard_timeoutFailure = Timed out. Note that it is possible that the deployment may still succeed.
+#widget_resourceFactoryWizard_timeoutHelp = A timeout duration that if specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. A higher value may be useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure. Note that if there is a timeout failure, it is still possible that the resource deployment succeeded. In the event of a timeout you may want to execute a discovery scan before attempting to redeploy the resource.
+#widget_resourceFactoryWizard_timeoutFailure = Timed out
widget_resourceFactoryWizard_uploadFailure = \u4e0a\u4f20\u6587\u4ef6\u5931\u8d25
widget_resourceFactoryWizard_uploadFileStepName = \u4e0a\u4f20\u8d44\u6e90Content\u6587\u4ef6
widget_resourceFactoryWizard_uploadInProgress = \u6b63\u5728\u4e0a\u4f20\u4e2d... \u5927\u7684\u53d1\u5e03\u6587\u4ef6\u9700\u8981\u6d88\u8017\u6570\u5206\u949f\u5b8c\u6210.
commit 7b82e90aa77706ec33c5195e02da0f374e410c86
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Wed Aug 15 12:07:13 2012 -0400
Upate this dev plugin to also allow for a delay when reporting metrics. This
allows the plugin to be used for "slow" collection reporting when
simulating an overloaded agent or misbehaving plugin.
For example, to see debug logging in the agent when metric collection is
falling behind try:
1) Update pattern2 collection interval to 40s so that the two pattern metrics
are not collected at the same time, thus creating more load.
2) Set the new "delay" plugin config prop to 25. So, each collection will
take 25s, and quickly the agent will fall behind.
diff --git a/modules/plugins/pattern-generator/src/main/java/org/rhq/plugins/pattern/PatternComponent.java b/modules/plugins/pattern-generator/src/main/java/org/rhq/plugins/pattern/PatternComponent.java
index 5c8d631..18c6036 100644
--- a/modules/plugins/pattern-generator/src/main/java/org/rhq/plugins/pattern/PatternComponent.java
+++ b/modules/plugins/pattern-generator/src/main/java/org/rhq/plugins/pattern/PatternComponent.java
@@ -1,4 +1,3 @@
-
package org.rhq.plugins.pattern;
import java.util.Set;
@@ -30,6 +29,8 @@ public class PatternComponent implements ResourceComponent, MeasurementFacet {
int[] wanted = new int[2];
+ long delay = 0L; // in seconds
+
/**
* Return availability of this resource
* @see org.rhq.core.pluginapi.inventory.ResourceComponent#getAvailability()
@@ -38,7 +39,6 @@ public class PatternComponent implements ResourceComponent, MeasurementFacet {
return AvailabilityType.UP;
}
-
/**
* Start the resource connection
* @see org.rhq.core.pluginapi.inventory.ResourceComponent#start(org.rhq.core.pluginapi.inventory.ResourceContext)
@@ -46,19 +46,23 @@ public class PatternComponent implements ResourceComponent, MeasurementFacet {
public void start(ResourceContext context) throws InvalidPluginConfigurationException {
Configuration conf = context.getPluginConfiguration();
- String tmp = conf.getSimpleValue("ones","1");
+ String tmp = conf.getSimpleValue("ones", "1");
int wantedOnes = Integer.parseInt(tmp);
- if (wantedOnes<1)
+ if (wantedOnes < 1)
throw new InvalidPluginConfigurationException("Ones must be > 0");
- tmp = conf.getSimpleValue("zeros","1");
+ tmp = conf.getSimpleValue("zeros", "1");
int wantedZeros = Integer.parseInt(tmp);
- if (wantedZeros<1)
+ if (wantedZeros < 1)
throw new InvalidPluginConfigurationException("Zeros must be > 0");
wanted[0] = wantedZeros;
wanted[1] = wantedOnes;
- }
+ tmp = conf.getSimpleValue("delay", "0");
+ delay = Long.parseLong(tmp);
+ if (delay < 0L)
+ delay = 0L;
+ }
/**
* Tear down the resource connection
@@ -68,19 +72,22 @@ public class PatternComponent implements ResourceComponent, MeasurementFacet {
// Nothing to do.
}
-
/**
* Gather "measurement" data - actually a series of 1s and 0s starting with 0.
* @see org.rhq.core.pluginapi.measurement.MeasurementFacet#getValues(org.rhq.core.domain.measurement.MeasurementReport, java.util.Set)
*/
- public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> requests) throws Exception {
+ public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> requests) throws Exception {
+
+ if (delay > 0L) {
+ Thread.sleep(delay * 1000L);
+ }
- boolean flipMetrics = false;
- boolean flipTraits = false;
- for (MeasurementScheduleRequest request : requests) {
- String metricName = request.getName();
+ boolean flipMetrics = false;
+ boolean flipTraits = false;
+ for (MeasurementScheduleRequest request : requests) {
+ String metricName = request.getName();
- if (metricName.startsWith("pattern")) {
+ if (metricName.startsWith("pattern")) {
double value;
if (metricName.equals("pattern1")) {
@@ -98,15 +105,15 @@ public class PatternComponent implements ResourceComponent, MeasurementFacet {
double value;
if (metricName.equals("text1")) {
- value = numberForTrait;
- flipTraits = true;
+ value = numberForTrait;
+ flipTraits = true;
} else {
- // text2
- value = 1 - numberForTrait;
+ // text2
+ value = 1 - numberForTrait;
}
String traitValue = (value == 0) ? "red" : "green";
- MeasurementDataTrait datum = new MeasurementDataTrait(request,traitValue);
+ MeasurementDataTrait datum = new MeasurementDataTrait(request, traitValue);
report.addData(datum);
}
}
diff --git a/modules/plugins/pattern-generator/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/pattern-generator/src/main/resources/META-INF/rhq-plugin.xml
index 70a8a59..e45ba0f 100644
--- a/modules/plugins/pattern-generator/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/pattern-generator/src/main/resources/META-INF/rhq-plugin.xml
@@ -16,6 +16,7 @@
<plugin-configuration>
<c:simple-property name="zeros" description="Number of zeros in a row" type="integer" default="1"/>
<c:simple-property name="ones" description="Number of ones in a row" type="integer" default="2"/>
+ <c:simple-property name="delay" description="Number of seconds to delay each metric collection (to test slow reporting)" type="integer" default="0"/>
</plugin-configuration>
<metric property="pattern1" displayName="Pattern 1 Metric" defaultInterval="30000" displayType="summary" defaultOn="true"/>
commit c9eb53bb8dab7393d9b5383fbe5bab99088487ed
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue Aug 14 17:13:42 2012 -0400
[Bug 846353 - ORA-02049 during upgrade from JON-3.1.0.GA to JON-3.1.1.ER1 with Oracle]
After a lot of investigation it seems that the problem occurs occasionally
when we remove obsolete properties from resource configuration. It does
not happen every time, on fact it's fairly rare, although for the same DB,
and the same plugin update, it is repeatable. This makes it seem like the
locking issue is due mainly to unpredictable locking at the db level, and
likely the fact that we occasionally hit a page lock due to some other
prior update to the config table. Since the config table stores so many
different types of data it's not obvious how we would identify the conflict.
The approach taken was to try and reduce possible conflict by increasing the
granularity of metadata update transactions. Prior to this change we used a
single encompassing transaction for a plugin update, that means all types
were updated under one umbrella transaction. Not one transaction, because
we already use nested transactions in several places, but using one umbrella
transaction increases the chance of that transaction holding a lock that
could affect a nested transaction.
We still maintain the umbrella transaction but this commit breaks it up
such that a nested transaction is used for the update of each resource
type in the plugin.
That means each type update will not hold any locks when it has completed.
This change seems to be working as the AS7 plugin now updates successfully.
Additionally:
- added some more INFO level logging to give some basic progress during a
plugin update.
- added some more debug logging as well
- removed a bunch of unnecessary em.flush calls
- used the return value of some em.merge calls to ensure using the up to
date entity.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java
index dcc1a0b..b343f79 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java
@@ -73,24 +73,27 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
for (PropertyDefinition newProperty : newPropertyDefinitions) {
PropertyDefinition existingProp = existingDefinition.get(newProperty.getName());
if (existingProp != null) {
+ log.debug("Updating nonGrouped property [" + existingProp + "]");
+
updatePropertyDefinition(existingProp, newProperty);
updateReport.addUpdatedPropertyDefinition(newProperty);
} else {
+ log.debug("Adding nonGrouped property [" + newProperty + "]");
+
existingDefinition.put(newProperty);
updateReport.addNewPropertyDefinition(newProperty);
}
}
- // delete outdated properties
- removeNoLongerUsedProperties(newDefinition, existingDefinition, existingPropertyDefinitions);
+ existingDefinition = removeNoLongerUsedProperties(newDefinition, existingDefinition,
+ existingPropertyDefinitions);
+
} else {
// TODO what if existingDefinitions is null?
// we probably don't run in here, as the initial persisting is done
// somewhere else.
}
- // entityManager.flush();
-
/*
* Now update / delete contained groups We need to be careful here, as groups are present in PropertyDefinition
* as "backlink" from PropertyDefinition to group
@@ -108,6 +111,8 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
// first look for contained stuff
for (PropertyDefinition def : groupedDefinitions) {
+ log.debug("Removing property [" + def + "] from group [" + group + "]");
+
existingPropertyDefinitions.remove(def);
existingDefinition.getPropertyDefinitions().remove(def.getName());
def.setPropertyGroupDefinition(null);
@@ -115,41 +120,44 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
}
// then remove the definition itself
+ log.debug("Removing group [" + group + "]");
+
existingGroups.remove(group);
entityManager.remove(group);
}
- // entityManager.flush();
-
// update existing groups that stay
for (PropertyGroupDefinition group : toUpdate) {
String groupName = group.getName();
- // System.out.println("Group to update: " + groupName + ", id=" + group.getId());
List<PropertyDefinition> newGroupedDefinitions = newDefinition.getPropertiesInGroup(groupName);
for (PropertyDefinition nDef : newGroupedDefinitions) {
PropertyDefinition existingProperty = existingDefinition.getPropertyDefinitions().get(nDef.getName());
if (existingProperty != null) {
+ log.debug("Updating property [" + nDef + "] in group [" + group + "]");
+
updatePropertyDefinition(existingProperty, nDef);
updateReport.addUpdatedPropertyDefinition(nDef);
+
} else {
+ log.debug("Adding property [" + nDef + "] to group [" + group + "]");
+
existingDefinition.put(nDef);
updateReport.addNewPropertyDefinition(nDef);
}
}
// delete outdated properties of this group
- removeNoLongerUsedProperties(newDefinition, existingDefinition,
+ existingDefinition = removeNoLongerUsedProperties(newDefinition, existingDefinition,
existingDefinition.getPropertiesInGroup(groupName));
}
- // entityManager.flush();
-
// persist new groups
for (PropertyGroupDefinition group : toPersist) {
- /*
- * First persist a new group definition and then link the properties to it
- */
+
+ // First persist a new group definition and then link the properties to it
+ log.debug("Persisting new group [" + group + "]");
+
entityManager.persist(group);
existingGroups.add(group); // iterating over this does not update the underlying crap
@@ -185,17 +193,22 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
}
for (String name : toRemove) {
+ log.debug("Removing template [" + name + "]");
+
ConfigurationTemplate template = existingTemplates.remove(name);
entityManager.remove(template);
}
for (String name : templatesToUpdate) {
+ log.debug("Updating template [" + name + "]");
+
updateTemplate(existingDefinition.getTemplate(name), newTemplates.get(name));
}
for (String name : newTemplates.keySet()) {
// add completely new templates
if (!existingTemplates.containsKey(name)) {
+ log.debug("Adding template [" + name + "]");
ConfigurationTemplate newTemplate = newTemplates.get(name);
@@ -279,8 +292,9 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
* @param existingConfigDef existing persisted configuration
* @param existingProperties list of existing properties to inspect for potential removal
*/
- private void removeNoLongerUsedProperties(ConfigurationDefinition newConfigDef,
+ private ConfigurationDefinition removeNoLongerUsedProperties(ConfigurationDefinition newConfigDef,
ConfigurationDefinition existingConfigDef, List<PropertyDefinition> existingProperties) {
+
List<PropertyDefinition> propDefsToDelete = new ArrayList<PropertyDefinition>();
for (PropertyDefinition existingPropDef : existingProperties) {
PropertyDefinition newPropDef = newConfigDef.get(existingPropDef.getName());
@@ -296,8 +310,10 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
existingConfigDef.getPropertyDefinitions().remove(propDef.getName());
existingProperties.remove(propDef); // does not operate on original list!!
}
- entityManager.merge(existingConfigDef);
+ existingConfigDef = entityManager.merge(existingConfigDef);
}
+
+ return existingConfigDef;
}
/**
@@ -360,7 +376,7 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
}
}
- entityManager.merge(existingProperty);
+ existingProperty = entityManager.merge(existingProperty);
} else { // different type
@@ -412,7 +428,7 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
}
}
}
- entityManager.merge(existingPDS);
+ existingPDS = entityManager.merge(existingPDS);
// handle <constraint> [0..*]
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
index 032deb3..2c8a925 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
@@ -153,7 +153,7 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
Set<ResourceType> legitimateChildren = new HashSet<ResourceType>();
for (ResourceType resourceType : nonRunsInsideResourceTypes) {
long startTime = System.currentTimeMillis();
- updateType(resourceType);
+ resourceType = resourceMetadataManager.updateType(resourceType);
long endTime = System.currentTimeMillis();
log.debug("Updated resource type [" + toConciseString(resourceType) + "] in " + (endTime - startTime)
+ " ms");
@@ -181,7 +181,7 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
resourceMetadataManager.getPluginTypes(subject, pluginName, legitTypes, obsoleteTypes, metadataCache);
if (!obsoleteTypes.isEmpty()) {
- log.debug("Removing " + obsoleteTypes.size() + " obsolete types: " + obsoleteTypes + "...");
+ log.info("Removing " + obsoleteTypes.size() + " obsolete types: " + obsoleteTypes + "...");
removeResourceTypes(subject, obsoleteTypes, new HashSet<ResourceType>(obsoleteTypes));
}
@@ -361,21 +361,19 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
}
}
- private void updateType(ResourceType resourceType) {
- entityManager.flush();
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public ResourceType updateType(ResourceType resourceType) {
// see if there is already an existing type that we need to update
- if (log.isDebugEnabled()) {
- log.debug("Updating resource type [" + resourceType.getName() + "] from plugin ["
- + resourceType.getPlugin() + "]...");
- }
+ log.info("Updating resource type [" + toConciseString(resourceType) + "]...");
ResourceType existingType;
try {
existingType = resourceTypeManager.getResourceTypeByNameAndPlugin(resourceType.getName(),
resourceType.getPlugin());
+
} catch (NonUniqueResultException nure) {
- log.debug("Found more than one existing ResourceType for " + resourceType);
+ log.info("Found more than one existing ResourceType for " + resourceType);
// TODO: Delete the redundant ResourceTypes to get the DB into a valid state.
throw new IllegalStateException(nure);
}
@@ -390,6 +388,8 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
} else {
mergeExistingType(resourceType, existingType);
}
+
+ return resourceType;
}
private void mergeExistingType(ResourceType resourceType, ResourceType existingType) {
@@ -427,7 +427,7 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
// Update the type itself
if (resourceType.getCategory() != existingType.getCategory()) {
log.info("Changing category of Resource type [" + resourceType + "] from " + existingType.getCategory()
- + " to " + resourceType.getCategory() + "...");
+ + " to " + resourceType.getCategory() + "...");
existingType.setCategory(resourceType.getCategory());
}
@@ -447,7 +447,7 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
// above already took care of any modifications to the ResourceSubCategories themselves).
} else if (newSubCat == null) {
if (oldSubCat != null) {
- log.debug("Metadata update: Subcategory of ResourceType [" + resourceType.getName() + "] changed from "
+ log.info("Metadata update: Subcategory of ResourceType [" + resourceType.getName() + "] changed from "
+ oldSubCat + " to " + newSubCat);
existingType.setSubCategory(null);
}
@@ -459,13 +459,12 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
throw new IllegalStateException("Resource type [" + resourceType.getName() + "] in plugin ["
+ resourceType.getPlugin() + "] has a subcategory (" + newSubCat.getName()
+ ") which was not defined as a child subcategory of one of its ancestor resource types.");
- log.debug("Metadata update: Subcategory of ResourceType [" + resourceType.getName() + "] changed from "
+ log.info("Metadata update: Subcategory of ResourceType [" + resourceType.getName() + "] changed from "
+ oldSubCat + " to " + existingSubCat);
existingType.setSubCategory(existingSubCat);
}
existingType = entityManager.merge(existingType);
- entityManager.flush();
}
@Override
@@ -600,7 +599,6 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
MeasurementMetadataManagerBean.getMetricDefinitions(resourceType);
entityManager.persist(resourceType);
- entityManager.flush();
}
private void linkSubCategoryToParents(ResourceType resourceType) {
@@ -665,8 +663,6 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
obsoleteParentType.removeChildResourceType(existingType);
moveResourcesToNewParent(existingType, obsoleteParentType, newParentTypes);
}
-
- entityManager.flush();
}
private static String toConciseString(ResourceType type) {
@@ -711,7 +707,7 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
// children are not handled in this method, update their ancestry now.
resourceManager.updateAncestry(subjectManager.getOverlord(), resource.getId());
} else {
- log.debug("We were unable to move " + resource + " from invalid parent " + resource.getParentResource()
+ log.info("We were unable to move " + resource + " from invalid parent " + resource.getParentResource()
+ " to a new valid parent with one of the following types: " + newParentTypes);
}
}
@@ -842,7 +838,7 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
// simply use the ones from the new type
if ((existingSubCat.getChildSubCategories() == null) || existingSubCat.getChildSubCategories().isEmpty()) {
for (ResourceSubCategory newChildSubCategory : newSubCategory.getChildSubCategories()) {
- log.debug("Metadata update: Adding new child SubCategory [" + newChildSubCategory.getName()
+ log.info("Metadata update: Adding new child SubCategory [" + newChildSubCategory.getName()
+ "] to SubCategory [" + existingSubCat.getName() + "]...");
existingSubCat.addChildSubCategory(newChildSubCategory);
entityManager.persist(newChildSubCategory);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerLocal.java
index ae96d22..b40bf7a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerLocal.java
@@ -46,6 +46,9 @@ public interface ResourceMetadataManagerLocal {
void updateTypes(Set<ResourceType> resourceTypes) throws Exception;
+ /** Exists only to for transactional boundary reasons. Not for general consumption. */
+ ResourceType updateType(ResourceType resourceType) throws Exception;
+
/** TODO: do we want to create a driftMetadataManager SLSB and put this in there */
void updateDriftMetadata(ResourceType existingType, ResourceType resourceType);
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java
index 20f3b9e..4714f57 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java
@@ -176,6 +176,8 @@ public class UpdateConfigurationSubsystemTest extends UpdatePluginMetadataTestBa
}
}
+ // 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
commit b86e772ba8569cc2084fac6e1b2a96f7422cc0e8
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Aug 14 15:40:56 2012 -0400
BZ 848030 - jmxName can be null, so act accordingly. Also put the jmxName into the connection properties of the created resource.
diff --git a/modules/plugins/jboss-cache-v3/src/main/java/org/rhq/plugins/jbosscache3/JBossCacheDetailDiscoveryComponent.java b/modules/plugins/jboss-cache-v3/src/main/java/org/rhq/plugins/jbosscache3/JBossCacheDetailDiscoveryComponent.java
index 5d522de..5d907da 100644
--- a/modules/plugins/jboss-cache-v3/src/main/java/org/rhq/plugins/jbosscache3/JBossCacheDetailDiscoveryComponent.java
+++ b/modules/plugins/jboss-cache-v3/src/main/java/org/rhq/plugins/jbosscache3/JBossCacheDetailDiscoveryComponent.java
@@ -40,9 +40,9 @@ import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
import org.rhq.plugins.jbossas5.ProfileServiceComponent;
/**
- *
+ *
* @author Filip Drabek
- *
+ *
*/
public class JBossCacheDetailDiscoveryComponent implements
ResourceDiscoveryComponent<ProfileServiceComponent<?>> {
@@ -80,7 +80,7 @@ public class JBossCacheDetailDiscoveryComponent implements
String jmxName = defaultConfig.getSimple(CACHE_JMX_NAME).getStringValue();
- beanName += (jmxName.equals("") ? "" : "," + jmxName);
+ beanName += ((jmxName==null || jmxName.equals("")) ? "" : "," + jmxName);
// This is a singleton ResourceType, so we are only looking for a single MBean.
EmsBean emsBean = connection.getBean(beanName);
@@ -94,6 +94,8 @@ public class JBossCacheDetailDiscoveryComponent implements
conf.put(new PropertySimple(
JBossCacheDetailComponent.CACHE_DETAIL_BEAN_NAME,
beanName));
+ conf.put(new PropertySimple(CACHE_JMX_NAME, jmxName));
+
resources.add(new DiscoveredResourceDetails(resourceType,
beanName, resourceType.getName(), "", "JBoss Cache",
conf, null));
diff --git a/modules/plugins/jboss-cache-v3/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-cache-v3/src/main/resources/META-INF/rhq-plugin.xml
index cba79cf..2572f54 100644
--- a/modules/plugins/jboss-cache-v3/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-cache-v3/src/main/resources/META-INF/rhq-plugin.xml
@@ -31,7 +31,7 @@
singleton="true">
<plugin-configuration>
- <c:simple-property name="jmx-resource" default=""/>
+ <c:simple-property name="jmx-resource" default="" required="false"/>
</plugin-configuration>
<operation name="destroy" displayName="Destroy this cache."/>
commit 9e5352d85ca3b4ee98d52771930b61e72f73f579
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 14 14:35:51 2012 -0500
[BZ 833187] A few more updates to :nullable list parsing and saving code. The original fix did not include the loading of such properties.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationLoadDelegate.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationLoadDelegate.java
index 0a49bd1..2fdff39 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationLoadDelegate.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationLoadDelegate.java
@@ -257,7 +257,8 @@ public class ConfigurationLoadDelegate implements ConfigurationFacet {
}
}
- if (propertyName.endsWith(":expr") || propertyName.endsWith(":collapsed")) {
+ if (propertyName.endsWith(":expr") || propertyName.endsWith(":collapsed")
+ || propertyName.endsWith(":nullable")) {
String realName = propertyName.substring(0, propertyName.indexOf(":"));
valueObject = results.get(realName);
} else {
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
index 86ba37a..8286f17 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
@@ -569,7 +569,7 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
}
}
- propertyName = stripNumberIdentifier(property.getName());
+ propertyName = stripNumberIdentifier(propertyName);
return new SimpleEntry<String, List<Object>>(propertyName, values);
}
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 08c12ba..a1eb285 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
@@ -3734,7 +3734,7 @@
<c:simple-property name="persist-delivery-count-before-delivery" required="false" type="boolean" readOnly="true" defaultValue="false" description="Whether the delivery count is persisted before delivery. False means that this only happens after a message has been cancelled. The default value is false."/>
<c:simple-property name="persist-id-cache" required="false" type="boolean" readOnly="true" defaultValue="true" description="Whether IDs are persisted to the journal. The default value is true."/>
<c:simple-property name="persistence-enabled" required="false" type="boolean" readOnly="true" defaultValue="true" description="Whether the server will use the file based journal for persistence. The default value is true."/>
- <c:list-property name="remoting-interceptors:nullable" required="false" readOnly="true" description="The list of interceptor classes used by this server." >
+ <c:list-property name="remoting-interceptors:nullable" required="false" readOnly="true" displayName="Remoting Interceptors" description="The list of interceptor classes used by this server." >
<c:simple-property name="remoting-interceptors" readOnly="true"/>
</c:list-property>
<c:simple-property name="run-sync-speed-test" required="false" type="boolean" readOnly="true" defaultValue="false" description="Whether on startup to perform a diagnostic test on how fast your disk can sync. Useful when determining performance issues. The default value is false."/>
@@ -4700,7 +4700,7 @@
<c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="true" defaultValue="-1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of -1 signifies an unlimited number of attempts. The default value is -1."/>
<c:simple-property name="retry-interval" required="false" type="long" readOnly="true" defaultValue="500" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 500."/>
<c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="true" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
- <c:list-property name="static-connectors:nullable" required="false" readOnly="true" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if 'discovery-group-name' is defined." >
+ <c:list-property name="static-connectors:nullable" required="false" readOnly="true" displayName="Static Connectors" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if 'discovery-group-name' is defined." >
<c:simple-property name="static-connectors" readOnly="true"/>
</c:list-property>
<c:simple-property name="use-duplicate-detection" required="false" type="boolean" readOnly="true" defaultValue="true" description="Whether the bridge will automatically insert a duplicate id property into each message that it forwards. The default value is true."/>
@@ -4823,7 +4823,7 @@
<c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="true" defaultValue="-1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of -1 signifies an unlimited number of attempts. The default value is -1."/>
<c:simple-property name="retry-interval" required="false" type="long" readOnly="true" defaultValue="2000" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 2000."/>
<c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="true" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
- <c:list-property name="static-connectors:nullable" required="false" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if 'discovery-group-name' is defined." >
+ <c:list-property name="static-connectors:nullable" required="false" displayName="Static Connectors" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if 'discovery-group-name' is defined." >
<c:simple-property name="static-connectors" />
</c:list-property>
<c:simple-property name="transformer-class-name" required="false" type="string" readOnly="true" description="The name of a user-defined class which implements the org.hornetq.core.server.cluster.Transformer interface."/>
@@ -6373,7 +6373,7 @@
<c:simple-property name="persist-delivery-count-before-delivery" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether the delivery count is persisted before delivery. False means that this only happens after a message has been cancelled. The default value is false."/>
<c:simple-property name="persist-id-cache" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether IDs are persisted to the journal. The default value is true."/>
<c:simple-property name="persistence-enabled" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the server will use the file based journal for persistence. The default value is true."/>
- <c:list-property name="remoting-interceptors:nullable" required="false" description="The list of interceptor classes used by this server." >
+ <c:list-property name="remoting-interceptors:nullable" required="false" displayName="Remoting Interceptors" description="The list of interceptor classes used by this server." >
<c:simple-property name="remoting-interceptors" />
</c:list-property>
<c:simple-property name="run-sync-speed-test" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether on startup to perform a diagnostic test on how fast your disk can sync. Useful when determining performance issues. The default value is false."/>
@@ -6829,7 +6829,7 @@
<c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="false" defaultValue="-1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of -1 signifies an unlimited number of attempts. The default value is -1."/>
<c:simple-property name="retry-interval" required="false" type="long" readOnly="false" defaultValue="500" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 500."/>
<c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
- <c:list-property name="static-connectors:nullable" required="false" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if 'discovery-group-name' is defined." >
+ <c:list-property name="static-connectors:nullable" required="false" displayName="Static Connectors" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if 'discovery-group-name' is defined." >
<c:simple-property name="static-connectors" />
</c:list-property>
<c:simple-property name="use-duplicate-detection" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the bridge will automatically insert a duplicate id property into each message that it forwards. The default value is true."/>
@@ -6918,7 +6918,7 @@
<c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="false" defaultValue="-1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of -1 signifies an unlimited number of attempts. The default value is -1."/>
<c:simple-property name="retry-interval" required="false" type="long" readOnly="false" defaultValue="2000" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 2000."/>
<c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
- <c:list-property name="static-connectors:nullable" required="false" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if 'discovery-group-name' is defined." >
+ <c:list-property name="static-connectors:nullable" required="false" displayName="Static Connectors" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if 'discovery-group-name' is defined." >
<c:simple-property name="static-connectors" />
</c:list-property>
<c:simple-property name="transformer-class-name" required="false" type="string" readOnly="false" description="The name of a user-defined class which implements the org.hornetq.core.server.cluster.Transformer interface."/>
@@ -9342,7 +9342,7 @@
<c:simple-property name="persist-delivery-count-before-delivery" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether the delivery count is persisted before delivery. False means that this only happens after a message has been cancelled. The default value is false."/>
<c:simple-property name="persist-id-cache" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether IDs are persisted to the journal. The default value is true."/>
<c:simple-property name="persistence-enabled" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the server will use the file based journal for persistence. The default value is true."/>
- <c:list-property name="remoting-interceptors:nullable" required="false" description="The list of interceptor classes used by this server.">
+ <c:list-property name="remoting-interceptors:nullable" required="false" displayName="Remoting Interceptors" description="The list of interceptor classes used by this server.">
<c:simple-property name="remoting-interceptors"/>
</c:list-property>
<c:simple-property name="run-sync-speed-test" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether on startup to perform a diagnostic test on how fast your disk can sync. Useful when determining performance issues. The default value is false."/>
@@ -11936,7 +11936,7 @@
<c:simple-property name="persist-delivery-count-before-delivery" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether the delivery count is persisted before delivery. False means that this only happens after a message has been cancelled. The default value is false."/>
<c:simple-property name="persist-id-cache" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether IDs are persisted to the journal. The default value is true."/>
<c:simple-property name="persistence-enabled" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the server will use the file based journal for persistence. The default value is true."/>
- <c:list-property name="remoting-interceptors:nullable" required="false" description="The list of interceptor classes used by this server.">
+ <c:list-property name="remoting-interceptors:nullable" required="false" displayName="Remoting Interceptors" description="The list of interceptor classes used by this server.">
<c:simple-property name="remoting-interceptors"/>
</c:list-property>
<c:simple-property name="run-sync-speed-test" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether on startup to perform a diagnostic test on how fast your disk can sync. Useful when determining performance issues. The default value is false."/>
@@ -12903,7 +12903,7 @@
<c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="false" defaultValue="-1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of -1 signifies an unlimited number of attempts. The default value is -1."/>
<c:simple-property name="retry-interval" required="false" type="long" readOnly="false" defaultValue="500" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 500."/>
<c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
- <c:list-property name="static-connectors:nullable" required="false" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if 'discovery-group-name' is defined.">
+ <c:list-property name="static-connectors:nullable" required="false" displayName="Static Connectors" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if 'discovery-group-name' is defined.">
<c:simple-property name="static-connectors"/>
</c:list-property>
<c:simple-property name="use-duplicate-detection" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the bridge will automatically insert a duplicate id property into each message that it forwards. The default value is true."/>
@@ -13026,7 +13026,7 @@
<c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="false" defaultValue="-1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of -1 signifies an unlimited number of attempts. The default value is -1."/>
<c:simple-property name="retry-interval" required="false" type="long" readOnly="false" defaultValue="2000" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 2000."/>
<c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
- <c:list-property name="static-connectors:nullable" required="false" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if 'discovery-group-name' is defined.">
+ <c:list-property name="static-connectors:nullable" required="false" displayName="Static Connectors" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if 'discovery-group-name' is defined.">
<c:simple-property name="static-connectors"/>
</c:list-property>
<c:simple-property name="transformer-class-name" required="false" type="string" readOnly="false" description="The name of a user-defined class which implements the org.hornetq.core.server.cluster.Transformer interface."/>
commit 15248b7c3099a46a3c41ccf487f391861d03a9bd
Author: John Sanda <jsanda(a)redhat.com>
Date: Tue Aug 14 15:13:24 2012 -0400
[BZ 846715] Taking groovy server plugin out of build
Until we find a new home for the groovy-script-server plugin, I am
taking it out of the build to get past errors when building with Java 7.
diff --git a/modules/enterprise/server/plugins/pom.xml b/modules/enterprise/server/plugins/pom.xml
index 4e4a30e..11f3b5c 100644
--- a/modules/enterprise/server/plugins/pom.xml
+++ b/modules/enterprise/server/plugins/pom.xml
@@ -78,7 +78,6 @@
<module>filetemplate-bundle</module>
<module>ant-bundle</module>
<module>validate-all-serverplugins</module>
- <module>groovy-script</module>
<module>packagetype-cli</module>
</modules>
commit 19cfeb90dcbf853a5aacf76656b4218af16d642f
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Aug 14 15:51:48 2012 +0200
[BZ 848066] - The group resource configuration page shows the config editor again
Also made the layout consistent with the single resource config page by
moving the button bar to the bottom of the page.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
index f6d6657..c5467b8 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
@@ -111,9 +111,8 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
save();
}
});
+ this.saveButton.disable();
buttonbar.addMember(saveButton);
- // The button bar will remain hidden until the configuration has been successfully loaded.
- buttonbar.setVisible(false);
return buttonbar;
}
@@ -125,7 +124,7 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
}
this.refreshing = true;
- this.saveButton.disable();
+
if (editor != null) {
editor.destroy();
removeMember(editor);
@@ -146,6 +145,7 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
this.editor.addPropertyValueChangeListener(this);
this.editor.setReadOnly(!this.resourcePermission.isConfigureWrite());
addMember(this.editor);
+ addMember(createButtonBar());
this.refreshing = false; // when we get here, we know we are done the refresh
}
}
@@ -197,7 +197,6 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
"The server did not return the configuration for one or more member resources.");
}
memberConfigurations.add(memberConfiguration);
- addMember(createButtonBar());
}
initEditor();
}
commit bbdcaee2ca23717a53277fe0bb479f761f46025e
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Aug 14 13:38:06 2012 +0200
[BZ 847804] - make sure to fetch the latest known resource config through
the proxy factory.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
index 10ee612..0199c77 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
@@ -491,10 +491,13 @@ public class ResourceClientProxy {
public Configuration getResourceConfiguration() {
if (!LazyLoadScenario.isShouldLoad())
return null;
-
- return remoteClient.getProxy(ConfigurationManagerRemote.class).getResourceConfiguration(
- remoteClient.getSubject(),
- resourceClientProxy.resourceId);
+
+ //make sure to fetch the latest known resource config. This ensures that
+ //the server goes out to the agent if there is no known config yet and thus
+ //giving the scripting user an always up-to-date info.
+ ResourceConfigurationUpdate update = remoteClient.getProxy(ConfigurationManagerRemote.class).getLatestResourceConfigurationUpdate(
+ remoteClient.getSubject(), resourceClientProxy.resourceId);
+ return update == null ? null : update.getConfiguration();
}
public ConfigurationDefinition getResourceConfigurationDefinition() {
commit 06a05b1371c11563b639d4faf74f27254668cd21
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon Aug 13 18:20:12 2012 -0500
[BZ 829329] Enable the discovery of server-group deployments after a domain deployment is sent to server groups.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
index ff55c8d..27b1133 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
@@ -552,6 +552,13 @@ public abstract class BaseServerComponent<T extends ResourceComponent<?>> extend
return result;
}
+ /**
+ * Requests a deferred child resource discovery for sub-resources of this server.
+ */
+ public void requestDeferredChildResourcesDiscovery() {
+ this.context.getInventoryContext().requestDeferredChildResourcesDiscovery();
+ }
+
@Override
public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> requests) throws Exception {
Set<MeasurementScheduleRequest> skmRequests = new HashSet<MeasurementScheduleRequest>(requests.size());
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DomainDeploymentComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DomainDeploymentComponent.java
index 6192c18..54cffbf 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DomainDeploymentComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DomainDeploymentComponent.java
@@ -77,6 +77,14 @@ public class DomainDeploymentComponent extends DeploymentComponent implements Op
Result res = getASConnection().execute(operation, 120); // wait up to 2 minutes
if (res.isSuccess()) {
operationResult.setSimpleResult("Successfully deployed to server groups " + serverGroups);
+
+ //request the server to discover child resources to allow the discovery of the deployments
+ //on server groups immediately
+ if (this.context.getParentResourceComponent().getClass().isInstance(HostControllerComponent.class)) {
+ HostControllerComponent<?> hostController = (HostControllerComponent<?>) this.context
+ .getParentResourceComponent();
+ hostController.requestDeferredChildResourcesDiscovery();
+ }
} else {
operationResult.setErrorMessage("Deployment to server groups failed: " + res.getFailureDescription());
}
commit 1084a72ad31e8d78529ce8313e9e83c12b264ec7
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon Aug 13 16:36:03 2012 -0500
[BZ 839643] Removed the property from the profile subsystem definition until the AS7 issue is resolved. The property is not important for profiles since the value is read-only and used only by the managed server. The value can still be read from the managed server itself.
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 d27d432..08c12ba 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
@@ -6471,7 +6471,6 @@
<c:simple-property name="failover-on-server-shutdown" required="false" type="boolean" readOnly="false" description="True to fail over on server shutdown."/>
<c:simple-property name="group-id" required="false" type="string" readOnly="false" description="The group id."/>
<c:simple-property name="ha" required="true" type="boolean" readOnly="false" defaultValue="false" description="Whether the connection factory supports High Availability. The default value is false."/>
- <c:simple-property name="initial-message-packet-size" required="true" type="integer" readOnly="true" description="The initial size of messages created through this factory."/>
<c:simple-property name="max-retry-interval" required="false" type="long" readOnly="false" defaultValue="2000" description="The max retry interval. The default value is 2000."/>
<c:simple-property name="min-large-message-size" required="false" type="integer" readOnly="false" defaultValue="102400" description="The min large message size. The default value is 102400."/>
<c:simple-property name="pre-acknowledge" required="false" type="boolean" readOnly="false" defaultValue="false" description="True to pre-acknowledge. The default value is false."/>
commit 83c2b30289f9b11b2d0e25d02f51b1475ccd9aea
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Aug 13 16:34:19 2012 -0400
BZ 846385 - Make sure to use the JDG types only when he product found is JDG and the other way around.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SubsystemDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SubsystemDiscovery.java
index deec7a3..18eb274 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SubsystemDiscovery.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SubsystemDiscovery.java
@@ -85,8 +85,9 @@ public class SubsystemDiscovery implements ResourceDiscoveryComponent<BaseCompon
lookForChildren = true;
}
- if (isIspnForJDG(context, confPath)) {
- log.debug("We have JDG as child, ignoring the {JBossAS7}Infinispan type");
+ // check if the parent is a JDG server. In this case ignore the as7 version
+ // of the type and vice versa
+ if (shouldSkipEntryWrtIspn(context, confPath)) {
return details;
}
@@ -190,40 +191,48 @@ public class SubsystemDiscovery implements ResourceDiscoveryComponent<BaseCompon
return details;
}
- private boolean isIspnForJDG(ResourceDiscoveryContext<BaseComponent<?>> context, String confPath) {
-
- // Check if this is ISPN
+ /**
+ * The as7 plugin and the JDG plugin both have a subsystem=infinispan. We need to decide
+ * which one to 'activate' depending on the type, plugin and the detected parent.
+ * Rules are:<ul>
+ * <li>If the parent is a host controller or such, there is no jdg available</li>
+ * <li>If parent is eap/as7, use the type from the as7 plugin</li>
+ * <li>If parent is a jdg server, use the type from the jdg plugin.</li>
+ * </ul>
+ *
+ *
+ * @param context The parent's resource component
+ * @param confPath The subsystem that got fed into discovery. Directly return is not subsystem=infinispan
+ * @return True if this subsystem should be skipped.
+ */
+ private boolean shouldSkipEntryWrtIspn(ResourceDiscoveryContext<BaseComponent<?>> context,
+ String confPath) {
+
+ String jdgPluginType = "JDG";
+
+ // If this is not subsystem=infinispan, we should not skip it at all
if (!"subsystem=infinispan".equals(confPath))
return false;
ResourceType ourType = context.getResourceType();
- if (ourType.getPlugin().equals("JDG"))
- return false;
+ boolean ourPluginTypeIsJdg = ourType.getPlugin().equals(jdgPluginType);
- if (!ourType.getName().equals("Infinispan"))
- return false;
+ String productType = context.getParentResourceComponent().pluginConfiguration.getSimpleValue("productType","AS7");
+ boolean isJdgProduct = jdgPluginType.equals(productType);
- // So we are {JBossAS7}Infinispan
- Set<ResourceType> parentTypes = ourType.getParentResourceTypes();
- ResourceType parent = null;
- for (ResourceType type : parentTypes) {
- if (type.getName().equals("JBossAS7 Standalone Server") && type.getPlugin().equals("JBossAS7")) {
- parent = type;
- break;
- }
- }
- if (parent==null)
+ if (ourPluginTypeIsJdg && isJdgProduct) {
+ if (log.isDebugEnabled())
+ log.debug("Ours is JDG and product is JDG");
return false;
+ }
- // So we are as7/eap and need to check now if we have a JDG plugin's ISPN resource as child
- boolean found = false;
- for (ResourceType type: parent.getChildResourceTypes()) {
- if (type.getPlugin().equals("JDG") && type.getName().equals("Infinispan")) {
- found = true;
- }
+ if (!ourPluginTypeIsJdg && !isJdgProduct) {
+ if (log.isDebugEnabled())
+ log.debug("Ours is not JDG (" + ourType.toString() + ") and product is not JDG (" + productType + ")");
+ return false;
}
- return found;
+ return true;
}
}
commit 1b2ba60b043c4c9e8feff247dcb0b53f342b9371
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon Aug 13 15:07:10 2012 -0500
[BZ 847674] Prevent exceptions from bubbling up because that is an indication the server is still down after the restart. Consider a thrown exception just a failed attempt to connect to the server, equivalent to success == false response for the test operation.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
index 9bc01f2..ff55c8d 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
@@ -406,12 +406,19 @@ public abstract class BaseServerComponent<T extends ResourceComponent<?>> extend
int count = 0;
while (!up) {
Operation op = new ReadAttribute(new Address(), "release-version");
- Result res = getASConnection().execute(op);
- if (res.isSuccess()) { // If op succeeds, server is not down
- up = true;
- } else if (count > 20) {
- break;
+ try{
+ Result res = getASConnection().execute(op);
+ if (res.isSuccess()) { // If op succeeds, server is not down
+ up = true;
+ } else if (count > 20) {
+ break;
+ }
+ } catch (Exception e) {
+ //do absolutely nothing
+ //if an exception is thrown that means the server is still down, so consider this
+ //a single failed attempt, equivalent to res.isSuccess == false
}
+
if (!up) {
try {
Thread.sleep(1000); // Wait 1s
commit 35d9093ac3c6118d1fc9ad5a8eef3a6bce6fe398
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Aug 13 14:18:10 2012 -0400
- Fix issues with Filtering UNCOMMITTED resources in a few NamedQueries.
- Remove unnecessary decl of ResourceGroupManager in test class, use the base class var.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/Availability.java b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/Availability.java
index 6158a74..d8a1083 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/Availability.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/Availability.java
@@ -104,7 +104,8 @@ import org.rhq.core.domain.resource.Resource;
+ " WHERE av.resource.id IN ( SELECT ires.id " //
+ " FROM ResourceGroup rg " //
+ " JOIN rg.implicitResources ires " //
- + " WHERE rg.id = :groupId AND ires.inventoryStatus = 'COMMITTED' ) " //
+ + " WHERE rg.id = :groupId ) " //
+ + " AND av.resource.inventoryStatus = 'COMMITTED' " //
+ " AND ((av.startTime <= :start AND (av.endTime >= :start OR av.endTime IS NULL) ) " /* availability straddles :start */
+ " OR (av.startTime BETWEEN :start AND :end)) " /* interval straddles availability.startTime */
+ "ORDER BY av.startTime ASC"), //
@@ -113,6 +114,7 @@ import org.rhq.core.domain.resource.Resource;
+ " JOIN av.resource res JOIN res.parentResource parent JOIN res.resourceType type " //
+ " WHERE parent.id = :parentId " //
+ " AND type.id = :typeId " //
+ + " AND av.resource.inventoryStatus = 'COMMITTED' " //
+ " AND ((av.startTime <= :start AND (av.endTime >= :start OR av.endTime IS NULL)) " /* availability straddles :start */
+ " OR (av.startTime BETWEEN :start AND :end)) " /* interval straddles availability.startTime */
+ "ORDER BY av.startTime ASC"), //
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/ResourceGroup.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/ResourceGroup.java
index 7b30aaf..937a891 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/ResourceGroup.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/ResourceGroup.java
@@ -197,7 +197,8 @@ import org.rhq.core.domain.tagging.Tag;
+ " AND res.id NOT IN ( SELECT explicitRes.id " //
+ " FROM ResourceGroup rg " //
+ " JOIN rg.explicitResources explicitRes " //
- + " WHERE rg.id = :groupId AND explicitRes.inventoryStatus = 'COMMITTED') ") })
+ + " WHERE rg.id = :groupId ) " //
+ + " AND res.inventoryStatus = 'COMMITTED' ") })
@SequenceGenerator(name = "id", sequenceName = "RHQ_RESOURCE_GROUP_ID_SEQ")
@Table(name = "RHQ_RESOURCE_GROUP")
@XmlAccessorType(XmlAccessType.FIELD)
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/GroupWithUncommittedTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/GroupWithUncommittedTest.java
index 8ef992d..3c57e5c 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/GroupWithUncommittedTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/GroupWithUncommittedTest.java
@@ -24,7 +24,6 @@ import java.util.List;
import javax.persistence.Query;
import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.rhq.core.domain.authz.Permission;
@@ -39,7 +38,6 @@ 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.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.test.LargeGroupTestBase;
import org.rhq.enterprise.server.test.TestServerCommunicationsService;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -49,7 +47,6 @@ import org.rhq.enterprise.server.util.SessionTestHelper;
public class GroupWithUncommittedTest extends LargeGroupTestBase {
private static final boolean TESTS_ENABLED = true;
- private ResourceGroupManagerLocal rgMgr;
private LargeGroupEnvironment env;
private class GroupAvailCounts {
@@ -77,11 +74,6 @@ public class GroupWithUncommittedTest extends LargeGroupTestBase {
protected void setupMockAgentServices(TestServerCommunicationsService agentServiceContainer) {
}
- @BeforeMethod
- public void getManagers() {
- this.rgMgr = LookupUtil.getResourceGroupManager();
- }
-
/**
* Remove the group and all its members.
*/
@@ -104,7 +96,8 @@ public class GroupWithUncommittedTest extends LargeGroupTestBase {
SessionTestHelper.simulateLogin(env.normalSubject);
// these queries were tweeked to filter uncommitted - see BZ 820981
- PageList<ResourceGroupComposite> results = rgMgr.findResourceGroupComposites(env.normalSubject, null, null,
+ 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;
@@ -263,7 +256,7 @@ public class GroupWithUncommittedTest extends LargeGroupTestBase {
assert resConfigCount == gac.visibleTotal;
assert pluginConfigCount == gac.visibleTotal;
- int groupSize = rgMgr.getExplicitGroupMemberCount(env.compatibleGroup.getId());
+ int groupSize = resourceGroupManager.getExplicitGroupMemberCount(env.compatibleGroup.getId());
assert resConfigCount == groupSize;
assert pluginConfigCount == groupSize;
commit ef1a7865118a3a76f7ee0ea1e119ba03f28c34ca
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Fri Aug 10 15:31:52 2012 -0500
[BZ 828329] Adding inventory context to a resource context.
Squashed commit of the following:
commit 14b7dd184880140d74d4658ffa0e62a575f27c4f
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 7 16:03:33 2012 -0500
[BZ 828329] Minor documentation updates and rewording.
commit 7f5aa39c22688ee935b23d2dad767ff03c41dc96
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 7 14:45:31 2012 -0500
[BZ 828329] Removed plugin container specific classes. The regular will just block until the discovery processes completes, no data is returned to caller.
commit 2b17808e9bff072776c7ecada992d33c34203155
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon Aug 6 21:07:00 2012 -0500
[BZ 828329] The inventory context has now a deferred and a blocking method for requesting discovery. Also included are various other updates based on community feedback.
commit 816622e43c88c3b2bf751c1e2d9682d64556fdbb
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon Aug 6 10:38:34 2012 -0500
[BZ 828329] Added the possibility to start discovery scans from a resource context. The code executes a deffered service scan for children of the resource managed by the resource context.
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/InventoryContext.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/InventoryContext.java
new file mode 100644
index 0000000..ec1fab4
--- /dev/null
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/InventoryContext.java
@@ -0,0 +1,65 @@
+/*
+ * 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.core.pluginapi.inventory;
+
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public interface InventoryContext {
+
+ /**
+ * This method requests a deferred service discovery process for children of the resource. It requests the discovery
+ * process and returns immediately without waiting for results. The discovery process imports into inventory all discovered
+ * resources, so no further action is required from the caller.
+ *
+ * This method should be used by resources following an action (outside of create/delete children) that results
+ * in having additional children discoverable. A good example is an operation execution that enables extra functionality
+ * on the managed resource which in turn translates into having additional children available for management.
+ *
+ * Note: All services are discovered by the regular discovery process that runs every 24 hours. This method allows
+ * a resource to request an immediate run of the discovery process for child resources, rather than wait for the scheduled
+ * service discovery.
+ */
+ public void requestDeferredChildResourcesDiscovery();
+
+
+ /**
+ * This method requests a service discovery process for children of the resource. It schedules the discovery
+ * process and blocks until the discovery finishes. The discovery process imports into inventory all discovered
+ * resources, so no further action is required from the caller.
+ *
+ * This method should be used by resources following an action (outside of create/delete children) that results
+ * in having additional children discoverable. A good example is an operation execution that enables extra functionality
+ * on the managed resource which in turn translates into having additional children available for management. This method blocks
+ * until the discovery processes finishes, this includes committing resources to inventory. For additional processing,
+ * the calling resource can then request the list of child resources (it will include newly discovered resources too).
+ *
+ * Note: All services are discovered by the regular discovery process that runs every 24 hours. This method allows
+ * a resource to request an immediate run of the discovery process for child resources, rather than wait for the scheduled
+ * service discovery.
+ *
+ * @return discovered child resources
+ */
+ public void requestChildResourcesDiscovery();
+
+}
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java
index 4b21719..76ccf39 100644
--- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java
@@ -83,6 +83,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
private final OperationContext operationContext;
private final ContentContext contentContext;
private final AvailabilityContext availabilityContext;
+ private final InventoryContext inventoryContext;
private final PluginContainerDeployment pluginContainerDeployment;
private final ResourceTypeProcesses trackedProcesses;
@@ -152,7 +153,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
public ResourceContext(Resource resource, T parentResourceComponent, ResourceContext<?> parentResourceContext,
ResourceDiscoveryComponent<T> resourceDiscoveryComponent, SystemInfo systemInfo, File temporaryDirectory,
File dataDirectory, String pluginContainerName, EventContext eventContext, OperationContext operationContext,
- ContentContext contentContext, AvailabilityContext availabilityContext,
+ ContentContext contentContext, AvailabilityContext availabilityContext, InventoryContext inventoryContext,
PluginContainerDeployment pluginContainerDeployment) {
this.resourceKey = resource.getResourceKey();
@@ -177,6 +178,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
this.operationContext = operationContext;
this.contentContext = contentContext;
this.availabilityContext = availabilityContext;
+ this.inventoryContext = inventoryContext;
String parentResourceUuid = "";
if (resource.getParentResource() != null) {
@@ -505,6 +507,16 @@ public class ResourceContext<T extends ResourceComponent<?>> {
}
/**
+ * Returns an {@link InventoryContext} that allows the plugin to access inventory related functionality provided by the
+ * plugin container.
+ *
+ * @return the inventory context
+ */
+ public InventoryContext getInventoryContext() {
+ return inventoryContext;
+ }
+
+ /**
* @deprecated Use {@link AvailabilityContext#createAvailabilityCollectorRunnable(AvailabilityFacet, long)}
*/
public AvailabilityCollectorRunnable createAvailabilityCollectorRunnable(AvailabilityFacet availChecker,
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java
index 3c5b6a2..471978c 100644
--- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java
@@ -23,13 +23,13 @@
package org.rhq.core.pluginapi.upgrade;
import java.io.File;
-import java.util.concurrent.Executor;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.pluginapi.availability.AvailabilityContext;
import org.rhq.core.pluginapi.content.ContentContext;
import org.rhq.core.pluginapi.event.EventContext;
+import org.rhq.core.pluginapi.inventory.InventoryContext;
import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
import org.rhq.core.pluginapi.inventory.ResourceContext;
@@ -60,11 +60,11 @@ public class ResourceUpgradeContext<T extends ResourceComponent<?>> extends Reso
T parentResourceComponent, ResourceDiscoveryComponent<T> resourceDiscoveryComponent, SystemInfo systemInfo,
File temporaryDirectory, File dataDirectory, String pluginContainerName, EventContext eventContext,
OperationContext operationContext, ContentContext contentContext, AvailabilityContext availabilityContext,
- PluginContainerDeployment pluginContainerDeployment) {
+ InventoryContext inventoryContext, PluginContainerDeployment pluginContainerDeployment) {
super(resource, parentResourceComponent, parentResourceContext, resourceDiscoveryComponent, systemInfo,
temporaryDirectory, dataDirectory, pluginContainerName, eventContext, operationContext, contentContext,
- availabilityContext, pluginContainerDeployment);
+ availabilityContext, inventoryContext, pluginContainerDeployment);
this.resourceConfiguration = resource.getResourceConfiguration();
this.name = resource.getName();
diff --git a/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java b/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java
index fe194c9..118d514 100644
--- a/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java
+++ b/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java
@@ -86,7 +86,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null,
- mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null);
+ mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -152,7 +152,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parent1ResourceContext, null,
- null, mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null);
+ null, mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -206,7 +206,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null,
- mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null);
+ mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -260,7 +260,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null,
- mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null);
+ mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -314,7 +314,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null,
- mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null);
+ mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -377,7 +377,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parent1ResourceContext, null,
- null, mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null);
+ null, mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getFutureChildResourceDataDirectory(inputChildResourceKey);
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryContextImpl.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryContextImpl.java
new file mode 100644
index 0000000..460a827
--- /dev/null
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryContextImpl.java
@@ -0,0 +1,57 @@
+/*
+ * 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.core.pc.inventory;
+
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.pc.PluginContainer;
+import org.rhq.core.pluginapi.inventory.InventoryContext;
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public class InventoryContextImpl implements InventoryContext {
+
+ private final Resource resource;
+
+ /**
+ * @param resource resource
+ */
+ public InventoryContextImpl(Resource resource) {
+ this.resource = resource;
+ }
+
+ /* (non-Javadoc)
+ * @see org.rhq.core.pluginapi.inventory.InventoryContext#discoverChildResources()
+ */
+ @Override
+ public void requestDeferredChildResourcesDiscovery() {
+ PluginContainer.getInstance().getInventoryManager().executeServiceScanDeferred(resource);
+ }
+
+ /* (non-Javadoc)
+ * @see org.rhq.core.pluginapi.inventory.InventoryContext#requestChildResourcesDiscovery()
+ */
+ @Override
+ public void requestChildResourcesDiscovery() {
+ PluginContainer.getInstance().getInventoryManager().executeServiceScanImmediately(resource);
+ }
+}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
index 8cd3859..b3f7fa9 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
@@ -108,6 +108,7 @@ import org.rhq.core.pluginapi.event.EventContext;
import org.rhq.core.pluginapi.inventory.ClassLoaderFacet;
import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
+import org.rhq.core.pluginapi.inventory.InventoryContext;
import org.rhq.core.pluginapi.inventory.ManualAddFacet;
import org.rhq.core.pluginapi.inventory.ProcessScanResult;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
@@ -575,10 +576,29 @@ public class InventoryManager extends AgentService implements ContainerService,
}
}
+ @NotNull
+ public InventoryReport executeServiceScanImmediately(Resource resource) {
+ try {
+ RuntimeDiscoveryExecutor discoveryExecutor = new RuntimeDiscoveryExecutor(this, this.configuration,
+ resource);
+ return inventoryThreadPoolExecutor.submit((Callable<InventoryReport>) discoveryExecutor).get();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Service scan execution was interrupted", e);
+ } catch (ExecutionException e) {
+ // Should never happen, reports are always generated, even if they're just to report the error
+ throw new RuntimeException("Unexpected exception", e);
+ }
+ }
+
public void executeServiceScanDeferred() {
inventoryThreadPoolExecutor.submit((Callable<InventoryReport>) this.serviceScanExecutor);
}
+ public void executeServiceScanDeferred(Resource resource) {
+ RuntimeDiscoveryExecutor discoveryExecutor = new RuntimeDiscoveryExecutor(this, this.configuration, resource);
+ inventoryThreadPoolExecutor.submit((Callable<InventoryReport>) discoveryExecutor);
+ }
+
/** this will NOT send a availability report up to the server! */
public AvailabilityReport executeAvailabilityScanImmediately(boolean changedOnlyReport) {
return executeAvailabilityScanImmediately(changedOnlyReport, false);
@@ -1296,7 +1316,7 @@ public class InventoryManager extends AgentService implements ContainerService,
/**
* Get the parent resource's children, ensuring we use the resource container version of the resource, because
* the container's resource is guaranteed to be up to date.
- *
+ *
* @param parentResource
* @return the children. parentResouce children if there is no container. May be empty. Not null.
*/
@@ -1304,13 +1324,13 @@ public class InventoryManager extends AgentService implements ContainerService,
return getContainerChildren(parentResource, getResourceContainer(parentResource));
}
- /**
+ /**
* Get the parent resource's children, ensuring we use the resource container version of the resource, because
* the container's resource is guaranteed to be up to date.
- *
+ *
* @param parentResource
* @param parentContainer
- * @return the children, empty if parentContainer is null or there are no children. not null.
+ * @return the children, empty if parentContainer is null or there are no children. not null.
* @return the children, may be empty, not null.
*/
public Set<Resource> getContainerChildren(Resource parentResource, ResourceContainer container) {
@@ -1784,6 +1804,7 @@ public class InventoryManager extends AgentService implements ContainerService,
getOperationContext(resource), // for operation manager access
getContentContext(resource), // for content manager access
getAvailabilityContext(resource, this.availabilityCollectors), // for components that want to perform async avail checking
+ getInventoryContext(resource),
this.configuration.getPluginContainerDeployment()); // helps components make determinations of what to do
}
@@ -1803,6 +1824,7 @@ public class InventoryManager extends AgentService implements ContainerService,
getOperationContext(resource), // for operation manager access
getContentContext(resource), // for content manager access
getAvailabilityContext(resource, this.availabilityCollectors), // for components that want avail manager access
+ getInventoryContext(resource),
this.configuration.getPluginContainerDeployment()); // helps components make determinations of what to do
}
@@ -1853,7 +1875,7 @@ public class InventoryManager extends AgentService implements ContainerService,
return this.platform;
}
} else {
- // don't use container children here, the caller is providing the desired resources
+ // don't use container children here, the caller is providing the desired resources
for (Resource child : parent.getChildResources()) {
if (child != null && matches(resource, child)) {
return child;
@@ -2376,7 +2398,7 @@ public class InventoryManager extends AgentService implements ContainerService,
/**
* The resource upgrade should only occur during the {@link #initialize()} method and should be
* switched off at all other times.
- *
+ *
* @return true if resource upgrade is currently active, false otherwise
*/
public boolean isResourceUpgradeActive() {
@@ -2644,6 +2666,21 @@ public class InventoryManager extends AgentService implements ContainerService,
return availabilityContext;
}
+ /**
+ * Create inventory context for a resource.
+ *
+ * @param resource the resource
+ * @return the inventory context
+ */
+ private InventoryContext getInventoryContext(Resource resource) {
+ if (null == resource.getUuid() || resource.getUuid().isEmpty()) {
+ log.error("RESOURCE UUID IS NOT SET! Inventory features may not work!");
+ }
+
+ InventoryContext inventoryContext = new InventoryContextImpl(resource);
+ return inventoryContext;
+ }
+
private void updateResourceVersion(Resource resource, String version) {
String existingVersion = resource.getVersion();
boolean versionChanged = (existingVersion != null) ? !existingVersion.equals(version) : version != null;
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/bundle/BundleManagerTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/bundle/BundleManagerTest.java
index b6b39e0..4b37c89 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/bundle/BundleManagerTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/bundle/BundleManagerTest.java
@@ -478,7 +478,7 @@ public class BundleManagerTest {
@SuppressWarnings("unchecked")
private static class MockResourceContext extends ResourceContext {
public MockResourceContext(Resource resource) {
- super(resource, null, null, null, null, null, null, null, null, null, null, null, null);
+ super(resource, null, null, null, null, null, null, null, null, null, null, null, null, null);
}
}
}
\ No newline at end of file
diff --git a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
index 05ebc2f..daf5463 100644
--- a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
+++ b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
@@ -101,7 +101,8 @@ public class AntBundlePluginComponentTest {
resource.setUuid(UUID.randomUUID().toString());
@SuppressWarnings({ "rawtypes", "unchecked" })
ResourceContext<?> context = new ResourceContext(resource, null, null, null,
- SystemInfoFactory.createJavaSystemInfo(), tmpDir, null, "antBundleTestPC", null, null, null, null, null);
+ SystemInfoFactory.createJavaSystemInfo(), tmpDir, null, "antBundleTestPC", null, null, null, null, null,
+ null);
this.plugin.start(context);
}
diff --git a/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java b/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java
index b9622c6..050aa2e 100644
--- a/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java
+++ b/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java
@@ -52,6 +52,7 @@ import org.rhq.core.pc.availability.AvailabilityContextImpl;
import org.rhq.core.pc.content.ContentContextImpl;
import org.rhq.core.pc.event.EventContextImpl;
import org.rhq.core.pc.event.EventManager;
+import org.rhq.core.pc.inventory.InventoryContextImpl;
import org.rhq.core.pc.inventory.ResourceContainer;
import org.rhq.core.pc.operation.OperationContextImpl;
import org.rhq.core.pluginapi.availability.AvailabilityContext;
@@ -59,6 +60,7 @@ import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
import org.rhq.core.pluginapi.content.ContentContext;
import org.rhq.core.pluginapi.event.EventContext;
import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.InventoryContext;
import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
import org.rhq.core.pluginapi.inventory.ProcessScanResult;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
@@ -141,6 +143,7 @@ public abstract class ComponentTest {
private List<ProcessInfo> processInfo = Collections.emptyList();
private PluginDescriptor pluginDescriptor;
private AvailabilityContext availabilityContext;
+ private InventoryContext inventoryContext;
/**
@@ -277,11 +280,13 @@ public abstract class ComponentTest {
ResourceComponent component = (ResourceComponent) Class.forName(rclassname).newInstance();
availabilityContext = new AvailabilityContextImpl(cresource,availCollectorThreadPool);
+ inventoryContext = new InventoryContextImpl(cresource);
+
EventContext eventContext = new EventContextImpl(resource);
ResourceContext context = new ResourceContext(cresource, parentComponent,
null, rdc, systemInfo, temporaryDirectory, dataDirectory,
pluginContainerName, eventContext, operationContext, contentContext,
- availabilityContext, pluginContainerDeployment);
+ availabilityContext, inventoryContext, pluginContainerDeployment);
component.start(context);
components.put(component, cresource);
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
index 8b85deb..9bc01f2 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
@@ -540,6 +540,7 @@ public abstract class BaseServerComponent<T extends ResourceComponent<?>> extend
+ " server with key [" + context.getResourceKey() + "].");
context.getAvailabilityContext().requestAvailabilityCheck();
+ context.getInventoryContext().requestDeferredChildResourcesDiscovery();
return result;
}
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java
index 8ddb308..28a8688 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java
@@ -345,7 +345,8 @@ public class UploadAndDeployTest extends AbstractIntegrationTest {
resource.setUuid(UUID.randomUUID().toString());
StandaloneASComponent parentComponent = new StandaloneASComponent();
parentComponent.setConnection(getASConnection());
- ResourceContext context = new ResourceContext(resource,parentComponent,null,null,null,null,null,null,null,null,null,null,null);
+ ResourceContext context = new ResourceContext(resource, parentComponent, null, null, null, null, null, null,
+ null, null, null, null, null, null);
bc.start(context);
String bytes_value = uploadToAs(TEST_WAR_PATH);
@@ -379,7 +380,8 @@ public class UploadAndDeployTest extends AbstractIntegrationTest {
resource.setUuid(UUID.randomUUID().toString());
StandaloneASComponent parentComponent = new StandaloneASComponent();
parentComponent.setConnection(getASConnection());
- ResourceContext context = new ResourceContext(resource,parentComponent,null,null,null,null,null,null,null,null,null,null,null);
+ ResourceContext context = new ResourceContext(resource, parentComponent, null, null, null, null, null, null,
+ null, null, null, null, null, null);
bc.start(context);
String bytes_value = uploadToAs(TEST_WAR_PATH);
diff --git a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
index 511d686..610cb61 100644
--- a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
+++ b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
@@ -71,6 +71,7 @@ import org.rhq.core.pc.availability.AvailabilityContextImpl;
import org.rhq.core.pc.content.ContentContextImpl;
import org.rhq.core.pc.event.EventContextImpl;
import org.rhq.core.pc.event.EventManager;
+import org.rhq.core.pc.inventory.InventoryContextImpl;
import org.rhq.core.pc.inventory.ResourceContainer;
import org.rhq.core.pc.operation.OperationContextImpl;
import org.rhq.core.pluginapi.availability.AvailabilityContext;
@@ -78,6 +79,7 @@ import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
import org.rhq.core.pluginapi.content.ContentContext;
import org.rhq.core.pluginapi.event.EventContext;
import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.InventoryContext;
import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
import org.rhq.core.pluginapi.inventory.ProcessScanResult;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
@@ -294,12 +296,13 @@ public abstract class ComponentTest {
ResourceComponent component = (ResourceComponent) Class.forName(rclassname).newInstance();
AvailabilityContext availContext = new AvailabilityContextImpl(cresource,availCollectorThreadPool);
+ InventoryContext inventoryContext = new InventoryContextImpl(cresource);
EventContext eventContext = new EventContextImpl(resource);
ResourceContext context = new ResourceContext(cresource, parentComponent,
null, rdc, systemInfo, temporaryDirectory, dataDirectory,
pluginContainerName, eventContext, operationContext, contentContext,
- availContext, pluginContainerDeployment);
+ availContext, inventoryContext,pluginContainerDeployment);
component.start(context);
components.put(component, cresource);
diff --git a/modules/plugins/oracle/src/test/java/org/rhq/plugins/oracle/ComponentTest.java b/modules/plugins/oracle/src/test/java/org/rhq/plugins/oracle/ComponentTest.java
index dfee1b6..569bd09 100644
--- a/modules/plugins/oracle/src/test/java/org/rhq/plugins/oracle/ComponentTest.java
+++ b/modules/plugins/oracle/src/test/java/org/rhq/plugins/oracle/ComponentTest.java
@@ -36,12 +36,14 @@ import org.rhq.core.pc.availability.AvailabilityContextImpl;
import org.rhq.core.pc.content.ContentContextImpl;
import org.rhq.core.pc.event.EventContextImpl;
import org.rhq.core.pc.event.EventManager;
+import org.rhq.core.pc.inventory.InventoryContextImpl;
import org.rhq.core.pc.operation.OperationContextImpl;
import org.rhq.core.pc.upgrade.plugins.multi.base.NothingDiscoveringDiscoveryComponent;
import org.rhq.core.pluginapi.availability.AvailabilityContext;
import org.rhq.core.pluginapi.content.ContentContext;
import org.rhq.core.pluginapi.event.EventContext;
import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.InventoryContext;
import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
import org.rhq.core.pluginapi.inventory.ResourceContext;
@@ -133,9 +135,11 @@ public abstract class ComponentTest {
ResourceDiscoveryComponent resourceDiscoveryComponent = new NothingDiscoveringDiscoveryComponent();
EventContext eventContext = new EventContextImpl(resource);
AvailabilityContext availContext = new AvailabilityContextImpl(resource, Executors.newCachedThreadPool());
+ InventoryContext inventoryContext = new InventoryContextImpl(resource);
ResourceContext context = new ResourceContext(resource, parentResourceComponent, parentResourceContext,
resourceDiscoveryComponent, systemInfo, temporaryDirectory, dataDirectory, pluginContainerName,
- eventContext, operationContext, contentContext, availContext, pluginContainerDeployment);
+ eventContext, operationContext, contentContext, availContext, inventoryContext,
+ pluginContainerDeployment);
component.start(context);
resourceDiscoveryContext = new ResourceDiscoveryContext(resourceType, parentResourceComponent, context,
@@ -169,9 +173,10 @@ public abstract class ComponentTest {
EventContext eventContext = new EventContextImpl(resource);
AvailabilityContext availContext = new AvailabilityContextImpl(resource, Executors.newCachedThreadPool());
+ InventoryContext inventoryContext = new InventoryContextImpl(resource);
ResourceContext context = new ResourceContext(resource, component, parentContext, resourceDiscoveryComponent,
systemInfo, temporaryDirectory, dataDirectory, pluginContainerName, eventContext, operationContext,
- contentContext, availContext, pluginContainerDeployment);
+ contentContext, availContext, inventoryContext, pluginContainerDeployment);
ResourceDiscoveryContext resourceDiscoveryContext = new ResourceDiscoveryContext(resourceType, component,
context, systemInfo, Collections.emptyList(), Collections.emptyList(), pluginContainerName,
pluginContainerDeployment);
@@ -200,9 +205,10 @@ public abstract class ComponentTest {
EventContext eventContext = new EventContextImpl(resource);
AvailabilityContext availContext = new AvailabilityContextImpl(resource, Executors.newCachedThreadPool());
+ InventoryContext inventoryContext = new InventoryContextImpl(resource);
ResourceContext context = new ResourceContext(cresource, parentComponent, parentContext,
resourceDiscoveryComponent, systemInfo, temporaryDirectory, dataDirectory, pluginContainerName,
- eventContext, operationContext, contentContext, availContext, pluginContainerDeployment);
+ eventContext, operationContext, contentContext, availContext, inventoryContext, pluginContainerDeployment);
component.start(context);
components.put(component, cresource);
diff --git a/modules/plugins/snmptrapd/src/test/java/org/rhq/plugins/snmptrapd/ComponentTest.java b/modules/plugins/snmptrapd/src/test/java/org/rhq/plugins/snmptrapd/ComponentTest.java
index b023609..cd90737 100644
--- a/modules/plugins/snmptrapd/src/test/java/org/rhq/plugins/snmptrapd/ComponentTest.java
+++ b/modules/plugins/snmptrapd/src/test/java/org/rhq/plugins/snmptrapd/ComponentTest.java
@@ -24,11 +24,13 @@ import org.rhq.core.pc.availability.AvailabilityContextImpl;
import org.rhq.core.pc.content.ContentContextImpl;
import org.rhq.core.pc.event.EventContextImpl;
import org.rhq.core.pc.event.EventManager;
+import org.rhq.core.pc.inventory.InventoryContextImpl;
import org.rhq.core.pc.operation.OperationContextImpl;
import org.rhq.core.pc.upgrade.plugins.multi.base.NothingDiscoveringDiscoveryComponent;
import org.rhq.core.pluginapi.availability.AvailabilityContext;
import org.rhq.core.pluginapi.content.ContentContext;
import org.rhq.core.pluginapi.event.EventContext;
+import org.rhq.core.pluginapi.inventory.InventoryContext;
import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
import org.rhq.core.pluginapi.inventory.ResourceContext;
@@ -97,9 +99,10 @@ public abstract class ComponentTest {
ContentContext contentContext = new ContentContextImpl(0);
PluginContainerDeployment pluginContainerDeployment = null;
AvailabilityContext availContext = new AvailabilityContextImpl(resource, Executors.newCachedThreadPool());
+ InventoryContext inventoryContext = new InventoryContextImpl(resource);
ResourceContext context = new ResourceContext(resource, parentResourceComponent, parentResourceContext,
resourceDiscoveryComponent, systemInfo, temporaryDirectory, dataDirectory, pluginContainerName,
- eventContext, operationContext, contentContext, availContext, pluginContainerDeployment);
+ eventContext, operationContext, contentContext, availContext, inventoryContext, pluginContainerDeployment);
Assert.assertNotNull(context.getEventContext());
component.start(context);
}
commit 579776f3fe66776d0b013bf13eba8114fe7ff89a
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu Aug 9 13:53:35 2012 -0700
Remove unused parameter. Ended up not needing the criteria parameter.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
index 9f640dc..e269475 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
@@ -26,7 +26,6 @@ import static org.rhq.enterprise.gui.coregui.client.inventory.groups.ResourceGro
import static org.rhq.enterprise.gui.coregui.client.inventory.groups.ResourceGroupDataSourceField.PLUGIN;
import static org.rhq.enterprise.gui.coregui.client.inventory.groups.ResourceGroupDataSourceField.TYPE;
-import java.util.ArrayList;
import java.util.List;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -126,8 +125,7 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
processResponse(request.getRequestId(), response);
}
- private PageList<ResourceGroupComposite> filterEmptyMemberGroups(ResourceGroupCriteria groupCriteria,
- PageList<ResourceGroupComposite> result){
+ private PageList<ResourceGroupComposite> filterEmptyMemberGroups(PageList<ResourceGroupComposite> result){
PageList<ResourceGroupComposite> pageList = new PageList<ResourceGroupComposite>(result.getPageControl());
@@ -141,7 +139,7 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
}
public void onSuccess(PageList<ResourceGroupComposite> result) {
- PageList<ResourceGroupComposite> filteredResult = filterEmptyMemberGroups(criteria,result);
+ PageList<ResourceGroupComposite> filteredResult = filterEmptyMemberGroups(result);
response.setData(buildRecords(filteredResult));
response.setTotalRows(filteredResult.getTotalSize()); // for paging to work we have to specify size of full result set
processResponse(request.getRequestId(), response);
commit 901fc3d0ecb9b5f800c6c5c3dc59dabebb61a87c
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed Aug 8 17:33:53 2012 -0700
Take out search optimization of not doing a search if the search term is the same as the last search. This is causing some stickiness and sometimes the search doesnt run if it was already cached and it thinks it has done a search but it hasnt (probably because of timing issues).
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
index f56c81e..e0e004d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
@@ -48,7 +48,6 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message;
*/
public class BasicSearchStrategy extends AbstractSearchStrategy {
- private String lastExpression;
public BasicSearchStrategy(EnhancedSearchBar searchBar) {
super(searchBar);
@@ -175,12 +174,9 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
private void getTabAwareSearchSuggestions(final SearchSubsystem searchSubsystem, final String expression,
int caretPosition) {
- if (null != expression && expression.equals(lastExpression)) {
- // short-circuit if we dont really need to do a search
- Log.debug("search tab aware Suggestions: ignoring duplicate search for: " + expression);
+ if(null == expression || expression.isEmpty()){
return;
}
- lastExpression = expression;
final long suggestStart = System.currentTimeMillis();
commit 6b621264526d1490d423e14e482ff18b3ea2f85f
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri Aug 10 09:24:26 2012 -0400
[Bug 847138 - RFE: Add indication that resource tree is loading or expanding]
Replace the default TreeGrid loading message, which was weak and only showed
up briefly at initial tree creation, with more robust loading... message
display when loading, expanding or updating the tree. This helps situations
where fairly large tree load/updates take place, typically due to large
numbers of siblings or Autogroup creation/manipulation.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
index 2a5b827..5c58a70 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
@@ -35,6 +35,7 @@ import com.smartgwt.client.data.fields.DataSourceTextField;
import com.smartgwt.client.rpc.RPCResponse;
import com.smartgwt.client.types.DSDataFormat;
import com.smartgwt.client.types.DSProtocol;
+import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.tree.Tree;
import com.smartgwt.client.widgets.tree.TreeGrid;
import com.smartgwt.client.widgets.tree.TreeNode;
@@ -71,10 +72,12 @@ public class ResourceTreeDatasource extends DataSource {
// the encompassing grid. It's unfortunate to have the DS know about the encompassing TreeGrid
// but we have a situation in which a new AG node needs to be able to access its parent TreeNode by ID.
private TreeGrid treeGrid;
+ private Label loadingLabel;
private ResourceGWTServiceAsync resourceService = GWTServiceLookup.getResourceService();
- public ResourceTreeDatasource(List<Resource> initialData, List<Resource> lockedData, TreeGrid treeGrid) {
+ public ResourceTreeDatasource(List<Resource> initialData, List<Resource> lockedData, TreeGrid treeGrid,
+ Label loadingLabel) {
this.setClientOnly(false);
this.setDataProtocol(DSProtocol.CLIENTCUSTOM);
this.setDataFormat(DSDataFormat.CUSTOM);
@@ -82,6 +85,7 @@ public class ResourceTreeDatasource extends DataSource {
this.initialData = initialData;
this.lockedData = (null != lockedData) ? lockedData : new ArrayList<Resource>();
this.treeGrid = treeGrid;
+ this.loadingLabel = loadingLabel;
DataSourceField idDataField = new DataSourceTextField("id", MSG.common_title_id());
idDataField.setPrimaryKey(true);
@@ -131,6 +135,8 @@ public class ResourceTreeDatasource extends DataSource {
public void executeFetch(final String requestId, final DSRequest request, final DSResponse response) {
//final long start = System.currentTimeMillis();
+ loadingLabel.show();
+
final String parentResourceId = request.getCriteria().getAttribute("parentId");
//com.allen_sauer.gwt.log.client.Log.info("All attributes: " + Arrays.toString(request.getCriteria().getAttributes()));
@@ -148,6 +154,8 @@ public class ResourceTreeDatasource extends DataSource {
processResponse(requestId, response);
}
+ loadingLabel.hide();
+
} else {
Log.debug("ResourceTreeDatasource: Loading Resource [" + parentResourceId + "]...");
@@ -161,6 +169,8 @@ public class ResourceTreeDatasource extends DataSource {
CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_loadFailed_children(), caught);
response.setStatus(RPCResponse.STATUS_FAILURE);
processResponse(requestId, response);
+
+ loadingLabel.hide();
}
public void onSuccess(PageList<Resource> result) {
@@ -182,6 +192,8 @@ public class ResourceTreeDatasource extends DataSource {
TreeNode[] treeNodes = buildNodes(result, lockedData, treeGrid);
response.setData(treeNodes);
processResponse(requestId, response);
+
+ loadingLabel.hide();
}
});
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
index 2393f8d..c38e77a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
@@ -43,6 +43,7 @@ import com.smartgwt.client.data.DSCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.types.SelectionStyle;
+import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.SelectionChangedHandler;
import com.smartgwt.client.widgets.grid.events.SelectionEvent;
@@ -79,6 +80,7 @@ import org.rhq.core.domain.resource.composite.ResourcePermission;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.LinkManager;
import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
import org.rhq.enterprise.gui.coregui.client.ViewId;
@@ -111,6 +113,7 @@ public class ResourceTreeView extends LocatableVLayout {
private TreeGrid treeGrid;
private String selectedNodeId;
+ private Label loadingLabel;
private Resource rootResource;
@@ -131,11 +134,17 @@ public class ResourceTreeView extends LocatableVLayout {
@Override
public void onInit() {
+ // manually handle a loading... message at initial load and also subsequent fetches
+ loadingLabel = new Label(MSG.common_msg_loading());
+ loadingLabel.setIcon(ImageManager.getLoadingIcon());
+ loadingLabel.setHeight(20);
+ loadingLabel.hide();
+ addMember(loadingLabel);
+
// TODO (ips): Are we intentionally avoiding calling super.onInit() here? If so, why?
}
private void buildTree() {
-
treeGrid = new CustomResourceTreeGrid(getLocatorId());
treeGrid.setOpenerImage("resources/dir.png");
@@ -149,6 +158,8 @@ public class ResourceTreeView extends LocatableVLayout {
treeGrid.setShowRollOver(false);
treeGrid.setSortField("name");
treeGrid.setShowHeader(false);
+ // disable what the tree grid may do, defer to loadingLabel to handle all of our cases
+ treeGrid.setLoadingDataMessage(null);
treeGrid.setLeaveScrollbarGap(false);
@@ -190,12 +201,15 @@ public class ResourceTreeView extends LocatableVLayout {
disable();
try {
+ loadingLabel.show();
getAutoGroupBackingGroup(agNode, new AsyncCallback<ResourceGroup>() {
public void onSuccess(ResourceGroup result) {
+ loadingLabel.hide();
renderAutoGroup(result);
}
public void onFailure(Throwable caught) {
+ loadingLabel.hide();
// Make sure to re-enable ourselves.
enable();
CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_loadFailed_selection(),
@@ -203,6 +217,7 @@ public class ResourceTreeView extends LocatableVLayout {
}
});
} catch (RuntimeException re) {
+ loadingLabel.hide();
// Make sure to re-enable ourselves.
enable();
CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_loadFailed_selection(), re);
@@ -281,9 +296,11 @@ public class ResourceTreeView extends LocatableVLayout {
criteria.addFilterResourceTypeId(agNode.getResourceType().getId());
criteria.addFilterAutoGroupParentResourceId(agNode.getParentResource().getId());
criteria.addFilterVisible(false);
+ loadingLabel.show();
resourceGroupService.findResourceGroupsByCriteria(criteria, new AsyncCallback<PageList<ResourceGroup>>() {
public void onFailure(Throwable caught) {
+ loadingLabel.hide();
callback.onFailure(new RuntimeException(MSG.view_tree_common_loadFailed_node(), caught));
}
@@ -299,11 +316,13 @@ public class ResourceTreeView extends LocatableVLayout {
resourceGroupService.createPrivateResourceGroup(backingGroup, childIds,
new AsyncCallback<ResourceGroup>() {
public void onFailure(Throwable caught) {
+ loadingLabel.hide();
callback.onFailure(new RuntimeException(MSG.view_tree_common_loadFailed_create(),
caught));
}
public void onSuccess(ResourceGroup result) {
+ loadingLabel.hide();
// store a map entry from backingGroupId to AGTreeNode so we can easily
// get back to this node given the id of the backing group (from the viewpath)
autoGroupNodeMap.put(result.getId(), agNode);
@@ -322,11 +341,13 @@ public class ResourceTreeView extends LocatableVLayout {
resourceGroupService.setAssignedResources(backingGroup.getId(), childIds, false,
new AsyncCallback<Void>() {
public void onFailure(Throwable caught) {
+ loadingLabel.hide();
callback.onFailure(new RuntimeException(MSG.view_tree_common_loadFailed_update(),
caught));
}
public void onSuccess(Void result) {
+ loadingLabel.hide();
callback.onSuccess(backingGroup);
}
});
@@ -895,7 +916,6 @@ public class ResourceTreeView extends LocatableVLayout {
// This is the case where the tree was previously loaded and we get fired to look at a different
// node in the same tree and just have to switch the selection
updateSelection(isRefresh);
-
} else {
// This is for cases where we have to load the tree fresh including down to the currently visible node
loadTree(selectedResourceId, true, null);
@@ -913,10 +933,12 @@ public class ResourceTreeView extends LocatableVLayout {
final ResourceGWTServiceAsync resourceService = GWTServiceLookup.getResourceService();
// This is an expensive call, but loads all nodes that are visible in the tree given a selected resource
+ loadingLabel.show();
resourceService.getResourceLineageAndSiblings(selectedResourceId,
new AsyncCallback<List<ResourceLineageComposite>>() {
public void onFailure(Throwable caught) {
+ loadingLabel.hide();
boolean resourceDoesNotExist = caught.getMessage().contains("ResourceNotFoundException");
// If a Resource with the specified id does not exist, don't emit an error, since
// ResourceDetailView.loadSelectedItem() will take care of emitting one.
@@ -953,7 +975,8 @@ public class ResourceTreeView extends LocatableVLayout {
setRootResource(root);
// seed datasource with initial resource list and which ancestor resources are locked
- ResourceTreeDatasource dataSource = new ResourceTreeDatasource(lineage, lockedData, treeGrid);
+ ResourceTreeDatasource dataSource = new ResourceTreeDatasource(lineage, lockedData, treeGrid,
+ loadingLabel);
treeGrid.setDataSource(dataSource);
addMember(treeGrid);
@@ -963,6 +986,8 @@ public class ResourceTreeView extends LocatableVLayout {
public void execute(DSResponse response, Object rawData, DSRequest request) {
Log.info("Done fetching data for tree.");
+ loadingLabel.hide();
+
if (updateSelection) {
updateSelection();
}
@@ -994,6 +1019,8 @@ public class ResourceTreeView extends LocatableVLayout {
treeGrid.getTree().linkNodes(
ResourceTreeDatasource.buildNodes(lineage, lockedData, treeGrid));
+ loadingLabel.hide();
+
TreeNode selectedNode = treeGrid.getTree().findById(selectedNodeId);
if (selectedNode != null && updateSelection) {
updateSelection();
@@ -1029,9 +1056,11 @@ public class ResourceTreeView extends LocatableVLayout {
criteria.addFilterId(selectedAutoGroupId);
criteria.addFilterVisible(false);
criteria.fetchResourceType(true);
+ loadingLabel.show();
resourceGroupService.findResourceGroupsByCriteria(criteria, new AsyncCallback<PageList<ResourceGroup>>() {
public void onFailure(Throwable caught) {
+ loadingLabel.hide();
CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_loadFailed_node(), caught);
}
@@ -1043,6 +1072,7 @@ public class ResourceTreeView extends LocatableVLayout {
loadTree(backingGroup.getAutoGroupParentResource().getId(), false, new AsyncCallback<Void>() {
public void onFailure(Throwable caught) {
+ loadingLabel.hide();
CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_loadFailed_children(), caught);
}
@@ -1053,6 +1083,8 @@ public class ResourceTreeView extends LocatableVLayout {
AutoGroupTreeNode agNode = (AutoGroupTreeNode) treeGrid.getTree().findById(selectedNodeId);
autoGroupNodeMap.put(backingGroup.getId(), agNode);
updateSelection();
+
+ loadingLabel.hide();
}
});
}
@@ -1061,7 +1093,6 @@ public class ResourceTreeView extends LocatableVLayout {
}
public void renderView(ViewPath viewPath) {
-
ViewId currentViewId = viewPath.getCurrent();
String currentViewIdPath = currentViewId.getPath();
if ("AutoGroup".equals(currentViewIdPath)) {
commit 23b39b07ef79025500b063dd223dc243e12c5004
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri Aug 10 09:20:16 2012 -0400
Get rid of annoying maven warning by specifying to use the latest release
version.
diff --git a/pom.xml b/pom.xml
index 0ae9a07..36b9c62 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1317,6 +1317,7 @@
<plugin>
<groupId>com.googlecode.maven-overview-plugin</groupId>
<artifactId>maven-overview-plugin</artifactId>
+ <version>RELEASE</version>
</plugin>
<!--
commit 71dc21ab49b1a986e4364e52e0fa6f817c96bf89
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu Aug 9 16:09:41 2012 -0400
BZ 838670 Mark more configuration elements as r/w, as underyling AS allows that now.
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 6a6a40c..d27d432 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
@@ -397,33 +397,34 @@
<!ENTITY datasourceReadWriteConfiguration '
<resource-configuration>
- <c:simple-property name="connection-url" required="true" type="string" readOnly="true" description="The JDBC driver connection URL"/>
- <c:simple-property name="driver-name" required="true" type="string" description="Name of the (existing) JDBC driver to use" readOnly="true">
+ <c:simple-property name="connection-url" required="true" type="string" readOnly="false" description="The JDBC driver connection URL"/>
+ <c:simple-property name="driver-name" required="true" type="string" description="Name of the (existing) JDBC driver to use" readOnly="false">
<c:option-source target="resource" expression="type=^Deployment$" filter=".*\.jar"/>
</c:simple-property>
- <c:simple-property name="driver-class" required="false" type="string" readOnly="true" description="The fully qualified name of the JDBC driver class"/>
- <c:simple-property name="jndi-name" required="true" type="string" readOnly="true" description="Specifies the JNDI name for the datasource"/>
+ <c:simple-property name="driver-class" required="false" type="string" readOnly="false" description="The fully qualified name of the JDBC driver class"/>
+ <c:simple-property name="jndi-name" required="true" type="string" readOnly="false" description="Specifies the JNDI name for the datasource"/>
<c:simple-property name="driver" required="false" type="string" readOnly="true" description="Defines the JDBC driver the datasource should use with this format: driver-name>#major-version.minor-version where driver-name is the fully qualified name of the JDBC driver class"/>
- <c:simple-property name="user-name" type="string" readOnly="true" required="false" description="Specify the username used when creating a new connection."/>
- <c:simple-property name="password" type="password" readOnly="true" required="false" description="Specify the password used when creating a new connection."/>
- <c:simple-property name="new-connection-sql" type="string" readOnly="true" required="false" description="Specifies an SQL statement to execute whenever a connection is added to the connection pool."/>
- <c:simple-property name="url-delimiter" type="string" readOnly="true" description="Specifies the delimiter for URLs in connection-url for HA datasources" required="false"/>
- <c:simple-property name="url-selector-strategy-class-name" type="string" readOnly="true" description="A class that implements org.jboss.jca.adapters.jdbc.URLSelectorStrategy" required="false"/>
- <c:simple-property name="use-java-context" type="boolean" readOnly="true" required="false" description="Setting this to false will bind the DataSource into global JNDI;"/>
+ <c:simple-property name="user-name" type="string" readOnly="false" required="false" description="Specify the username used when creating a new connection."/>
+ <c:simple-property name="password" type="password" readOnly="false" required="false" description="Specify the password used when creating a new connection."/>
+ <c:simple-property name="new-connection-sql" type="string" readOnly="false" required="false" description="Specifies an SQL statement to execute whenever a connection is added to the connection pool."/>
+ <c:simple-property name="url-delimiter" type="string" readOnly="false" description="Specifies the delimiter for URLs in connection-url for HA datasources" required="false"/>
+ <c:simple-property name="url-selector-strategy-class-name" type="string" readOnly="false" description="A class that implements org.jboss.jca.adapters.jdbc.URLSelectorStrategy" required="false"/>
+ <c:simple-property name="use-java-context" type="boolean" readOnly="false" required="false" default="true" description="Setting this to false will bind the DataSource into global JNDI;"/>
<c:simple-property name="enabled" type="boolean" readOnly="true" required="false" description="Specifies if the datasource should be enabled"/>
+ <c:simple-property name="jta" type="boolean" readOnly="false" required="false" default="true" description="Enable JTA integration"/>
<c:simple-property name="max-pool-size" type="integer" readOnly="false" required="false" description="The max-pool-size element indicates the maximum number of connections for a pool. No more connections will be created in each sub-pool."/>
<c:simple-property name="min-pool-size" type="integer" readOnly="false" required="false" description="The min-pool-size element 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."/>
- <c:simple-property name="pool-prefill" type="boolean" readOnly="false" required="false" description="Whether to attempt to prefill the connection pool. Changing this value require a server restart."/>
- <c:simple-property name="pool-use-strict-min" type="boolean" readOnly="false" required="false" description="Define if the min-pool-size should be considered a strictly."/>
- <c:simple-property name="security-domain" required="false" type="string" readOnly="true" description="Indicates Subject (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 handleauthentication. This name correlates to the JAAS login-config.xml descriptor application-policy/name attribute."/>
- <c:simple-property name="reauth-plugin-class-name" required="false" type="string" readOnly="true" description="re-authentication plugin implementation provided for specific purpose (i.e vendor)"/>
+ <c:simple-property name="pool-prefill" type="boolean" readOnly="false" required="false" default="false" description="Whether to attempt to prefill the connection pool. Changing this value require a server restart."/>
+ <c:simple-property name="pool-use-strict-min" type="boolean" readOnly="false" required="false" default="false" description="Define if the min-pool-size should be considered a strictly."/>
+ <c:simple-property name="security-domain" required="false" type="string" readOnly="false" description="Indicates Subject (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 handleauthentication. This name correlates to the JAAS login-config.xml descriptor application-policy/name attribute."/>
+ <c:simple-property name="reauth-plugin-class-name" required="false" type="string" readOnly="false" description="re-authentication plugin implementation provided for specific purpose (i.e vendor)"/>
<!--
<c:map-property name="reauth-plugin-properties" description="properties for reauthentication plugin passed to the implementation provided for specific purpose (i.e vendor)">
read-only
configuration
</c:map-property>
-->
- <c:simple-property name="flush-strategy" required="false" type="string" readOnly="true" description="Specifies how the pool should be flush in case of an error." default="FailingConnectionOnly" defaultValue="FailingConnectionOnly">
+ <c:simple-property name="flush-strategy" required="false" type="string" readOnly="false" description="Specifies how the pool should be flush in case of an error." default="FailingConnectionOnly" defaultValue="FailingConnectionOnly">
<c:property-options>
<c:option value="FailingConnectionOnly"/>
<c:option value="IdleConnections"/>
@@ -431,17 +432,24 @@
</c:property-options>
</c:simple-property>
- <c:simple-property name="prepared-statements-cacheSize" type="long" readOnly="true" required="false" description="The number of prepared statements per connection in an LRU cache"/>
- <c:simple-property name="share-prepared-statements" type="boolean" readOnly="true" required="false" description="Whether to share prepare statements, i.e. whether asking for same statement twice without closing uses the same underlying prepared statement"/>
- <c:simple-property name="track-statements" type="string" readOnly="true" required="false" description="Whether to check for unclosed statements when a connection is returned to the pool and result sets are closed when a statement is closed/return to the prepared statement cache. valid values are: false - do not track statements and results true - track statements and result sets and warn when they are not closed nowarn - track statements but do no warn about them being unclosed"/>
- <c:simple-property name="allocation-retry" type="integer" readOnly="true" required="false" description="The allocation retry element indicates the number of times that allocating a connection should be tried before throwing an exception."/>
- <c:simple-property name="allocation-retry-wait-millis" type="long" readOnly="true" required="false" description="Indicates the time in milliseconds to wait between retrying to allocate a connection."/>
+ <c:simple-property name="allow-multiple-users" type="boolean" required="false" readOnly="false" description="Specifies if multiple users will access the datasource through the getConnection(user, password) method and hence if the internal pool type should account for that"/>
+ <c:simple-property name="prepared-statements-cacheSize" type="long" readOnly="false" required="false" description="The number of prepared statements per connection in an LRU cache"/>
+ <c:simple-property name="share-prepared-statements" type="boolean" readOnly="false" required="false" default="false" description="Whether to share prepare statements, i.e. whether asking for same statement twice without closing uses the same underlying prepared statement"/>
+ <c:simple-property name="track-statements" type="string" readOnly="false" required="false" description="Whether to check for unclosed statements when a connection is returned to the pool and result sets are closed when a statement is closed/return to the prepared statement cache. valid values are: false - do not track statements and results true - track statements and result sets and warn when they are not closed nowarn - track statements but do no warn about them being unclosed">
+ <c:property-options>
+ <c:option value="false"/>
+ <c:option value="true"/>
+ <c:option value="NOWARN"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="allocation-retry" type="integer" readOnly="false" required="false" description="The allocation retry element indicates the number of times that allocating a connection should be tried before throwing an exception."/>
+ <c:simple-property name="allocation-retry-wait-millis" type="long" readOnly="false" required="false" description="Indicates the time in milliseconds to wait between retrying to allocate a connection."/>
<c:simple-property name="blocking-timeout-wait-millis" type="long" readOnly="false" required="false" description="The blocking-timeout-millis element 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."/>
<c:simple-property name="idle-timeout-minutes" type="long" readOnly="false" required="false" description="The idle-timeout-minutes elements 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. Changing this value require a server restart."/>
- <c:simple-property name="query-timeout" type="long" readOnly="true" required="false" description="Any configured query timeout in seconds The default is no timeout"/>
- <c:simple-property name="use-try-lock" type="long" readOnly="true" required="false" description="Any configured timeout for internal locks on the resource adapter objects in seconds"/>
- <c:simple-property name="set-tx-query-timeout" type="boolean" readOnly="true" required="false" description="Whether to set the query timeout based on the time remaining until transaction timeout, any configured query timeout will be used if there is no transaction."/>
- <c:simple-property name="transaction-isolation" type="string" readOnly="true" required="false" description="Set java.sql.Connection transaction isolation level to use. The constants defined by transaction-isolation-values are the possible transaction isolation levels.">
+ <c:simple-property name="query-timeout" type="long" readOnly="false" required="false" description="Any configured query timeout in seconds The default is no timeout"/>
+ <c:simple-property name="use-try-lock" type="long" readOnly="false" required="false" description="Any configured timeout for internal locks on the resource adapter objects in seconds"/>
+ <c:simple-property name="set-tx-query-timeout" type="boolean" readOnly="false" required="false" default="false" description="Whether to set the query timeout based on the time remaining until transaction timeout, any configured query timeout will be used if there is no transaction."/>
+ <c:simple-property name="transaction-isolation" type="string" readOnly="false" required="false" description="Set java.sql.Connection transaction isolation level to use. The constants defined by transaction-isolation-values are the possible transaction isolation levels.">
<c:property-options>
<c:option value="TRANSACTION_READ_UNCOMMITTED"/>
<c:option value="TRANSACTION_READ_COMMITTED"/>
@@ -450,16 +458,16 @@
<c:option value="TRANSACTION_NONE"/>
</c:property-options>
</c:simple-property>
- <c:simple-property name="check-valid-connection-sql" type="string" readOnly="true" 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:simple-property name="exception-sorter-class-name" type="string" readOnly="true" required="false" description="An org.jboss.jca.adapters.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"/>
- <c:simple-property name="stale-connection-checker-class-name" type="string" readOnly="true" required="false" description="An org.jboss.jca.adapters.jdbc.StaleConnectionChecker that provides a boolean isStaleConnection(SQLException e) method which if it it returns true will wrap the exception in an org.jboss.jca.adapters.jdbc.StaleConnectionException"/>
- <c:simple-property name="valid-connection-checker-class-name" type="string" readOnly="true" required="false" description="An org.jboss.jca.adapters.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."/>
- <c:simple-property name="background-validation-minutes" type="long" readOnly="false" required="false" description="The background-validation-minutes element specifies the amount of time, in minutes, that background validation will run. Changing this value require a server restart."/>
- <c:simple-property name="background-validation" type="boolean" readOnly="false" required="false" description="An element to specify that connections should be validated on a background thread versus being validated prior to use. Changing this value require a server restart."/>
+ <c:simple-property name="check-valid-connection-sql" type="string" readOnly="false" 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:simple-property name="exception-sorter-class-name" type="string" readOnly="false" required="false" description="An org.jboss.jca.adapters.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"/>
+ <c:simple-property name="stale-connection-checker-class-name" type="string" readOnly="false" required="false" description="An org.jboss.jca.adapters.jdbc.StaleConnectionChecker that provides a boolean isStaleConnection(SQLException e) method which if it it returns true will wrap the exception in an org.jboss.jca.adapters.jdbc.StaleConnectionException"/>
+ <c:simple-property name="valid-connection-checker-class-name" type="string" readOnly="false" required="false" description="An org.jboss.jca.adapters.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."/>
+ <c:simple-property name="background-validation-millis" type="long" readOnly="false" required="false" description="The background-validation-minutes element specifies the amount of time, in minutes, that background validation will run. Changing this value require a server restart."/>
+ <c:simple-property name="background-validation" type="boolean" readOnly="false" required="false" default="false" description="An element to specify that connections should be validated on a background thread versus being validated prior to use. Changing this value require a server restart."/>
<c:simple-property name="use-fast-fail" type="boolean" readOnly="false" required="false" description="Whether fail a connection allocation on the first connection if it is invalid (true) or keep trying until the pool is exhausted of all potential connections (false)"/>
- <c:simple-property name="validate-on-match" type="boolean" readOnly="true" required="false" description="The validate-on-match element indicates whether or not connection level validation should be done when a connection factory attempts to match a managed connection for a given set. This is typically exclusive to the use of background validation"/>
- <c:simple-property name="spy" type="boolean" readOnly="true" required="false" description="whatever spy or not the jdbc connection"/>
- <c:simple-property name="use-ccm" type="boolean" readOnly="true" required="false" description="Enable the use of a cached connection manager"/>
+ <c:simple-property name="validate-on-match" type="boolean" readOnly="false" required="false" default="false" description="The validate-on-match element indicates whether or not connection level validation should be done when a connection factory attempts to match a managed connection for a given set. This is typically exclusive to the use of background validation"/>
+ <c:simple-property name="spy" type="boolean" readOnly="false" required="false" defaultValue="false" description="whatever spy or not the jdbc connection"/>
+ <c:simple-property name="use-ccm" type="boolean" readOnly="false" required="false" description="Enable the use of a cached connection manager"/>
<c:group name="children:connection-properties:pname+-" displayName="Connection Properties">
<c:list-property name="*1" displayName="Connection Property" readOnly="false" required="false">
<c:map-property name="*:pname" displayName="Name" readOnly="false">
commit 77cee38075da30754fa6081dcf5cfe239f547a71
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu Aug 9 14:20:52 2012 -0400
BZ 839320 When a property is required and the user has not explicitly choosen a value and there is a defaultValue, use this.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
index 366f840..86ba37a 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
@@ -500,7 +500,25 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
entry = new SimpleEntry<String, Object>(realName, null);
}
} else {
- Object o = getObjectWithType(propertyDefinition,property.getStringValue());
+ Object o;
+/*
+ If no value is given in the property and the property is required,
+ we'll take the default value from the definition. This can e.g. happen
+ when you have
+ <c:simple-property name="mode" required="true" type="string" readOnly="false" default="SYNC" defaultValue="SYNC">
+ <c:property-options>
+ <c:option value="SYNC"/>
+ <c:option value="ASYNC"/>
+ </c:property-options>
+ </c:simple-property>
+ and the user chooses to just keep the default choice in the ui
+*/
+
+ if (property.getStringValue()==null && propertyDefinition.isRequired()) {
+ o = getObjectWithType(propertyDefinition,propertyDefinition.getDefaultValue());
+ } else {
+ o = getObjectWithType(propertyDefinition,property.getStringValue());
+ }
entry = new SimpleEntry<String, Object>(name, o);
}
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 77bacfb..6a6a40c 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
@@ -11350,7 +11350,7 @@
</c:property-options>
</c:simple-property>
<c:simple-property name="jndi-name" required="false" type="string" readOnly="false" description="The jndi-name to which to bind this cache instance."/>
- <c:simple-property name="mode" required="true" type="string" readOnly="false" default="SYNC" description="Sets the clustered cache mode, ASYNC for asynchronous operation, or SYNC for synchronous operation.">
+ <c:simple-property name="mode" required="true" type="string" readOnly="false" default="SYNC" defaultValue="SYNC" description="Sets the clustered cache mode, ASYNC for asynchronous operation, or SYNC for synchronous operation.">
<c:property-options>
<c:option value="SYNC"/>
<c:option value="ASYNC"/>
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java
index ba2f13c..21e3d5f 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java
@@ -862,4 +862,90 @@ public class ConfigurationUpdatingTest extends AbstractConfigurationHandlingTest
assert cop.numberOfSteps() == 1 : "One step was expected, but got " + cop.numberOfSteps();
}
+
+ /**
+ * Test that if a property is required and has a defaultValue and the user just uses this,
+ * we actually pass this default to the operation, as e.g. the CreateResourceReport may not
+ * include the default value.
+ * @throws Exception If anything goes wrong
+ */
+ public void testSimpleWithDefault1() throws Exception {
+
+ ConfigurationDefinition definition = loadDescriptor("simpleWithDefault1");
+
+ FakeConnection connection = new FakeConnection();
+
+ ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(definition, connection, null);
+
+ Configuration conf = new Configuration();
+ PropertySimple ps = new PropertySimple("mode",null);
+ conf.put(ps);
+
+ CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, new Address());
+
+ assert cop.numberOfSteps() == 1;
+ Operation step1 = cop.step(0);
+ assert step1.getOperation().equals("write-attribute");
+ Map<String, Object> props = step1.getAdditionalProperties();
+ assert props.size() == 2;
+ assert props.get("name").equals("mode");
+ assert props.get("value").equals("SYNC"); // the defaultValue
+ }
+
+ /**
+ * Check that if a property is required and has no defaultValue, but the user provides a value,
+ * that the user provided value ends up in the operation
+ * @throws Exception
+ */
+ public void testSimpleWithDefault2() throws Exception {
+
+ ConfigurationDefinition definition = loadDescriptor("simpleWithDefault2");
+
+ FakeConnection connection = new FakeConnection();
+
+ ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(definition, connection, null);
+
+ Configuration conf = new Configuration();
+ PropertySimple ps = new PropertySimple("mode","ASYNC");
+ conf.put(ps);
+
+ CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, new Address());
+
+ assert cop.numberOfSteps() == 1;
+ Operation step1 = cop.step(0);
+ assert step1.getOperation().equals("write-attribute");
+ Map<String, Object> props = step1.getAdditionalProperties();
+ assert props.size() == 2;
+ assert props.get("name").equals("mode");
+ assert props.get("value").equals("ASYNC"); // the user provided value
+ }
+
+ /**
+ * Check that if a property is required and has no defaultValue, and the user provides null
+ * as value, that we set null
+ * @throws Exception
+ */
+ public void testSimpleWithDefault3() throws Exception {
+
+ ConfigurationDefinition definition = loadDescriptor("simpleWithDefault2");
+
+ FakeConnection connection = new FakeConnection();
+
+ ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(definition, connection, null);
+
+ Configuration conf = new Configuration();
+ PropertySimple ps = new PropertySimple("mode",null);
+ conf.put(ps);
+
+ CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, new Address());
+
+ assert cop.numberOfSteps() == 1;
+ Operation step1 = cop.step(0);
+ assert step1.getOperation().equals("write-attribute");
+ Map<String, Object> props = step1.getAdditionalProperties();
+ assert props.size() == 2;
+ assert props.get("name").equals("mode");
+ assert props.get("value")==null; // no value
+ }
+
}
diff --git a/modules/plugins/jboss-as-7/src/test/resources/test-plugin.xml b/modules/plugins/jboss-as-7/src/test/resources/test-plugin.xml
index 4350230..f10f52b 100644
--- a/modules/plugins/jboss-as-7/src/test/resources/test-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/test/resources/test-plugin.xml
@@ -290,6 +290,37 @@
</resource-configuration>
</server>
+ <server name="simpleWithDefault1"
+ class="BaseComponent"
+ discovery="SubsystemDiscovery">
+
+ <resource-configuration>
+ <c:simple-property name="mode" required="true" type="string" readOnly="false" default="SYNC" defaultValue="SYNC" >
+ <c:property-options>
+ <c:option value="SYNC"/>
+ <c:option value="ASYNC"/>
+ </c:property-options>
+ </c:simple-property>
+ </resource-configuration>
+
+ </server>
+
+ <server name="simpleWithDefault2"
+ class="BaseComponent"
+ discovery="SubsystemDiscovery">
+
+ <resource-configuration>
+ <c:simple-property name="mode" required="true" type="string" readOnly="false" default="SYNC" >
+ <c:property-options>
+ <c:option value="SYNC"/>
+ <c:option value="ASYNC"/>
+ </c:property-options>
+ </c:simple-property>
+ </resource-configuration>
+
+ </server>
+
+
<!-- Simple c:group entries from descriptor with no special handling. -->
<service name="simpleGroupNoSpecial"
class="BaseComponent"
@@ -327,4 +358,6 @@
</resource-configuration>
</service>
+
+
</plugin>
\ No newline at end of file
commit 396b48fde3613c359b49ca4b776ee18fa39f3865
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Aug 9 09:12:57 2012 -0400
[Bug 847014 - Resource tree not complete when more than 200 children]
Allow an unlimited number of children when expanding the tree node. Although
this may create a large vertical expansion, it may also be what the
user wants. See BZ comments for more on the approach and alternatives
but basically, take this [easy] approach until it's clear that users, or UX,
want something else.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
index c072e13..2a5b827 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
@@ -43,6 +43,7 @@ import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceSubCategory;
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.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.Messages;
@@ -152,6 +153,8 @@ public class ResourceTreeDatasource extends DataSource {
ResourceCriteria criteria = new ResourceCriteria();
criteria.addFilterParentResourceId(Integer.parseInt(parentResourceId));
+ // we don't need sorting since we get everything and the tree nodes are already sorted
+ criteria.setPageControl(PageControl.getUnlimitedInstance());
resourceService.findResourcesByCriteria(criteria, new AsyncCallback<PageList<Resource>>() {
public void onFailure(Throwable caught) {
commit c1d401ff6c2b495cb599dfb66e0dd157b6442614
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Aug 9 09:05:46 2012 -0400
[Bug 838683 - If RHQ server is down, UI shows "Server returned FAILURE with no error message"]
More recent versions of Firefox, and possibly other browsers, have changed
the request's response code in this situation. Added updated handling.
Also, fixed an I18N issue.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/rpc/TrackingRequestCallback.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/rpc/TrackingRequestCallback.java
index f461f6e..2702814 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/rpc/TrackingRequestCallback.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/rpc/TrackingRequestCallback.java
@@ -18,7 +18,6 @@
*/
package org.rhq.enterprise.gui.coregui.client.util.rpc;
-import java.util.logging.Logger;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.Response;
@@ -38,6 +37,7 @@ public class TrackingRequestCallback implements RequestCallback {
private long start = System.currentTimeMillis();
private static final int STATUS_CODE_OK = 200;
+ private static final int STATUS_CODE_ERROR_INTERNET_NO_RESPONSE = 0;
private static final int STATUS_CODE_ERROR_INTERNET_CANNOT_CONNECT = 12029;
private static final int STATUS_CODE_ERROR_INTERNET_CONNECTION_ABORTED = 12030;
@@ -69,7 +69,7 @@ public class TrackingRequestCallback implements RequestCallback {
statusCode = response.getStatusCode();
statusText = response.getStatusText();
} catch (Throwable t) {
- // If the server is unreachable or has terminated firefox will generate a JavaScript exception
+ // If the server is unreachable or has terminated firefox may generate a JavaScript exception
// when trying to read the response object. Let the user know the server is unreachable.
// (http://helpful.knobs-dials.com/index.php/0x80004005_%28NS_ERROR_FAILURE%2...
if (UserSessionManager.isLoggedIn()) {
@@ -90,13 +90,15 @@ public class TrackingRequestCallback implements RequestCallback {
callback.onResponseReceived(request, response);
break;
+ // these status codes are known to be returned from various browsers when the server is lost or not responding
+ case STATUS_CODE_ERROR_INTERNET_NO_RESPONSE:
case STATUS_CODE_ERROR_INTERNET_CANNOT_CONNECT:
case STATUS_CODE_ERROR_INTERNET_CONNECTION_ABORTED:
RPCTracker.getInstance().failCall(this);
// If the server is unreachable or has terminated, and the user is still logged in,
// let them know the server is now unreachable.
if (UserSessionManager.isLoggedIn()) {
- CoreGUI.getErrorHandler().handleError("Server unreachable and may be down");
+ CoreGUI.getErrorHandler().handleError(CoreGUI.getMessages().view_core_serverUnreachable());
}
break;
commit 58c9ee2d6dd34ebce6b96aed0cbc35da27374165
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Thu Aug 9 13:16:53 2012 +0200
Fixing the typo in constructor and bad usage of this constructor in 1 test
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java
index 35c9367..84018a8 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java
@@ -95,7 +95,7 @@ public class BundleCriteria extends TaggedCriteria {
}
public void addFilterBundleTypeName(String filterBundleTypeName) {
- this.filterName = filterBundleTypeName;
+ this.filterBundleTypeName = filterBundleTypeName;
}
public void addFilterDescription(String filterDescription) {
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java
index a4d43b8..1621dac 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java
@@ -952,7 +952,7 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// return bundle "two" using all criteria and with all optional data
c.addFilterId(b.getId());
c.addFilterName(b.getName());
- c.addFilterBundleTypeName(b.getName());
+ c.addFilterBundleTypeName(b.getBundleType().getName());
c.fetchBundleVersions(true);
c.fetchRepo(true);
bundles = bundleManager.findBundlesByCriteria(overlord, c);
commit 21e61a1588663c97975580003c00dfd8cbc20798
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Thu Aug 9 13:12:03 2012 +0200
[BZ 822795 - Search filter not working in bundle deployment wizard] Added filtering by the name of the bundle.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java
index 037bc10..eaa4371 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java
@@ -23,6 +23,7 @@ import java.util.LinkedHashMap;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.Criteria;
+import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
@@ -76,7 +77,7 @@ public class BundleSelector extends AbstractSelector<Bundle, BundleCriteria> {
}
protected RPCDataSource<Bundle, BundleCriteria> getDataSource() {
- return new BundlesDataSource();
+ return new SelectedBundlesDataSource();
}
protected Criteria getLatestCriteria(DynamicForm availableFilterForm) {
@@ -94,4 +95,15 @@ public class BundleSelector extends AbstractSelector<Bundle, BundleCriteria> {
protected String getItemTitle() {
return MSG.common_title_bundles();
}
+
+ public class SelectedBundlesDataSource extends BundlesDataSource {
+ @Override
+ protected BundleCriteria getFetchCriteria(final DSRequest request) {
+ BundleCriteria result = super.getFetchCriteria(request);
+ if (null != result) {
+ result.setStrict(false);
+ }
+ return result;
+ }
+ }
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesDataSource.java
index f8389b4..42a3e0d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesDataSource.java
@@ -90,28 +90,12 @@ public class BundlesDataSource extends RPCDataSource<Bundle, BundleCriteria> {
@Override
protected BundleCriteria getFetchCriteria(final DSRequest request) {
BundleCriteria criteria = new BundleCriteria();
-
- if (request.getCriteria().getValues().get("tagNamespace") != null) {
- criteria.addFilterTagNamespace((String) request.getCriteria().getValues().get("tagNamespace"));
- }
-
- if (request.getCriteria().getValues().get("tagSemantic") != null) {
- criteria.addFilterTagSemantic((String) request.getCriteria().getValues().get("tagSemantic"));
- }
-
- if (request.getCriteria().getValues().get("tagName") != null) {
- criteria.addFilterTagName((String) request.getCriteria().getValues().get("tagName"));
- }
-
- if (request.getCriteria().getValues().get("bundleType") != null) {
- criteria.addFilterBundleTypeId(Integer.valueOf(request.getCriteria().getValues().get("bundleType")
- .toString()));
- }
-
- // TODO: this doesn't work like I think it should, figure out how to search on the name column
- // if (request.getCriteria().getValues().get("search") != null) {
- // criteria.setSearchExpression(request.getCriteria().getValues().get("search").toString());
- // }
+ criteria.addFilterTagNamespace(getFilter(request, "tagNamespace", String.class));
+ criteria.addFilterTagSemantic(getFilter(request, "tagSemantic", String.class));
+ criteria.addFilterTagName(getFilter(request, "tagName", String.class));
+ criteria.addFilterBundleTypeId(getFilter(request, "bundleType", Integer.class));
+ criteria.addFilterTagSemantic(getFilter(request, "tagSemantic", String.class));
+ criteria.addFilterName(getFilter(request, "search", String.class));
return criteria;
}
commit 88c286048d73a963eb2e2debd1009d8ed0d595b0
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Aug 8 16:04:19 2012 -0500
[BZ 837510] Prevent the edge case by retrieving the clustered property from AS5 only when the first metric collection occurs. Also marked the getter deprecated to prevent further use of the property outside of this component.
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/WebApplicationContextComponent.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/WebApplicationContextComponent.java
index 6eb7e7e..07708b7 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/WebApplicationContextComponent.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/WebApplicationContextComponent.java
@@ -82,7 +82,7 @@ public class WebApplicationContextComponent extends ManagedComponentComponent {
private String servletComponentNamesRegex;
private ResponseTimeLogParser logParser;
- private boolean clustered;
+ private Boolean clustered;
@Override
public void start(ResourceContext<ProfileServiceComponent<?>> resourceContext) throws Exception {
@@ -97,17 +97,6 @@ public class WebApplicationContextComponent extends ManagedComponentComponent {
this.logParser.setExcludes(responseTimeConfig.getExcludes());
this.logParser.setTransforms(responseTimeConfig.getTransforms());
}
-
- try {
- ManagedProperty distributableProp = getManagedComponent().getProperty(DISTRIBUTABLE_MANAGED_PROPERTY);
- if (distributableProp != null) {
- Boolean distributable = (Boolean) getInnerValue(distributableProp.getValue());
- clustered = distributable != null && distributable.booleanValue();
- }
- } catch (Exception e) {
- log.warn("Failed to determine whether the web app context " + resourceContext.getResourceKey()
- + " is clustered or not.", e);
- }
}
@Override
@@ -144,8 +133,14 @@ public class WebApplicationContextComponent extends ManagedComponentComponent {
// TODO: Communicate this error back to the server for display in the GUI.
}
} else if (metricName.equals(CLUSTERED_TRAIT)) {
- MeasurementDataTrait trait = new MeasurementDataTrait(request, Boolean.toString(clustered));
- report.addData(trait);
+ if(clustered == null){
+ retrieveClusteredProperty();
+ }
+
+ if (clustered != null) {
+ MeasurementDataTrait trait = new MeasurementDataTrait(request, clustered.toString());
+ report.addData(trait);
+ }
} else {
String metricNameToUse = metricName;
if (clustered && !"runState".equals(metricName)) {
@@ -170,10 +165,33 @@ public class WebApplicationContextComponent extends ManagedComponentComponent {
}
}
+ /**
+ * @deprecated The clustered property should be retrieved by the individual component in the
+ * specific use case that requires it. Leaving this method for backwards compatibility
+ * with plugins that use the AS5 plugin and also use reflection.
+ */
+ @Deprecated
public boolean isClustered() {
+ if (clustered == null) {
+ return false;
+ }
+
return clustered;
}
+ private void retrieveClusteredProperty() {
+ try {
+ ManagedProperty distributableProp = getManagedComponent().getProperty(DISTRIBUTABLE_MANAGED_PROPERTY);
+ if (distributableProp != null) {
+ Boolean distributable = (Boolean) getInnerValue(distributableProp.getValue());
+ clustered = distributable != null && distributable.booleanValue();
+ }
+ } catch (Exception e) {
+ log.warn("Failed to determine whether the web app context " + this.getResourceContext().getResourceKey()
+ + " is clustered or not.", e);
+ }
+ }
+
private Double getServletMetric(ManagementView managementView, String metricName) throws Exception {
ComponentType servletComponentType = MoreKnownComponentTypes.MBean.Servlet.getType();
//Set<ManagedComponent> servletComponents = managementView.getMatchingComponents(this.servletComponentNamesRegex,
commit 15552573391da403073ea1c27a8a9a5ffc969e65
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Wed Aug 8 11:45:51 2012 -0700
[BZ 845389 - Group without members with unknown status appears in every availability search result] Get rid of superfluous empty groups that show up as unknown availability.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
index 72f25a4..9f640dc 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
@@ -26,6 +26,7 @@ import static org.rhq.enterprise.gui.coregui.client.inventory.groups.ResourceGro
import static org.rhq.enterprise.gui.coregui.client.inventory.groups.ResourceGroupDataSourceField.PLUGIN;
import static org.rhq.enterprise.gui.coregui.client.inventory.groups.ResourceGroupDataSourceField.TYPE;
+import java.util.ArrayList;
import java.util.List;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -50,6 +51,7 @@ import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
@@ -110,7 +112,7 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
}
@Override
- public void executeFetch(final DSRequest request, final DSResponse response, ResourceGroupCriteria criteria) {
+ public void executeFetch(final DSRequest request, final DSResponse response, final ResourceGroupCriteria criteria ) {
groupService.findResourceGroupCompositesByCriteria(criteria,
new AsyncCallback<PageList<ResourceGroupComposite>>() {
public void onFailure(Throwable caught) {
@@ -123,10 +125,25 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
response.setStatus(RPCResponse.STATUS_FAILURE);
processResponse(request.getRequestId(), response);
}
+
+ private PageList<ResourceGroupComposite> filterEmptyMemberGroups(ResourceGroupCriteria groupCriteria,
+ PageList<ResourceGroupComposite> result){
+
+ PageList<ResourceGroupComposite> pageList = new PageList<ResourceGroupComposite>(result.getPageControl());
+
+ for (ResourceGroupComposite rgc : result) {
+ if (rgc.getExplicitCount() > 0 ){
+ pageList.add(rgc);
+ }
+ }
+
+ return pageList;
+ }
public void onSuccess(PageList<ResourceGroupComposite> result) {
- response.setData(buildRecords(result));
- response.setTotalRows(result.getTotalSize()); // for paging to work we have to specify size of full result set
+ PageList<ResourceGroupComposite> filteredResult = filterEmptyMemberGroups(criteria,result);
+ response.setData(buildRecords(filteredResult));
+ response.setTotalRows(filteredResult.getTotalSize()); // for paging to work we have to specify size of full result set
processResponse(request.getRequestId(), response);
}
});
commit 8ead20e62a892e10b12ed70c20a8b1c4e55ff024
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Tue Aug 7 14:27:26 2012 -0700
Add i18n messages for ResourceGroupCompositeDataSource
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
index 2abefa1..72f25a4 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
@@ -47,6 +47,7 @@ import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.ImageManager;
+import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
@@ -57,6 +58,8 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message;
*/
public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGroupComposite, ResourceGroupCriteria> {
+ private static final Messages MSG = CoreGUI.getMessages();
+
public static final String FILTER_GROUP_IDS = "resourceGroupIds";
ResourceGroupGWTServiceAsync groupService = GWTServiceLookup.getResourceGroupService();
@@ -112,7 +115,7 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
new AsyncCallback<PageList<ResourceGroupComposite>>() {
public void onFailure(Throwable caught) {
if (caught.getMessage().contains("SearchExpressionException")) {
- Message message = new Message("Invalid search expression.", Message.Severity.Error);
+ Message message = new Message(MSG.search_invalid_search_expression(), Message.Severity.Error);
CoreGUI.getMessageCenter().notify(message);
} else {
CoreGUI.getErrorHandler().handleError(MSG.view_inventory_groups_loadFailed(), caught);
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index a558db1..f9b75f3 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -413,6 +413,7 @@ filter_from_date = From
filter_to_date = To
group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+search_invalid_search_expression = Invalid search expression.
search_failed_to_save_search = Failed to Save Search: {0}
search_failed_to_retrieve_saved_search = Failed to retrieve saved search
search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index b146b3d..11c4488 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -432,6 +432,7 @@ filter_from_date = Od
filter_to_date = Do
group_tree_groupOfResourceType = Skupina: [{0}]
group_tree_partialClusterTooltip = {0} z {1} Älenů skupiny má "{2}" zdroj
+##search_invalid_search_expression = Invalid search expression.
##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 7b9effe..71d8367 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -397,6 +397,7 @@ filter_from_date = Von
filter_to_date = Bis
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} der {1} Gruppenmitglieder haben eine ''{2}'' Ressource
+##search_invalid_search_expression = Invalid search expression.
##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index b7c191e..33e39c8 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -410,6 +410,7 @@ filter_from_date = éå§
filter_to_date = çµäº
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {1} ã®äžã® {0} ã°ã«ãŒãã¡ã³ããŒã ''{2}'' ãªãœãŒã¹ãæã£ãŠããŸã
+##search_invalid_search_expression = Invalid search expression.
##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 72b2f34..2c1af7e 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -416,6 +416,7 @@ favorites_resources = Recursos Favoritos
##filter_to_date = To
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+##search_invalid_search_expression = Invalid search expression.
##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 5a44858..29a3fa6 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -403,6 +403,7 @@
#filter_from_date = From
#filter_to_date = To
#group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+##search_invalid_search_expression = Invalid search expression.
##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 6ae9e47..cd7f97f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -405,6 +405,7 @@ favorites_resources = \u8d44\u6e90\u6536\u85cf\u5939
##filter_to_date = To
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = \u9664\u53bb {1},{0}\u7684\u7ec4\u6210\u5458\u62e5\u6709 \u4e00\u4e2a''{2}''\u8d44\u6e90
+##search_invalid_search_expression = Invalid search expression.
##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
commit b97ed4379723df4bd78d5a101094ada80097025e
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Aug 8 11:37:36 2012 -0500
[BZ 836527] Added a create content method for backwards compatiblity with the SOA-P plugin.
diff --git a/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/util/FileContentDelegate.java b/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/util/FileContentDelegate.java
index f82b5ec..6b967b8 100644
--- a/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/util/FileContentDelegate.java
+++ b/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/util/FileContentDelegate.java
@@ -84,15 +84,14 @@ public class FileContentDelegate {
}
/**
- * Creates a new package described by the specified details. The destination of the content in the provided input
- * stream will be determined by the package name.
+ * Creates a new package described by the specified details. The destination of the content in the provided
+ * file will be determined by the package name.
*
* @param details describes the package being created
- * @param content content to be written for the package. NOTE this Stream will be closed by this method.
+ * @param sourceContentFile content file to be written for the package.
* @param unzip if <code>true</code>, the content stream will be treated like a ZIP file and be unzipped as
* it is written, using the package name as the base directory; if <code>false</code> the
* @param createBackup If <code>true</code>, the original file will be backed up to file.bak
- * @param shaString the SHA-256 of the specified input stream
*/
public void createContent(PackageDetails details, File sourceContentFile, boolean unzip, boolean createBackup) {
File destinationContentFile = getPath(details);
@@ -115,6 +114,37 @@ public class FileContentDelegate {
}
/**
+ * Creates a new package described by the specified details. The destination of the content in the provided input
+ * stream will be determined by the package name.
+ *
+ * @param details describes the package being created
+ * @param content content to be written for the package. NOTE this Stream will be closed by this method.
+ * @param unzip if <code>true</code>, the content stream will be treated like a ZIP file and be unzipped as
+ * it is written, using the package name as the base directory; if <code>false</code> the
+ * @param createBackup If <code>true</code>, the original file will be backed up to file.bak
+ * @deprecated Method deprecated because of SHA256 computations. Method added only for backwards compatibility with SOA-P plugin.
+ * Replaced by {@link #createContent(PackageDetails, File, boolean, boolean)}
+ */
+ @Deprecated
+ public void createContent(PackageDetails details, InputStream content, boolean unzip, boolean createBackup) {
+ File destinationContentFile = getPath(details);
+ try {
+ if (createBackup) {
+ moveToBackup(destinationContentFile, ".bak");
+ }
+ if (unzip) {
+ ZipUtil.unzipFile(content, destinationContentFile);
+ computeAndSaveSHA(destinationContentFile);
+ } else {
+ FileUtil.writeFile(content, destinationContentFile);
+ }
+ details.setFileName(destinationContentFile.getPath());
+ } catch (IOException e) {
+ throw new RuntimeException("Error creating artifact from details: " + destinationContentFile, e);
+ }
+ }
+
+ /**
* Try to move the passed contentFile to a backup named contentFile + suffix
* @param contentFile File object pointing to the original file
* @param suffix the suffix to tack on
commit 581324eeb3d32f4d8879d4749423fbde0f76de8c
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Aug 8 13:41:26 2012 +0200
[BZ 846623] - When creating the "child" alert definitions of group or template alert definitions, pass the real user that creates the alert def and circumvent authz.
This behaves exactly the same as before but instead of bypassing the authz by passing the overlord when creating the child alert,
a new local SLSB method is used that doesn't perform the authz checks and can therefore receive the original user that request the creation of the group/template
alert def.
This is good for the CLI alert sender that, when creating an alert script to be run as "myself", checks if the user creating the alert def is the same as the one set
to run it.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
index c4fdcda..927ae74 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
@@ -196,9 +196,23 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
return results;
}
+ @Override
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public int createDependentAlertDefinition(Subject subject, AlertDefinition alertDefinition, int resourceId)
+ throws InvalidAlertDefinitionException {
+
+ return createAlertDefinitionInternal(subject, alertDefinition, resourceId, false);
+ }
+
+ @Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public int createAlertDefinition(Subject subject, AlertDefinition alertDefinition, Integer resourceId)
throws InvalidAlertDefinitionException {
+
+ return createAlertDefinitionInternal(subject, alertDefinition, resourceId, true);
+ }
+
+ private int createAlertDefinitionInternal(Subject subject, AlertDefinition alertDefinition, Integer resourceId, boolean checkPerms) throws InvalidAlertDefinitionException {
checkAlertDefinition(subject, alertDefinition, resourceId);
// if this is an alert definition, set up the link to a resource
@@ -212,7 +226,7 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
}
// after the resource is set up (in the case of non-templates), we can use the checkPermission on it
- if (checkPermission(subject, alertDefinition) == false) {
+ if (checkPerms && checkPermission(subject, alertDefinition) == false) {
if (alertDefinition.getResourceType() != null) {
throw new PermissionException("User [" + subject.getName()
+ "] does not have permission to create alert templates for type ["
@@ -265,7 +279,7 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
return alertDefinition.getId();
}
-
+
private void fixRecoveryId(AlertDefinition definition) {
try {
if (definition.getParentId() != 0 && definition.getRecoveryId() != 0) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
index d663198..81f0ac0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
@@ -48,6 +48,25 @@ public interface AlertDefinitionManagerLocal {
int createAlertDefinition(Subject subject, AlertDefinition alertDefinition, Integer resourceId)
throws InvalidAlertDefinitionException;
+ /**
+ * This is exactly the same as {@link #createAlertDefinition(Subject, AlertDefinition, Integer)} but
+ * assumes the resource is part of a group (or has given resource type for templates) for which
+ * a group or template alert definition is being created.
+ * <p>
+ * This method assumes the caller already checked the subject has permissions to create a group or template alert
+ * definition on a group / resource type the resource is member of.
+ * <p>
+ * In another words this method is a helper to
+ * {@link GroupAlertDefinitionManagerLocal#createGroupAlertDefinitions(Subject, AlertDefinition, Integer)} and
+ * {@link AlertTemplateManagerLocal#createAlertTemplate(Subject, AlertDefinition, Integer)}.
+ *
+ * @param subject the user that is creating the group or template alert definition
+ * @param alertDefinition the alert definition on the resource
+ * @param resourceId the resource
+ * @return the id of the newly created alert definition
+ */
+ int createDependentAlertDefinition(Subject subject, AlertDefinition alertDefinition, int resourceId);
+
boolean isEnabled(Integer definitionId);
boolean isTemplate(Integer definitionId);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
index 5b4ad77..cda1e0f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
@@ -128,7 +128,6 @@ public class AlertTemplateManagerBean implements AlertTemplateManagerLocal {
+ alertTemplate.toSimpleString(), t);
}
- Subject overlord = subjectManager.getOverlord();
Throwable firstThrowable = null;
List<Integer> resourceIdsForType = getCommittedResourceIdsNeedingTemplateApplication(user, alertTemplateId,
@@ -140,8 +139,8 @@ public class AlertTemplateManagerBean implements AlertTemplateManagerLocal {
AlertDefinition childAlertDefinition = new AlertDefinition(alertTemplate);
childAlertDefinition.setParentId(alertTemplate.getId());
- // persist the child using overlord
- alertDefinitionManager.createAlertDefinition(overlord, childAlertDefinition, resourceId);
+ // persist the child as a dependent alert definition
+ alertDefinitionManager.createDependentAlertDefinition(user, childAlertDefinition, resourceId);
} catch (Throwable t) {
// continue on error, create as many as possible
if (firstThrowable == null) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java
index cde2f04..6df9ae0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java
@@ -137,6 +137,7 @@ public class GroupAlertDefinitionManagerBean implements GroupAlertDefinitionMana
return list;
}
+ @Override
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public int createGroupAlertDefinitions(Subject subject, AlertDefinition groupAlertDefinition,
Integer resourceGroupId) throws InvalidAlertDefinitionException, AlertDefinitionCreationException {
@@ -151,7 +152,6 @@ public class GroupAlertDefinitionManagerBean implements GroupAlertDefinitionMana
+ " with data " + groupAlertDefinition.toSimpleString(), t);
}
- Subject overlord = subjectManager.getOverlord();
Throwable firstThrowable = null;
List<Integer> resourceIdsForGroup = getCommittedResourceIdsNeedingGroupAlertDefinitionApplication(subject,
@@ -164,7 +164,7 @@ public class GroupAlertDefinitionManagerBean implements GroupAlertDefinitionMana
childAlertDefinition.setGroupAlertDefinition(groupAlertDefinition);
// persist the child
- alertDefinitionManager.createAlertDefinition(overlord, childAlertDefinition, resourceId);
+ alertDefinitionManager.createDependentAlertDefinition(subject, childAlertDefinition, resourceId);
} catch (Throwable t) {
// continue on error, create as many as possible
if (firstThrowable == null) {
commit 1047bbb5764ced04b78ee2c81dd9fcb3652387ed
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Aug 7 12:52:19 2012 -0400
Add Richard Hensman to the list of contributors.
diff --git a/pom.xml b/pom.xml
index 3dcca11..0ae9a07 100644
--- a/pom.xml
+++ b/pom.xml
@@ -735,7 +735,7 @@
<exclusion>
<scope>test</scope>
</exclusion>
- <!--<exclusion>
+ <!--<exclusion>
<scope>provided</scope>
</exclusion>-->
</exclusions>
@@ -1570,6 +1570,10 @@
<timezone>+1</timezone>
</contributor>
<contributor>
+ <name>Richard Hensman</name>
+ <timezone>0</timezone>
+ </contributor>
+ <contributor>
<name>Rafael Chies</name>
<timezone>-7</timezone>
<url>http://blogdorafaelchies.wordpress.com/</url>
commit 2639e50949fe39e77a4c17a650b62bc13d1e1a5f
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Aug 7 12:21:07 2012 -0400
BZ 841047 Don't assume a host name of 'master', but get it via api if it is not set. If this does not work, get it via hostname resolution.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASDiscovery.java
index 10889ce..e055cfa 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASDiscovery.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASDiscovery.java
@@ -19,6 +19,8 @@
package org.rhq.modules.plugins.jbossas7;
import java.io.File;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -64,7 +66,10 @@ public class ManagedASDiscovery implements ResourceDiscoveryComponent<HostContro
parentComponent = discoveryContext.getParentResourceComponent();
Configuration hcConfig = discoveryContext.getParentResourceContext().getPluginConfiguration();
- String hostName = hcConfig.getSimpleValue("domainHost", "master"); // TODO good default?
+ String hostName = hcConfig.getSimpleValue("domainHost", null);
+ if (hostName==null) {
+ hostName = getHostName(discoveryContext.getParentResourceComponent().getASConnection());
+ }
String productTypeString = hcConfig.getSimpleValue("productType", null);
JBossProductType productType = JBossProductType.valueOf(productTypeString);
@@ -129,6 +134,32 @@ public class ManagedASDiscovery implements ResourceDiscoveryComponent<HostContro
return discoveredResources;
}
+ /**
+ * Let us try to determine the hostname of the parent's controller via api access.
+ * If that does not work, use host name resolution.
+ *
+ * @param asConnection ASConnection to the parent
+ * @return Host name
+ */
+ private String getHostName(ASConnection asConnection) {
+
+ Operation op = new ReadAttribute(new Address(),"local-host-name");
+ String hostname;
+ Result res = asConnection.execute(op);
+ if (res.isSuccess()) {
+ hostname = (String) res.getResult();
+ return hostname;
+ }
+ // Above failed. Now try falling back to host name resolution
+ try {
+ hostname = InetAddress.getLocalHost().getHostName();
+ } catch (UnknownHostException e) {
+ hostname = "master"; // Very last resort
+ }
+
+ return hostname;
+ }
+
private String resolveSocketBindingGroup(String serverGroup) {
Address address = new Address("server-group", serverGroup);
Operation operation = new ReadAttribute(address, "socket-binding-group");
commit 1b21770ce8d938cce33f03b604b31f6fbc078c14
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue Aug 7 11:26:27 2012 -0400
[Bug 846375 - Resource list views should have name field as initial sort and limit ancestry to client side sorting only]
- Apply default initial sort on Name field for resource list views (using ResourceSearchView)
- note, updated constructor chaining to be more efficient while adding
default sort behavior. Removed an unused constructor.
- Disable server-side sorting on Ancestry since sorting on the encoded
value is not useful to the end user. Allow client-side sorting when all
rows are fetched, this gives the desired alpha sort on the display value.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/AncestryUtil.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/AncestryUtil.java
index 0313b46..15e7bc3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/AncestryUtil.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/AncestryUtil.java
@@ -66,6 +66,8 @@ public abstract class AncestryUtil {
ancestryField = new ListGridField(AncestryUtil.RESOURCE_ANCESTRY, CoreGUI.getMessages().common_title_ancestry());
ancestryField.setAlign(Alignment.LEFT);
ancestryField.setCellAlign(Alignment.LEFT);
+ // sorting on the encoded db value is not useful, limit to client sorting when we have all of the values
+ ancestryField.setCanSortClientOnly(true);
setupAncestryListGridFieldCellFormatter(ancestryField);
setupAncestryListGridFieldHover(ancestryField);
return ancestryField;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
index 9bb1dfa..55271c6 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
@@ -52,6 +52,7 @@ import org.rhq.core.domain.measurement.AvailabilityType;
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.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.ImageManager;
@@ -250,6 +251,11 @@ public class ResourceDatasource extends RPCDataSource<Resource, ResourceCriteria
Log.debug(" *** ResourceCriteria Search String: " + getFilter(request, "search", String.class));
criteria.setSearchExpression(getFilter(request, "search", String.class));
+ // filter out unsortable fields (i.e. fields sorted client-side only)
+ PageControl pageControl = getPageControl(request);
+ pageControl.removeOrderingField(AncestryUtil.RESOURCE_ANCESTRY);
+ criteria.setPageControl(pageControl);
+
return criteria;
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java
index ed0a1ca..0e59b6d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java
@@ -18,13 +18,38 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.resource;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.AVAILABILITY;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.CATEGORY;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.CTIME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.DESCRIPTION;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.ITIME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.KEY;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.LOCATION;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.MODIFIER;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.MTIME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.NAME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.PLUGIN;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.TYPE;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.VERSION;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.List;
+
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.Criteria;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.data.SortSpecifier;
+import com.smartgwt.client.types.SortDirection;
import com.smartgwt.client.widgets.events.DoubleClickEvent;
import com.smartgwt.client.widgets.events.DoubleClickHandler;
-import com.smartgwt.client.widgets.grid.*;
+import com.smartgwt.client.widgets.grid.CellFormatter;
+import com.smartgwt.client.widgets.grid.HoverCustomizer;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.measurement.AvailabilityType;
@@ -34,7 +59,15 @@ import org.rhq.core.domain.search.SearchSubsystem;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.LinkManager;
import org.rhq.enterprise.gui.coregui.client.components.ReportExporter;
-import org.rhq.enterprise.gui.coregui.client.components.table.*;
+import org.rhq.enterprise.gui.coregui.client.components.table.EscapedHtmlCellFormatter;
+import org.rhq.enterprise.gui.coregui.client.components.table.IconField;
+import org.rhq.enterprise.gui.coregui.client.components.table.RecordExtractor;
+import org.rhq.enterprise.gui.coregui.client.components.table.ResourceAuthorizedTableAction;
+import org.rhq.enterprise.gui.coregui.client.components.table.ResourceCategoryCellFormatter;
+import org.rhq.enterprise.gui.coregui.client.components.table.Table;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableActionEnablement;
+import org.rhq.enterprise.gui.coregui.client.components.table.TimestampCellFormatter;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.report.DriftComplianceReportResourceSearchView;
@@ -45,15 +78,9 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message;
import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.List;
-
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.*;
-
/**
- * The list view for {@link Resource}s.
+ * The list view for {@link Resource}s. If not specified a default title is assigned. If not specified the list will
+ * be initially sorted by resource name, ascending.
*
* @author Jay Shaughnessy
* @author Greg Hinkle
@@ -62,6 +89,8 @@ import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceD
public class ResourceSearchView extends Table {
private static final String DEFAULT_TITLE = MSG.common_title_resources();
+ private static final SortSpecifier[] DEFAULT_SORT_SPECIFIER = new SortSpecifier[] { new SortSpecifier("name",
+ SortDirection.ASCENDING) };
private List<ResourceSelectListener> selectListeners = new ArrayList<ResourceSelectListener>();
@@ -71,23 +100,21 @@ public class ResourceSearchView extends Table {
* A list of all Resources in the system.
*/
public ResourceSearchView(String locatorId) {
- this(locatorId, null);
- }
-
- public ResourceSearchView(String locatorId, String title, String[] excludeFields) {
- this(locatorId, null, title, null, excludeFields);
+ this(locatorId, null, null, null, null, false);
}
/**
* A Resource list filtered by a given criteria.
*/
public ResourceSearchView(String locatorId, Criteria criteria) {
- this(locatorId, criteria, DEFAULT_TITLE);
+ this(locatorId, criteria, null, null, null, false);
}
+ /**
+ * A Resource list filtered by a given criteria and optionally exportable
+ */
public ResourceSearchView(String locatorId, Criteria criteria, boolean exportable) {
- this(locatorId, criteria);
- this.exportable = exportable;
+ this(locatorId, criteria, null, null, null, exportable);
}
/**
@@ -96,7 +123,7 @@ public class ResourceSearchView extends Table {
* @param headerIcons 24x24 icon(s) to be displayed in the header
*/
public ResourceSearchView(String locatorId, Criteria criteria, String title, String... headerIcons) {
- this(locatorId, criteria, title, null, null, headerIcons);
+ this(locatorId, criteria, title, null, null, false, headerIcons);
}
/**
@@ -106,7 +133,22 @@ public class ResourceSearchView extends Table {
*/
public ResourceSearchView(String locatorId, Criteria criteria, String title, SortSpecifier[] sortSpecifier,
String[] excludeFields, String... headerIcons) {
- super(locatorId, title, criteria, sortSpecifier, excludeFields);
+
+ this(locatorId, criteria, title, sortSpecifier, excludeFields, false, headerIcons);
+ }
+
+ /**
+ * A Resource list filtered by a given criteria with the given title and optionally exportable.
+ *
+ * @param headerIcons 24x24 icon(s) to be displayed in the header
+ */
+ public ResourceSearchView(String locatorId, Criteria criteria, String title, SortSpecifier[] sortSpecifier,
+ String[] excludeFields, boolean exportable, String... headerIcons) {
+
+ super(locatorId, (null == title) ? DEFAULT_TITLE : title, criteria,
+ (null == sortSpecifier) ? DEFAULT_SORT_SPECIFIER : sortSpecifier, excludeFields);
+
+ this.exportable = exportable;
for (String headerIcon : headerIcons) {
addHeaderIcon(headerIcon);
@@ -309,7 +351,7 @@ public class ResourceSearchView extends Table {
}
private void addExportAction() {
- addTableAction("Export", MSG.common_button_reports_export(), new TableAction() {
+ addTableAction("Export", MSG.common_button_reports_export(), new TableAction() {
@Override
public boolean isEnabled(ListGridRecord[] selection) {
return true;
commit 076ffb39a33d57b6d42c331058f2551b1ebeb7bc
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue Aug 7 11:17:11 2012 -0400
Add new scripting api module to eclipse source path
diff --git a/.classpath b/.classpath
index 443abde..0516dd7 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/scripting/api/src/main/java"/>
<classpathentry kind="src" path="modules/cli-tests/src/main/java"/>
<classpathentry kind="src" path="modules/helpers/jeeGen/src/main/java"/>
<classpathentry kind="src" path="modules/helpers/bundleGen/src/main/java"/>
commit 00b1ee491e609c660113866e834668d0c1c6f3bc
Author: Simeon Pinder <spinder(a)fulliautomatix.conchfritter.com>
Date: Tue Aug 7 11:05:07 2012 -0400
[BZ 839552] passed in the wrong configuration when overriding behavior for SecurityDomain as7 nodes.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsComponent.java
index d486542..a4dccd0 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsComponent.java
@@ -474,7 +474,7 @@ public class ModuleOptionsComponent extends BaseComponent implements Configurati
public void updateResourceConfiguration(ConfigurationUpdateReport report) {
//determine the component
ResourceType resourceType = context.getResourceType();
- ConfigurationDefinition configDef = resourceType.getPluginConfigurationDefinition();
+ ConfigurationDefinition configDef = context.getResourceType().getResourceConfigurationDefinition();
Set<ResourceType> nodeParentTypes = context.getResourceType().getParentResourceTypes();
ResourceType parentType = (ResourceType) nodeParentTypes.toArray()[0];
ResourceType grandParentType = (ResourceType) parentType.getParentResourceTypes().toArray()[0];
commit 153be59c5228bfe4e63657da405d30b5bdb6b423
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Aug 7 15:54:18 2012 +0200
[BZ 846269] - AS5's shutdown operation doesn't require availability to be up.
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java
index 5ac0413..60fa42d 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java
@@ -54,6 +54,29 @@ import org.rhq.core.system.SystemInfo;
* @author Jay Shaughnessy
*/
public class ApplicationServerOperationsDelegate {
+
+ private static class ExecutionFailedException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ @SuppressWarnings("unused")
+ public ExecutionFailedException() {
+ }
+
+ public ExecutionFailedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ExecutionFailedException(String message) {
+ super(message);
+ }
+
+ @SuppressWarnings("unused")
+ public ExecutionFailedException(Throwable cause) {
+ super(cause);
+ }
+ }
+
/**
* max amount of time to wait for server to show as unavailable after
* executing stop - in milliseconds
@@ -303,28 +326,30 @@ public class ApplicationServerOperationsDelegate {
* @return The result of the shutdown operation - is successful
*/
private OperationResult shutDown() {
- AvailabilityType avail = this.serverComponent.getAvailability();
- if (avail == AvailabilityType.DOWN) {
- OperationResult result = new OperationResult();
- result.setErrorMessage("The server is already shut down.");
- return result;
- }
-
Configuration pluginConfig = serverComponent.getResourceContext().getPluginConfiguration();
ApplicationServerShutdownMethod shutdownMethod = Enum.valueOf(ApplicationServerShutdownMethod.class,
pluginConfig.getSimple(ApplicationServerPluginConfigurationProperties.SHUTDOWN_METHOD_CONFIG_PROP)
.getStringValue());
- String resultMessage = ApplicationServerShutdownMethod.JMX.equals(shutdownMethod) ? shutdownViaJmx()
- : shutdownViaScript();
-
- avail = waitForServerToShutdown();
+ String errorMessage = null;
+ String resultMessage = null;
+ try {
+ resultMessage = ApplicationServerShutdownMethod.JMX.equals(shutdownMethod) ? shutdownViaJmx()
+ : shutdownViaScript();
+ } catch (ExecutionFailedException e) {
+ errorMessage = e.getMessage();
+ }
+
+ AvailabilityType avail = waitForServerToShutdown();
OperationResult result;
if (avail == AvailabilityType.UP) {
result = new OperationResult();
result.setErrorMessage("The server failed to shut down.");
} else {
- return new OperationResult(resultMessage);
+ result = new OperationResult();
+ result.setSimpleResult(resultMessage);
+ result.setErrorMessage(errorMessage);
}
+
return result;
}
@@ -333,7 +358,7 @@ public class ApplicationServerOperationsDelegate {
*
* @return success message if no errors are encountered
*/
- private String shutdownViaScript() {
+ private String shutdownViaScript() throws ExecutionFailedException {
File shutdownScriptFile = getShutdownScriptPath();
validateScriptFile(shutdownScriptFile,
ApplicationServerPluginConfigurationProperties.SHUTDOWN_SCRIPT_CONFIG_PROP);
@@ -378,8 +403,8 @@ public class ApplicationServerOperationsDelegate {
logExecutionResults(results);
if (results.getError() != null) {
- throw new RuntimeException("Error executing shutdown script while stopping AS instance. Exit code ["
- + results.getExitCode() + "]", results.getError());
+ throw new ExecutionFailedException("Error executing shutdown script while stopping AS instance. Exit code ["
+ + results.getExitCode() + "]: " + results.getError().getMessage(), results.getError());
}
return "The server has been shut down.";
@@ -397,7 +422,7 @@ public class ApplicationServerOperationsDelegate {
*
* @return success message if no errors are encountered
*/
- private String shutdownViaJmx() {
+ private String shutdownViaJmx() throws ExecutionFailedException {
Configuration pluginConfig = serverComponent.getResourceContext().getPluginConfiguration();
String mbeanName = pluginConfig.getSimple(
ApplicationServerPluginConfigurationProperties.SHUTDOWN_MBEAN_CONFIG_PROP).getStringValue();
@@ -406,7 +431,7 @@ public class ApplicationServerOperationsDelegate {
EmsConnection connection = this.serverComponent.getEmsConnection();
if (connection == null) {
- throw new RuntimeException("Can not connect to the server");
+ throw new ExecutionFailedException("Can not connect to the server");
}
EmsBean bean = connection.getBean(mbeanName);
EmsOperation operation = bean.getOperation(operationName);
@@ -422,14 +447,18 @@ public class ApplicationServerOperationsDelegate {
* method, we'd need a clever way for the user to specify parameters
* anyway.
*/
- List<EmsParameter> params = operation.getParameters();
- int count = params.size();
- if (count == 0)
- operation.invoke(new Object[0]);
- else { // overloaded operation
- operation.invoke(new Object[] { 0 }); // return code of 0
+ try {
+ List<EmsParameter> params = operation.getParameters();
+ int count = params.size();
+ if (count == 0)
+ operation.invoke(new Object[0]);
+ else { // overloaded operation
+ operation.invoke(new Object[] { 0 }); // return code of 0
+ }
+ } catch (RuntimeException e) {
+ throw new ExecutionFailedException("Shutting down the server using JMX failed: " + e.getMessage(), e);
}
-
+
return "The server has been shut down.";
}
diff --git a/modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/itest/ApplicationServerComponentTest.java b/modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/itest/ApplicationServerComponentTest.java
index 2bc7f47..6d60b85 100644
--- a/modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/itest/ApplicationServerComponentTest.java
+++ b/modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/itest/ApplicationServerComponentTest.java
@@ -24,6 +24,8 @@ package org.rhq.plugins.jbossas5.itest;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
import java.io.File;
import java.util.Arrays;
@@ -50,6 +52,7 @@ import org.rhq.core.pc.inventory.InventoryManager;
import org.rhq.core.pc.inventory.ResourceContainer;
import org.rhq.core.pluginapi.configuration.ListPropertySimpleWrapper;
import org.rhq.core.pluginapi.configuration.MapPropertySimpleWrapper;
+import org.rhq.core.pluginapi.operation.OperationResult;
import org.rhq.core.pluginapi.util.FileUtils;
import org.rhq.core.pluginapi.util.StartScriptConfiguration;
import org.rhq.core.system.ProcessInfo;
@@ -197,9 +200,32 @@ public class ApplicationServerComponentTest extends AbstractJBossAS5PluginTest {
avail = getAvailability(getServerResource());
assertEquals(avail, AvailabilityType.DOWN);
+ //change the plugin config to shutdown via JMX
+ Configuration pluginConfig = getServerResource().getPluginConfiguration();
+ pluginConfig.getSimple("shutdownMethod").setValue("JMX");
+ restartServerResourceComponent();
+
+ //invoke the shutdown operation again and assert that it actually ran and generated some error message.
+ OperationResult operationResult = invokeOperation(getServerResource(), SHUTDOWN_OPERATION_NAME, null);
+ avail = getAvailability(getServerResource());
+ assertEquals(avail, AvailabilityType.DOWN);
+ assertNotNull(operationResult.getErrorMessage());
+
+ //ok, now try the same with the script shutdown method
+ pluginConfig = getServerResource().getPluginConfiguration();
+ pluginConfig.getSimple("shutdownMethod").setValue("SCRIPT");
+ restartServerResourceComponent();
+
+ //invoke the shutdown operation again and assert that it actually ran
+ operationResult = invokeOperation(getServerResource(), SHUTDOWN_OPERATION_NAME, null);
+ avail = getAvailability(getServerResource());
+ assertEquals(avail, AvailabilityType.DOWN);
+ assertNull(operationResult.getErrorMessage());
+ assertEquals(operationResult.getSimpleResult(), "The server has been shut down.");
+
// Before restarting it, add some stuff to the 'startScriptEnv' and 'startScriptArgs' props so we can verify
// they are used correctly by the Start op.
- Configuration pluginConfig = getServerResource().getPluginConfiguration();
+ pluginConfig = getServerResource().getPluginConfiguration();
StartScriptConfiguration startScriptConfig = new StartScriptConfiguration(pluginConfig);
// Add a var to the start script env.
commit 11f741ebd98c10d294e23d5f7174d12b67baea90
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Aug 6 15:08:20 2012 -0400
[Bug 828428 - org.rhq.enterprise.server.cloud.instance.CacheConsistencyManagerBean ERROR ORA-01795: maximum number of expressions in a list is 1000]
This time the problem is 1000 or more agents on a server (with status <> 0).
Batch the updates to avoid the Oracle limitation.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StatusManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StatusManagerBean.java
index dfd1990..9658dd1 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StatusManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StatusManagerBean.java
@@ -95,13 +95,28 @@ public class StatusManagerBean implements StatusManagerLocal {
List<Integer> agentIds = selectQuery.getResultList();
if (agentIds.size() > 0) {
- /*
- * note: not worried about size of the in clause, because the number of
- * agents per server will be reasonable, say, 50-150
- */
- Query updateQuery = entityManager.createNamedQuery(Agent.QUERY_UPDATE_CLEAR_STATUS_BY_IDS);
- updateQuery.setParameter("agentIds", agentIds);
- updateQuery.executeUpdate();
+
+ // handle the oracle 1000 member IN clause issue
+ final int ORACLE_BATCH_SIZE = 1000;
+
+ int numAgents = agentIds.size();
+ int batches = (numAgents / ORACLE_BATCH_SIZE) + 1;
+
+ // iterate over the agent ids when we have more than 1000 of them
+ for (int batch = 0; batch < batches; ++batch) {
+ int fromIndex = batch * ORACLE_BATCH_SIZE;
+ int toIndex = fromIndex + ORACLE_BATCH_SIZE;
+ if (toIndex > numAgents) // don't run over the end of the list
+ toIndex = numAgents;
+ List<Integer> agentIdBatch = agentIds.subList(fromIndex, toIndex);
+
+ if (fromIndex == toIndex)
+ continue;
+
+ Query updateQuery = entityManager.createNamedQuery(Agent.QUERY_UPDATE_CLEAR_STATUS_BY_IDS);
+ updateQuery.setParameter("agentIds", agentIdBatch);
+ int numUpdated = updateQuery.executeUpdate();
+ }
}
return agentIds;
commit b1867328cf3186d0c86a44b5296c1fbd1f48f1d8
Author: Richard Hensman <richard(a)onevisionconsulting.co.uk>
Date: Thu Jul 19 21:44:44 2012 +0100
Add support for monitoring Flash Recovery Areas to the Oracle plugin
diff --git a/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleFlashRecoveryAreaComponent.java b/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleFlashRecoveryAreaComponent.java
new file mode 100644
index 0000000..0446d7f
--- /dev/null
+++ b/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleFlashRecoveryAreaComponent.java
@@ -0,0 +1,83 @@
+/*
+ * 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.plugins.oracle;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.rhq.core.domain.measurement.AvailabilityType;
+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.pluginapi.measurement.MeasurementFacet;
+import org.rhq.core.util.jdbc.JDBCUtil;
+import org.rhq.plugins.database.AbstractDatabaseComponent;
+import org.rhq.plugins.database.DatabaseQueryUtility;
+
+/**
+ * Oracle Flash Recovery Area Component.
+ *
+ * @author Richard Hensman
+ */
+public class OracleFlashRecoveryAreaComponent extends AbstractDatabaseComponent implements MeasurementFacet {
+
+ private static final String SQL_AVAILABLE = "SELECT COUNT(*) FROM v$recovery_file_dest WHERE name = ?";
+ private static final String SQL_VALUES =
+ "SELECT space_limit spaceLimit, space_used spaceUsed, space_reclaimable spaceReclaimable, number_of_files numberOfFiles, (space_used/space_limit) usedPercent " +
+ "FROM v$recovery_file_dest WHERE name = ?";
+
+
+ private static Log log = LogFactory.getLog(OracleFlashRecoveryAreaComponent.class);
+
+ public AvailabilityType getAvailability() {
+ PreparedStatement statement = null;
+ ResultSet resultSet = null;
+ try {
+ statement = getConnection().prepareStatement(SQL_AVAILABLE);
+ statement.setString(1, this.resourceContext.getResourceKey());
+ resultSet = statement.executeQuery();
+ if (resultSet.next() && (resultSet.getInt(1) == 1)) {
+ return AvailabilityType.UP;
+ }
+ } catch (SQLException e) {
+ log.debug("unable to query", e);
+ } finally {
+ JDBCUtil.safeClose(statement, resultSet);
+ }
+
+ return AvailabilityType.DOWN;
+ }
+
+ public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
+ Map<String, Double> values = DatabaseQueryUtility.getNumericQueryValues(this, SQL_VALUES,
+ this.resourceContext.getResourceKey());
+ for (MeasurementScheduleRequest request : metrics) {
+ Double d = values.get(request.getName().toUpperCase(Locale.US));
+ if (d != null) {
+ report.addData(new MeasurementDataNumeric(request, d));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
index 8ef56cb..d8606e1 100644
--- a/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
@@ -610,14 +610,31 @@
<c:simple-property name="description" default="Oracle Tablespace"/>
</plugin-configuration>
- <!-- Space used in the tablespace (database blocks) -->
<metric property="usedSpace" displayName="Used Space" description="Space used in the tablespace (database blocks)" displayType="summary"/>
- <!-- Total size of the tablespace (database blocks) -->
<metric property="totalSize" displayName="Total Size" description="Total size of the tablespace (database blocks)" displayType="summary"/>
- <!-- Percentage of the tablespace used -->
<metric property="usedPercent" displayName="Used Percent" description="Percentage of the tablespace used" displayType="summary" units="percentage"/>
</service>
+
+ <service name="Oracle Flash Recovery Areas"
+ discovery="org.rhq.plugins.database.CustomTableRowDiscoveryComponent"
+ class="org.rhq.plugins.oracle.OracleFlashRecoveryAreaComponent">
+
+ <plugin-configuration>
+ <c:simple-property name="table" default="V$RECOVERY_FILE_DEST"/>
+ <c:simple-property name="metricQuery" default="SELECT {key} FROM V$RECOVERY_FILE_DEST"/>
+ <c:simple-property name="keyColumn" default="name"/>
+ <c:simple-property name="name" default="{key}"/>
+ <c:simple-property name="description" default="Oracle Flash Recovery Areas"/>
+ </plugin-configuration>
+
+ <metric property="spaceLimit" displayName="Space Limit" description="Flash Recovery Area space limit (database blocks)" displayType="summary"/>
+ <metric property="spaceUsed" displayName="Space Used" description="Space used in the Flash Recovery Area (database blocks)" displayType="summary"/>
+ <metric property="spaceReclaimable" displayName="Space Reclaimable" description="Space reclaimable in the Flash Recovery Area (database blocks)" displayType="summary"/>
+ <metric property="numberOfFiles" displayName="Number Of Files" description="Number of files in the Flash Recovery Area" displayType="summary"/>
+ <metric property="usedPercent" displayName="Used Percent" description="Percentage of the Flash Recovery Area used" displayType="summary" units="percentage"/>
+
+ </service>
</server>
commit 9726761caf702f5a53f33ef2d957a84e55953196
Author: Richard Hensman <richard(a)onevisionconsulting.co.uk>
Date: Wed Jul 18 15:09:10 2012 +0100
Add support for monitoring table spaces to the Oracle plugin
diff --git a/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleTablespaceComponent.java b/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleTablespaceComponent.java
new file mode 100644
index 0000000..e99787b
--- /dev/null
+++ b/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleTablespaceComponent.java
@@ -0,0 +1,83 @@
+/*
+ * 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.plugins.oracle;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.rhq.core.domain.measurement.AvailabilityType;
+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.pluginapi.measurement.MeasurementFacet;
+import org.rhq.core.util.jdbc.JDBCUtil;
+import org.rhq.plugins.database.AbstractDatabaseComponent;
+import org.rhq.plugins.database.DatabaseQueryUtility;
+
+/**
+ * Oracle Tablespace Component.
+ *
+ * @author Richard Hensman
+ */
+public class OracleTablespaceComponent extends AbstractDatabaseComponent implements MeasurementFacet {
+
+ private static final String SQL_AVAILABLE = "SELECT COUNT(*) FROM dba_tablespaces WHERE tablespace_name = ?";
+ private static final String SQL_VALUES =
+ "SELECT USED_SPACE usedSpace, TABLESPACE_SIZE totalSize, (USED_PERCENT/100) usedPercent " +
+ "FROM dba_tablespace_usage_metrics where tablespace_name = ?";
+
+
+ private static Log log = LogFactory.getLog(OracleTablespaceComponent.class);
+
+ public AvailabilityType getAvailability() {
+ PreparedStatement statement = null;
+ ResultSet resultSet = null;
+ try {
+ statement = getConnection().prepareStatement(SQL_AVAILABLE);
+ statement.setString(1, this.resourceContext.getResourceKey());
+ resultSet = statement.executeQuery();
+ if (resultSet.next() && (resultSet.getInt(1) == 1)) {
+ return AvailabilityType.UP;
+ }
+ } catch (SQLException e) {
+ log.debug("unable to query", e);
+ } finally {
+ JDBCUtil.safeClose(statement, resultSet);
+ }
+
+ return AvailabilityType.DOWN;
+ }
+
+ public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
+ Map<String, Double> values = DatabaseQueryUtility.getNumericQueryValues(this, SQL_VALUES,
+ this.resourceContext.getResourceKey());
+ for (MeasurementScheduleRequest request : metrics) {
+ Double d = values.get(request.getName().toUpperCase(Locale.US));
+ if (d != null) {
+ report.addData(new MeasurementDataNumeric(request, d));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
index 00f0284..8ef56cb 100644
--- a/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
@@ -593,8 +593,29 @@
<c:simple-property name="description" default="Oracle User"/>
</plugin-configuration>
- <metric property="connections" displayName="Total Connections" displayType="summary"/>
- <metric property="active" displayName="Active Connections" displayType="summary"/>
+ <metric property="connections" displayName="Total Connections" displayType="summary"/>
+ <metric property="active" displayName="Active Connections" displayType="summary"/>
+
+ </service>
+
+ <service name="Oracle Tablespaces"
+ discovery="org.rhq.plugins.database.CustomTableRowDiscoveryComponent"
+ class="org.rhq.plugins.oracle.OracleTablespaceComponent">
+
+ <plugin-configuration>
+ <c:simple-property name="table" default="DBA_TABLESPACES"/>
+ <c:simple-property name="metricQuery" default="SELECT {key} FROM DBA_TABLESPACES"/>
+ <c:simple-property name="keyColumn" default="tablespace_name"/>
+ <c:simple-property name="name" default="{key}"/>
+ <c:simple-property name="description" default="Oracle Tablespace"/>
+ </plugin-configuration>
+
+ <!-- Space used in the tablespace (database blocks) -->
+ <metric property="usedSpace" displayName="Used Space" description="Space used in the tablespace (database blocks)" displayType="summary"/>
+ <!-- Total size of the tablespace (database blocks) -->
+ <metric property="totalSize" displayName="Total Size" description="Total size of the tablespace (database blocks)" displayType="summary"/>
+ <!-- Percentage of the tablespace used -->
+ <metric property="usedPercent" displayName="Used Percent" description="Percentage of the tablespace used" displayType="summary" units="percentage"/>
</service>
commit 5b37f7a17ef64863a810a5b92cbf885eca05dda3
Author: John Sanda <jsanda(a)redhat.com>
Date: Mon Aug 6 12:38:46 2012 -0400
[BZ 838861] Handle empty zip file on java 7
Since an exception is not thrown when closing a ZipOutputStream on an
empty zip file in Java 7, I have added logic to check whether or not the
zip file has any content. sendChangeSetContentToServer is called only if
the content file is non-empty. The logging logic has been updated as
well so that we only log an error message when failing to close the
output stream only when the content file is non-empty. This keeps the
logging clean and consistent across Java 6 and 7.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftFilesSender.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftFilesSender.java
index 59d3054..266b666 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftFilesSender.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftFilesSender.java
@@ -1,20 +1,25 @@
package org.rhq.core.pc.drift;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.rhq.common.drift.ChangeSetReader;
import org.rhq.common.drift.FileEntry;
import org.rhq.common.drift.Headers;
import org.rhq.core.domain.drift.DriftFile;
import org.rhq.core.util.stream.StreamUtil;
-import java.io.*;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
-
public class DriftFilesSender implements Runnable {
private Log log = LogFactory.getLog(DriftFilesSender.class);
@@ -52,6 +57,7 @@ public class DriftFilesSender implements Runnable {
@Override
public void run() {
ZipOutputStream stream = null;
+ int numContentFiles = 0;
try {
if (log.isInfoEnabled()) {
log.info("Preparing to send content to server for " + defToString());
@@ -89,6 +95,7 @@ public class DriftFilesSender implements Runnable {
log.debug("Adding " + file.getPath() + " to " + contentFileName);
}
addFileToContentZipFile(stream, driftFile, file);
+ ++numContentFiles;
}
} else {
Map<String, FileEntry> fileEntries = createSnapshotIndex();
@@ -106,15 +113,18 @@ public class DriftFilesSender implements Runnable {
log.debug("Adding " + file.getPath() + " to " + contentFileName);
}
addFileToContentZipFile(stream, driftFile, file);
+ ++numContentFiles;
}
}
}
+ if (numContentFiles > 0) {
+ driftClient.sendChangeSetContentToServer(resourceId, headers.getDriftDefinitionName(), zipFile);
+ }
+
stream.close();
stream = null;
- driftClient.sendChangeSetContentToServer(resourceId, headers.getDriftDefinitionName(), zipFile);
-
if (log.isInfoEnabled()) {
long endTime = System.currentTimeMillis();
log.info("Finished submitting request to send content to server in " + (endTime - startTime) +
@@ -122,7 +132,19 @@ public class DriftFilesSender implements Runnable {
}
} catch (IOException e) {
- log.error("Failed to send drift files.", e);
+ if (numContentFiles > 0) {
+ // Only log an error message if the content zip file is not empty. With
+ // Java 6, closing an empty ZipOutputStream causes an exception which we
+ // can ignore. On Java 7 however, no exception is thrown when closing an
+ // empty ZipOutputStream. This check keeps the error reporting logic
+ // consistent across Java 6 and 7 such that we only log an error message
+ // when we fail to close the output stream when the content zip file is
+ // not empty. See https://bugzilla.redhat.com/show_bug.cgi?id=838681 for
+ // more info.
+ //
+ // jsanda
+ log.error("Failed to send drift files.", e);
+ }
} finally {
if (stream != null) {
try {
commit 0aeaf8e9f71ea154e2421e67e29269eea33b762c
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Fri Aug 3 15:02:56 2012 -0700
[BZ 826224 Creation of Compatible Group fails with value too long for type character when a description is entered which is longer then 100 characters] Group names limited now to 100 chars to match DB.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/wizard/GroupCreateStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/wizard/GroupCreateStep.java
index ee49f4e..143c159 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/wizard/GroupCreateStep.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/wizard/GroupCreateStep.java
@@ -75,6 +75,7 @@ public class GroupCreateStep extends AbstractWizardStep {
TextItem name = new TextItem("name", MSG.common_title_name());
name.setRequired(true);
name.setWidth(300);
+ name.setLength(100);
name.addChangedHandler(new ChangedHandler() {
@Override
public void onChanged(ChangedEvent changedEvent) {
commit 970715c3f73d18c6ecd3696b8970f6782fea49fa
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri Aug 3 07:28:36 2012 -0700
[BZ 841045 advisoryInfo-plain.xhtml is missing parameters on the repo-plain.xhtml link] applied patch from jlivings.
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/advisoryInfo-plain.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/advisoryInfo-plain.xhtml
index c672d16..7590610 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/advisoryInfo-plain.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/advisoryInfo-plain.xhtml
@@ -24,7 +24,10 @@
<ui:define name="breadcrumbs">
<h:outputLink value="listContentProviders-plain.xhtml">
${msg["contentprovider.list.breadcrumb"]}
+ <f:param name="mode" value="view" />
+ <f:param name="id" value="#{param.id}" />
</h:outputLink>
+
>
<h:outputLink value="repo-plain.xhtml">
${msg["repo.list.breadcrumb"]}
commit 63b805d29a7b66593203de5a006770adab06e105
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed Aug 1 20:00:29 2012 -0700
[BZ 838665 - Changing selected operation does not clear out parameters sent along with request]
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java
index c52eb30..8b26cb2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java
@@ -193,6 +193,8 @@ public abstract class AbstractOperationScheduleDetailsView extends
operationNameItem.setShowTitle(true);
items.add(operationNameItem);
operationNameItem.addChangedHandler(new ChangedHandler() {
+
+ @Override
public void onChanged(ChangedEvent event) {
handleOperationNameChange();
}
@@ -423,18 +425,15 @@ public abstract class AbstractOperationScheduleDetailsView extends
private void refreshOperationParametersItem() {
String operationName = getSelectedOperationName();
String value;
+ operationParameters = null; // reset params between dropdown selects
+ // make sure we wipe out anything left by the previous op def
+ for (Canvas child : this.operationParametersConfigurationHolder.getChildren()) {
+ child.destroy();
+ }
if (operationName == null) {
value = "<i>" + MSG.view_operationScheduleDetails_fieldDefault_parameters() + "</i>";
- for (Canvas child : this.operationParametersConfigurationHolder.getChildren()) {
- child.destroy();
- }
this.operationParametersConfigurationHolder.hide();
} else {
- // make sure we wipe out anything left by the previous op def
- for (Canvas child : this.operationParametersConfigurationHolder.getChildren()) {
- child.destroy();
- }
-
final ConfigurationDefinition parametersDefinition = this.operationNameToParametersDefinitionMap
.get(operationName);
if (parametersDefinition == null || parametersDefinition.getPropertyDefinitions().isEmpty()) {
commit 4f60260d2afe019943f23c64cdaf14f1f11c3d53
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Aug 1 16:34:02 2012 -0400
BZ 845118 provide delegates for the tow classes that were moved to util/ as other plugins may still rely on the old package structure.
diff --git a/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ObjectNameQueryUtility.java b/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ObjectNameQueryUtility.java
new file mode 100644
index 0000000..bc4b264
--- /dev/null
+++ b/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ObjectNameQueryUtility.java
@@ -0,0 +1,75 @@
+/*
+ * 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.plugins.jmx;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.rhq.core.domain.configuration.Configuration;
+
+/**
+ * Delegate for the old version of the class which got moved to util package
+ * @author Heiko W. Rupp
+ * @deprecated Use the version in the util package
+ */
+public class ObjectNameQueryUtility {
+
+ private org.rhq.plugins.jmx.util.ObjectNameQueryUtility onu;
+
+ public ObjectNameQueryUtility(String objectNameQueryTemplate) {
+ onu = new org.rhq.plugins.jmx.util.ObjectNameQueryUtility(objectNameQueryTemplate);
+ }
+
+ public ObjectNameQueryUtility(String objectNameQueryTemplate, Configuration parentConfiguration) {
+ onu = new org.rhq.plugins.jmx.util.ObjectNameQueryUtility(objectNameQueryTemplate,parentConfiguration);
+ }
+
+ public boolean setMatchedKeyValues(Map<String, String> keyProperties) {
+ return onu.setMatchedKeyValues(keyProperties);
+ }
+
+ public String formatMessage(String message) {
+ return onu.formatMessage(message);
+ }
+
+ public void resetVariables() {
+ onu.resetVariables();
+ }
+
+ public String getQueryTemplate() {
+ return onu.getQueryTemplate();
+ }
+
+ public Map<String, String> getVariableProperties() {
+ return onu.getVariableProperties();
+ }
+
+ public Map<String, String> getVariableValues() {
+ return onu.getVariableValues();
+ }
+
+ public String getTranslatedQuery() {
+ return onu.getTranslatedQuery();
+ }
+
+ public boolean isContainsExtraKeyProperties(Set<String> strings) {
+ return onu.isContainsExtraKeyProperties(strings);
+ }
+}
diff --git a/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ParentDefinedJMXServerNamingUtility.java b/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ParentDefinedJMXServerNamingUtility.java
new file mode 100644
index 0000000..fccb0ab
--- /dev/null
+++ b/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ParentDefinedJMXServerNamingUtility.java
@@ -0,0 +1,40 @@
+/*
+ * 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.plugins.jmx;
+
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+
+/**
+ * Delegate for the original version of this
+ * class that got moved to util/
+ * @deprecated Use the version of the class in the util Package
+ * @see org.rhq.plugins.jmx.util.ParentDefinedJMXServerNamingUtility
+ * @author Heiko W. Rupp
+ */
+@Deprecated
+public class ParentDefinedJMXServerNamingUtility {
+ public static final String PROPERTY_CHILD_JMX_SERVER_NAME = "childJmxServerName";
+
+ /** @deprecated use the version in util package instead */
+ @Deprecated
+ public static String getJVMName(ResourceDiscoveryContext<?> context) {
+ return org.rhq.plugins.jmx.util.ParentDefinedJMXServerNamingUtility.getJVMName(context);
+ }
+}
diff --git a/modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityDelegateTest.java b/modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityDelegateTest.java
new file mode 100644
index 0000000..58d11a1
--- /dev/null
+++ b/modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityDelegateTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.plugins.jmx.test;
+
+import java.util.Collections;
+
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.plugins.jmx.ObjectNameQueryUtility;
+
+/**
+ * This test explicitly tests the delegate for the ObjectNameQueryUtility.
+ * The Utility itself got moved into the util package. To be backward compatible,
+ * we need to have a delegate
+ */
+public class ObjectNameQueryUtilityDelegateTest {
+ @Test
+ public void testObjectNameQueryUtility() throws MalformedObjectNameException {
+ ObjectNameQueryUtility onqu = null;
+ onqu = new ObjectNameQueryUtility("java.lang:type=MemoryPool,name=Code Cache");
+ assert onqu.getQueryTemplate().equals("java.lang:type=MemoryPool,name=Code Cache");
+
+ onqu = new ObjectNameQueryUtility("java.lang:type=MemoryPool,name=%name%");
+ assert onqu.getTranslatedQuery().equals("java.lang:type=MemoryPool,*");
+ assert onqu.getVariableProperties().size() == 1;
+ assert onqu.getVariableProperties().get("name").equals("name");
+
+ onqu = new ObjectNameQueryUtility("java.lang:type=Threading");
+
+ onqu = new ObjectNameQueryUtility("java.lang:type=%foo%");
+ assert onqu.getTranslatedQuery().equals("java.lang:*");
+ assert onqu.getVariableProperties().size() == 1;
+ assert onqu.getVariableProperties().get("type").equals("foo");
+
+ onqu = new ObjectNameQueryUtility("jboss.esb.*:service=Queue,name=%name%");
+ assert onqu.getTranslatedQuery().equals("jboss.esb.*:service=Queue,*");
+ assert onqu.getVariableProperties().size() == 1;
+ assert onqu.getVariableProperties().get("name").equals("name");
+ ObjectName testON = new ObjectName(
+ "jboss.esb.quickstart.destination:service=Queue,name=quickstart_helloworld_Request_gw");
+ onqu.setMatchedKeyValues(testON.getKeyPropertyList());
+ String formulatedMessageTemplate = "Name of queue: {name}";
+ assert onqu.formatMessage(formulatedMessageTemplate).equals("Name of queue: quickstart_helloworld_Request_gw");
+
+ onqu = new ObjectNameQueryUtility("java.lang:type=%MyType%,name=%MyName%,app=%MyApp%,foo=%MyFoo%");
+ assert onqu.getTranslatedQuery().equals("java.lang:*");
+ assert onqu.getVariableProperties().size() == 4;
+ testON = new ObjectName("java.lang:type=A,name=B,app=C,foo=D");
+ onqu.setMatchedKeyValues(testON.getKeyPropertyList());
+ formulatedMessageTemplate = "Type: {MyType}, Name: {MyName}, App: {MyApp}, Foo: {MyFoo}";
+ assert onqu.formatMessage(formulatedMessageTemplate).equals("Type: A, Name: B, App: C, Foo: D");
+
+ Configuration c = new Configuration();
+ c.put(new PropertySimple("e", "foo"));
+ c.put(new PropertySimple("g", "bar"));
+ onqu = new ObjectNameQueryUtility("a:b=c,d={e},f={g}", c);
+ System.out.println("Template: " + onqu.getQueryTemplate());
+ assert onqu.getQueryTemplate().equals("a:b=c,d=foo,f=bar");
+
+ // Test some very long replacement tokens inspired by BZ 828596
+ onqu = new ObjectNameQueryUtility("*:type=HttpMetricInspector,name=%name%");
+ assert onqu.getQueryTemplate().equals("*:type=HttpMetricInspector,name=%name%");
+ assert onqu.getVariableProperties().size() == 1;
+ assert onqu.getVariableProperties().get("name").equals("name");
+ testON = new ObjectName("FooBarABCDEFGHIJKLMNOPQRSTUVWXYZ:type=HttpMetricInspector,name=ABCDEFGHIJKLMNOPQRSTUVWXYZöABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ onqu.setMatchedKeyValues(testON.getKeyPropertyList());
+ formulatedMessageTemplate = "Http metrics for endpoint {name}";
+ String res = onqu.formatMessage(formulatedMessageTemplate);
+ assert res.equals("Http metrics for endpoint ABCDEFGHIJKLMNOPQRSTUVWXYZöABCDEFGHIJKLMNOPQRSTUVWXYZ") : res;
+
+
+ }
+
+ @Test
+ public void testObjectNameQueryUtilityFiltering() throws MalformedObjectNameException {
+ ObjectNameQueryUtility onqu = null;
+
+ onqu = new ObjectNameQueryUtility("java.lang:type=MemoryPool,name=%foo%");
+ assert !onqu.isContainsExtraKeyProperties(Collections.singleton("type"));
+ assert !onqu.isContainsExtraKeyProperties(Collections.singleton("name"));
+ assert onqu.isContainsExtraKeyProperties(Collections.singleton("splat"));
+
+ }
+
+}
\ No newline at end of file
commit a9a655c1b1ff04330ef75e7a7c9456b88bd0ad56
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jul 31 09:07:55 2012 -0700
[BZ 733487 New SearchBar] Handle null search condition better.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
index 5409248..f56c81e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
@@ -163,7 +163,7 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
.getValueAsString().length());
} else {
Log.debug("Empty Search expression");
- getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE, "", 0);
+ getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE, null, 0);
}
}
@@ -175,7 +175,7 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
private void getTabAwareSearchSuggestions(final SearchSubsystem searchSubsystem, final String expression,
int caretPosition) {
- if (expression.equals(lastExpression)) {
+ if (null != expression && expression.equals(lastExpression)) {
// short-circuit if we dont really need to do a search
Log.debug("search tab aware Suggestions: ignoring duplicate search for: " + expression);
return;
@@ -193,7 +193,7 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
ComboBoxItem comboBox = searchBar.getSearchComboboxItem();
// If the value has already changed assume a subsequent search is what they want
- if (!expression.equals(comboBox.getValueAsString())) {
+ if (null != expression && !expression.equals(comboBox.getValueAsString())) {
Log.debug("search tab aware Suggestions: ignoring obsolete results for: " + expression);
return;
}
commit 412f7ac30c6e395d56f86b3ab434452681d82277
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Jul 31 10:19:26 2012 -0400
fix the versions to mimic the actual version strings in the distros
diff --git a/modules/core/util/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java b/modules/core/util/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java
index 2e81763..6a390765 100644
--- a/modules/core/util/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java
+++ b/modules/core/util/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java
@@ -39,7 +39,6 @@ public class ComparableVersionTest {
RHQ_VERSIONS.add("4.4.0.RC1");
RHQ_VERSIONS.add("4.4.0.RC2");
RHQ_VERSIONS.add("4.4.0.GA");
- RHQ_VERSIONS.add("4.4.1.GA");
}
private static List<String> JON_VERSIONS = new ArrayList<String>();
@@ -52,7 +51,7 @@ public class ComparableVersionTest {
JON_VERSIONS.add("4.4.0.JON310BETA1");
JON_VERSIONS.add("4.4.0.JON310CR1");
JON_VERSIONS.add("4.4.0.JON310GA");
- JON_VERSIONS.add("4.4.1.JON311GA");
+ JON_VERSIONS.add("4.4.0.JON311GA");
}
public void testRHQVersions() {
commit b49d9d3dd66056bee9fc58f8a4084f6f62487da4
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Jul 30 20:51:25 2012 -0700
[BZ 733487 New SearchBar] Fixed bug with return key in search bar not properly sending search. Added i18n.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
index cf40099..5409248 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
@@ -138,32 +138,33 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
public void searchFocusHandler(FocusEvent event) {
Log.debug("focus in BasicSearchStrategy");
String searchExpression = searchBar.getSearchComboboxItem().getValueAsString();
- if (null != searchExpression && searchExpression.length() > 0) {
- getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE,
- searchBar.getSearchComboboxItem().getValueAsString(), searchBar.getSearchComboboxItem()
- .getValueAsString().length());
- } else {
- getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE, "", 0);
- }
+ doSearch(searchExpression);
}
+
+
@Override
public void searchKeyUpHandler(KeyUpEvent keyUpEvent) {
Log.debug("Keyup in BasicSearchStrategy: " + keyUpEvent.getKeyName());
String searchExpression = searchBar.getSearchComboboxItem().getValueAsString();
+ doSearch(searchExpression);
+
+ }
+
+ @Override
+ public void searchReturnKeyHandler(KeyUpEvent keyUpEvent) {
+ doSearch((String)keyUpEvent.getItem().getValue());
+ }
+
+ private void doSearch(String searchExpression) {
if (null != searchExpression && searchExpression.length() > 0) {
getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE,
- searchBar.getSearchComboboxItem().getValueAsString(), searchBar.getSearchComboboxItem()
+ searchBar.getSearchComboboxItem().getValueAsString(), searchBar.getSearchComboboxItem()
.getValueAsString().length());
} else {
+ Log.debug("Empty Search expression");
getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE, "", 0);
}
-
- }
-
- @Override
- public void searchReturnKeyHandler(KeyUpEvent keyUpEvent) {
- // Do nothing here; standard Table.TableFilter will handle normally
}
@Override
@@ -171,10 +172,11 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
return 25;
}
- private void getTabAwareSearchSuggestions(SearchSubsystem searchSubsystem, final String expression,
+ private void getTabAwareSearchSuggestions(final SearchSubsystem searchSubsystem, final String expression,
int caretPosition) {
if (expression.equals(lastExpression)) {
+ // short-circuit if we dont really need to do a search
Log.debug("search tab aware Suggestions: ignoring duplicate search for: " + expression);
return;
}
@@ -182,9 +184,11 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
final long suggestStart = System.currentTimeMillis();
+ Log.debug("Searching for: "+expression);
searchService.getTabAwareSuggestions(searchSubsystem, expression, caretPosition, null,
new AsyncCallback<List<SearchSuggestion>>() {
+ @Override
public void onSuccess(List<SearchSuggestion> results) {
ComboBoxItem comboBox = searchBar.getSearchComboboxItem();
@@ -235,8 +239,9 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
Log.debug(results.size() + " suggestions searches fetched in: " + suggestFetchTime + "ms");
}
+ @Override
public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError("Failed to retrieve search suggestion", caught);
+ CoreGUI.getErrorHandler().handleError(MSG.search_failed_to_retrieve_search_suggestion(), caught);
}
});
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java
index e793f9f..c22ccd8 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java
@@ -71,10 +71,10 @@ public class EnhancedSearchBar extends ToolStrip {
private final SearchGWTServiceAsync searchService = GWTServiceLookup.getSearchService();
- private static final List IGNORED_KEYS;
+ private static final List<String> IGNORED_KEYS;
static {
- IGNORED_KEYS = new ArrayList(2);
+ IGNORED_KEYS = new ArrayList<String>(2);
IGNORED_KEYS.add("Arrow_Down");
IGNORED_KEYS.add("Arrow_Up");
}
@@ -253,13 +253,13 @@ public class EnhancedSearchBar extends ToolStrip {
@Override
public void onSuccess(Integer newSavedSearchId) {
currentSearchId = newSavedSearchId;
- Message message = new Message("Successfully Saved Search: " + name, Message.Severity.Info);
+ Message message = new Message(MSG.search_successfully_saved_search(name), Message.Severity.Info);
CoreGUI.getMessageCenter().notify(message);
}
@Override
public void onFailure(Throwable caught) {
- Message message = new Message("Failure to Save Search " + name, Message.Severity.Error);
+ Message message = new Message(MSG.search_failed_to_save_search(name), Message.Severity.Error);
CoreGUI.getMessageCenter().notify(message);
}
});
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java
index a04a000..9cdffbd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java
@@ -102,16 +102,18 @@ public class FavoritesSearchStrategy extends AbstractSearchStrategy {
Subject subject = UserSessionManager.getSessionSubject();
savedSearchCriteria.addFilterSubjectId(subject.getId());
savedSearchCriteria.setStrict(true);
- final long start = System.currentTimeMillis();
+ final long startTime = System.currentTimeMillis();
searchService.findSavedSearchesByCriteria(savedSearchCriteria, new AsyncCallback<List<SavedSearch>>() {
+ @Override
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(MSG.search_failed_to_retrieve_saved_search(), caught);
}
+ @Override
public void onSuccess(List<SavedSearch> result) {
- long fetchTime = System.currentTimeMillis() - start;
+ long fetchTime = System.currentTimeMillis() - startTime;
Log.debug(result.size() + " saved searches fetched in: " + fetchTime + "ms");
DataSource dataSource = new DataSource();
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 2e371d9..a558db1 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -413,8 +413,11 @@ filter_from_date = From
filter_to_date = To
group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+search_failed_to_save_search = Failed to Save Search: {0}
search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
search_name_your_search = name you search
+search_successfully_saved_search = Successfully Saved Search: {0}
util_ancestry_parentAncestry = Parent Ancestry for:
util_errorHandler_nullException = exception was null
util_monitoringRequestCallback_error_checkServerStatusFailure = Unable to determine login status - check Server status.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index 275fe4d..b146b3d 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -432,8 +432,11 @@ filter_from_date = Od
filter_to_date = Do
group_tree_groupOfResourceType = Skupina: [{0}]
group_tree_partialClusterTooltip = {0} z {1} Älenů skupiny má "{2}" zdroj
+##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
##search_name_your_search = name you search
+##search_successfully_saved_search = Successfully Saved Search: {0}
util_ancestry_parentAncestry = Původ rodiÄe pro:
util_errorHandler_nullException = vÃœjimka byla null
util_monitoringRequestCallback_error_checkServerStatusFailure = NepodaÅilo se urÄit stav pÅihlaÅ¡ovánà - zkontrolujte stav serveru.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index ddd07fd..7b9effe 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -397,8 +397,11 @@ filter_from_date = Von
filter_to_date = Bis
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} der {1} Gruppenmitglieder haben eine ''{2}'' Ressource
+##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
##search_name_your_search = name you search
+##search_successfully_saved_search = Successfully Saved Search: {0}
util_disambiguationReportDecorator_pluginSuffix = ({0} Plugin)
util_errorHandler_nullException = Exception war null
##util_monitoringRequestCallback_error_checkServerStatusFailure = Unable to determine login status - check Server status.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index 6eb5212..b7c191e 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -410,8 +410,11 @@ filter_from_date = éå§
filter_to_date = çµäº
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {1} ã®äžã® {0} ã°ã«ãŒãã¡ã³ããŒã ''{2}'' ãªãœãŒã¹ãæã£ãŠããŸã
+##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
##search_name_your_search = name you search
+##search_successfully_saved_search = Successfully Saved Search: {0}
util_ancestry_parentAncestry = 芪ã®å
ç¥ :
util_disambiguationReportDecorator_pluginSuffix = ({0} ãã©ã°ã€ã³)
util_errorHandler_nullException = äŸå€ã¯ null ã§ãã
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 900b847..72b2f34 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -416,8 +416,11 @@ favorites_resources = Recursos Favoritos
##filter_to_date = To
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
##search_name_your_search = name you search
+##search_successfully_saved_search = Successfully Saved Search: {0}
util_ancestry_parentAncestry = Ancestral para:
util_errorHandler_nullException = Exce\u00E7\u00E3o nula
util_monitoringRequestCallback_error_checkServerStatusFailure = Imposs\u00EDvel verificar o status do login - verifique o status do Servidor.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 43abe46..5a44858 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -403,8 +403,11 @@
#filter_from_date = From
#filter_to_date = To
#group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
-##search_name_your_search = name you search
+##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
+##search_name_your_search = name you searci
+##search_successfully_saved_search = Successfully Saved Search: {0}
#util_ancestry_parentAncestry = Parent Ancestry for:
#util_errorHandler_nullException = exception was null
#util_monitoringRequestCallback_error_checkServerStatusFailure = Unable to determine login status - check Server status.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 9f3fd76..6ae9e47 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -405,8 +405,11 @@ favorites_resources = \u8d44\u6e90\u6536\u85cf\u5939
##filter_to_date = To
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = \u9664\u53bb {1},{0}\u7684\u7ec4\u6210\u5458\u62e5\u6709 \u4e00\u4e2a''{2}''\u8d44\u6e90
+##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
##search_name_your_search = name you search
+##search_successfully_saved_search = Successfully Saved Search: {0}
util_ancestry_parentAncestry = Parent Ancestry for:
util_errorHandler_nullException = \u5f02\u5e38\u662f null
util_monitoringRequestCallback_error_checkServerStatusFailure = \u65e0\u6cd5\u786e\u5b9a\u767b\u5f55\u72b6\u6001- \u68c0\u67e5\u670d\u52a1\u5668\u72b6\u6001.
commit f4484a83507fa1f45ea18e5862dceb376efeda1c
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Jul 31 00:24:17 2012 +0200
[BZ 844495] - Fixing the inconsistency in the string handling introduced by
Rhino 1.7R4. The new version of Rhino introduced some performance
optimizations in the script concatenation which confused the script engine,
which is based on the previous versions of Rhino.
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
index e8069a6..0475ecb 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
@@ -78,6 +78,7 @@ import javax.script.SimpleBindings;
import javax.script.SimpleScriptContext;
import org.mozilla.javascript.Callable;
+import org.mozilla.javascript.ConsString;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.Function;
@@ -90,6 +91,7 @@ import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Synchronizer;
import org.mozilla.javascript.Undefined;
+import org.mozilla.javascript.WrapFactory;
import org.mozilla.javascript.Wrapper;
import org.mozilla.javascript.commonjs.module.RequireBuilder;
import org.mozilla.javascript.commonjs.module.provider.ModuleSourceProvider;
@@ -123,6 +125,8 @@ import org.rhq.scripting.javascript.engine.util.InterfaceImplementor;
* Modified to include the "require()" function by default.
* Modified to tighten the security of the script execution by running it in an
* AccessControlContext active at the time of the script engine creation.
+ * Modified to allow correct interoperability between Java and javascript string even
+ * if represented by the custom ConsString instance.
*
* @author Lukas Krejci
*/
@@ -167,7 +171,30 @@ public class RhinoScriptEngine extends AbstractScriptEngine
//LK - added support for CommonJS modules
private RequireBuilder requireBuilder;
+ //LK - custom wrap factory to overcome the difficulties comparing java strings with ConsString instances
+ // introduced by Rhino 1.7R4.
+ private static class CustomWrapFactory extends WrapFactory {
+
+ /**
+ * This behaves exactly the same as the super class' method except the fact that
+ * the ConsString is considered "primitive" and is not wrapped in any manner.
+ * <p>
+ * This is then consistent with the rest of Rhino that expects ConsString as a possible
+ * implementation of the string.
+ */
+ @Override
+ public Object wrap(Context cx, Scriptable scope, Object obj, Class<?> staticType) {
+ if (obj instanceof ConsString) {
+ return obj;
+ }
+
+ return super.wrap(cx, scope, obj, staticType);
+ }
+ }
+
+
//LK - make all the scripts run in an access control context
+ //LK - use a custom wrap factory to overcome the ConsString being mishandled when transferring from java to js and back
static {
ContextFactory.initGlobal(new ContextFactory() {
@Override
@@ -193,9 +220,11 @@ public class RhinoScriptEngine extends AbstractScriptEngine
}
}
+ @Override
protected Context makeContext() {
Context cx = super.makeContext();
cx.setOptimizationLevel(-1);
+ cx.setWrapFactory(new CustomWrapFactory());
return cx;
}
diff --git a/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java
index 7ccde17..6aa9355 100644
--- a/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java
+++ b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java
@@ -78,6 +78,32 @@ public class EngineTest {
assertEquals(captureScriptOutput(script), output, "Unexpected functions found in modules");
}
+ public void stringHandlingConsistent() throws Exception {
+ String script = "var a = \"str\"\n"
+ + "var b = \"str\"\n"
+ + "var test1 = a + b\n"
+ + "var test2 = \"strstr\"\n"
+ + "var test3 = new java.lang.String(\"strstr\")\n";
+
+ ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
+
+ engine.eval(script);
+
+ //now do the tests with the initialized context
+
+ Object ret = engine.eval("test1 == test2");
+ assertEquals(ret, Boolean.TRUE, "Unexpected concatenated and javascript string comparison.");
+
+ ret = engine.eval("test1 == test3");
+ assertEquals(ret, Boolean.TRUE, "Unexpected concatenated and java string comparison.");
+
+ ret = engine.eval("test2 == test3");
+ assertEquals(ret, Boolean.TRUE, "Unexpected javascript and java string comparison.");
+
+ ret = engine.eval("java.lang.Integer.parseInt('1' + '2');");
+ assertEquals(ret, 12, "Engine failed to pass a concatenated string as a string parameter.");
+ }
+
private ScriptEngine getScriptEngine() {
ScriptEngineManager manager = new ScriptEngineManager();
return manager.getEngineByName("rhino-nonjdk");
commit 264bf23cb169b7c2fe73f1756138914752f4f2ee
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Jul 30 10:23:35 2012 -0400
BZ 844217 - Use the correct name for the deployments directory (for bundles).
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java
index a756dea..9d93300 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java
@@ -87,7 +87,7 @@ public class StandaloneASDiscovery extends BaseProcessDiscovery {
// Set deployment directory, which only exists for standalone servers
String baseDir = pluginConfig.getSimpleValue("baseDir");
if (baseDir != null) {
- File deployDir = new File(baseDir, "deployment");
+ File deployDir = new File(baseDir, "deployments");
pluginConfig.put(new PropertySimple("deployDir", deployDir.getPath()));
}
commit c1d8f3211ece139eb08cb3f2ee22747a78f9d821
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri Jul 27 11:24:55 2012 -0400
Allow to run the plugin validator standalone. If done so, also print warnings and errors to stdout/stderr.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginValidator.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginValidator.java
index da50213..73da44f 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginValidator.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginValidator.java
@@ -54,15 +54,19 @@ import org.rhq.core.pluginapi.plugin.PluginLifecycleListener;
public class PluginValidator {
private static final Log LOG = LogFactory.getLog(PluginValidator.class);
private static final String PLUGIN_DESCRIPTOR_PATH = "META-INF/rhq-plugin.xml";
+ static boolean interactive = false;
/**
* If no args are passed in, the current thread's classloader will be used to find the plugins to validate.
* If one or more argument strings are provided, they will be assumed to be paths to the plugin jars to validate
* (in which case the thread's classloader will be ignored and not searched for plugins).
*
+ * If one argument is '-i'. Warnings and Errors will also be printed to stdout and stderr, which helps developers
+ * to find issues when they run the Plugin validator as a standalone tool.
+ *
* The last line this will output will be "!OK!" and exit with an exit code of 0 if everything is OK.
* The last line this will output will be "!FAILURE!" and exit with an exit code of 1 if one or more plugins failed validation.
- *
+ *
* @param args 0 or more plugin jar file paths
*/
public static void main(String[] args) {
@@ -72,6 +76,11 @@ public class PluginValidator {
if (args.length > 0) {
finder = new SimplePluginFinder();
for (String arg : args) {
+ if (arg.equals("-i")) {
+ interactive = true;
+ continue;
+ }
+
URL jarUrl = new File(arg).toURI().toURL();
finder.addUrl(jarUrl);
LOG.info("Plugin jar: " + jarUrl);
@@ -109,7 +118,7 @@ public class PluginValidator {
boolean sizesMatch = (manager.getPlugins().size() == finder.findPlugins().size());
if (!sizesMatch) {
success = false;
- LOG.error("Only [" + manager.getPlugins().size() + "] out of [" + finder.findPlugins().size()
+ errorLog("Only [" + manager.getPlugins().size() + "] out of [" + finder.findPlugins().size()
+ "] plugin descriptors are valid.");
} else {
LOG.info("All [" + finder.findPlugins().size() + "] plugin descriptors are valid.");
@@ -147,47 +156,47 @@ public class PluginValidator {
String componentClass = metadataManager.getComponentClass(resourceType);
if (componentClass == null) {
success = false;
- LOG.error("Missing component class in resource type [" + resourceType.getName() + "] from plugin ["
+ errorLog("Missing component class in resource type [" + resourceType.getName() + "] from plugin ["
+ resourceType.getPlugin() + "]");
} else {
try {
Class componentClazz = Class.forName(componentClass, false, pluginEnvironment.getPluginClassLoader());
if (!ResourceComponent.class.isAssignableFrom(componentClazz)) {
success = false;
- LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ "] from plugin [" + resourceType.getPlugin() + "] does not implement "
+ ResourceComponent.class);
}
if (!resourceType.getMetricDefinitions().isEmpty()
&& !MeasurementFacet.class.isAssignableFrom(componentClazz)) {
success = false;
- LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ "] from plugin [" + resourceType.getPlugin()
+ "] does not support the measurement collection facet but defines metrics.");
}
if (!resourceType.getOperationDefinitions().isEmpty()
&& !OperationFacet.class.isAssignableFrom(componentClazz)) {
success = false;
- LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ "] from plugin [" + resourceType.getPlugin()
+ "] does not support the operations facet but defines operations.");
}
if (resourceType.getBundleType() != null && !BundleFacet.class.isAssignableFrom(componentClazz)) {
success = false;
- LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ "] from plugin [" + resourceType.getPlugin()
+ "] does not support the bundle facet but defines a bundle type.");
}
if (!resourceType.getPackageTypes().isEmpty() && !ContentFacet.class.isAssignableFrom(componentClazz)) {
success = false;
- LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ "] from plugin [" + resourceType.getPlugin()
+ "] does not support the content management facet but defines package types.");
}
if (resourceType.getResourceConfigurationDefinition() != null
&& !ConfigurationFacet.class.isAssignableFrom(componentClazz)) {
success = false;
- LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ "] from plugin [" + resourceType.getPlugin()
+ "] does not support the configuration facet but defines resource configuration.");
}
@@ -200,19 +209,19 @@ public class PluginValidator {
}
if (hasCreatableChild && !CreateChildResourceFacet.class.isAssignableFrom(componentClazz)) {
success = false;
- LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ "] from plugin [" + resourceType.getPlugin()
+ "] does not support the child creation facet but has metadata saying it can.");
}
if (resourceType.isDeletable() && !DeleteResourceFacet.class.isAssignableFrom(componentClazz)) {
success = false;
- LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+ "] from plugin [" + resourceType.getPlugin()
+ "] does not support delete resource facet but has metadata saying it can delete children.");
}
} catch (Exception e) {
success = false;
- LOG.error("Cannot find component class [" + componentClass + "] for resource type ["
+ errorLog("Cannot find component class [" + componentClass + "] for resource type ["
+ resourceType.getName() + "] from plugin [" + resourceType.getPlugin() + "].");
}
}
@@ -228,18 +237,18 @@ public class PluginValidator {
Class discoveryClazz = Class.forName(discoveryClass, false, pluginEnvironment.getPluginClassLoader());
if (!ResourceDiscoveryComponent.class.isAssignableFrom(discoveryClazz)) {
success = false;
- LOG.error("Discovery class [" + discoveryClass + "] for resource type [" + resourceType.getName()
+ errorLog("Discovery class [" + discoveryClass + "] for resource type [" + resourceType.getName()
+ "] from plugin [" + resourceType.getPlugin() + "] does not implement "
+ ResourceDiscoveryComponent.class);
}
if (resourceType.isSupportsManualAdd() && !ManualAddFacet.class.isAssignableFrom(discoveryClazz)) {
- LOG.warn("Discovery class [" + discoveryClass + "] for resource type [" + resourceType.getName()
+ warnLog("Discovery class [" + discoveryClass + "] for resource type [" + resourceType.getName()
+ "] from plugin [" + resourceType.getPlugin() + "] does not implement " + ManualAddFacet.class
+ " - implementing manual-add in discoverResources() is deprecated.");
}
} catch (Exception e) {
success = false;
- LOG.error("Cannot find discovery class [" + discoveryClass + "] for resource type ["
+ errorLog("Cannot find discovery class [" + discoveryClass + "] for resource type ["
+ resourceType.getName() + "] from plugin [" + resourceType.getPlugin() + "].");
}
}
@@ -255,12 +264,12 @@ public class PluginValidator {
Class overseerClazz = Class.forName(overseerClass, false, pluginEnvironment.getPluginClassLoader());
if (!PluginLifecycleListener.class.isAssignableFrom(overseerClazz)) {
success = false;
- LOG.error("Plugin Lifecycle Listener class [" + overseerClass + "] for plugin ["
+ errorLog("Plugin Lifecycle Listener class [" + overseerClass + "] for plugin ["
+ resourceType.getPlugin() + "] does not implement " + PluginLifecycleListener.class);
}
} catch (Exception e) {
success = false;
- LOG.error("Cannot find Plugin Lifecycle Listener class [" + overseerClass + "] for plugin ["
+ errorLog("Cannot find Plugin Lifecycle Listener class [" + overseerClass + "] for plugin ["
+ resourceType.getPlugin() + "].");
}
}
@@ -279,10 +288,22 @@ public class PluginValidator {
pluginFinder.addUrl(jarUrl);
LOG.info("Found plugin jar: " + jarUrl);
} else {
- LOG.warn("Found a plugin descriptor outside of a jar, skipping: " + descriptorUrl);
+ warnLog("Found a plugin descriptor outside of a jar, skipping: " + descriptorUrl);
}
}
return pluginFinder;
}
+
+ private static void errorLog(String errorMessage) {
+ LOG.error(errorMessage);
+ if (interactive)
+ System.err.println(errorMessage);
+ }
+
+ private static void warnLog(String warningMessage) {
+ LOG.warn(warningMessage);
+ if (interactive)
+ System.out.println(warningMessage);
+ }
}
\ No newline at end of file
diff --git a/modules/enterprise/agent/src/etc/plugin-validator.sh b/modules/enterprise/agent/src/etc/plugin-validator.sh
new file mode 100755
index 0000000..803ff6c
--- /dev/null
+++ b/modules/enterprise/agent/src/etc/plugin-validator.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in lib/*.jar
+do
+ CP=$CP:$i
+done
+java -cp $CP org.rhq.core.pc.plugin.PluginValidator -i $*
commit 3fd82d43b6e74a1fe9c6a7a4e9c017f4882b725d
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Jul 25 09:39:09 2012 -0400
Put the standalone container start scripts directly in the agent distro, to make it easier to use them for developers.
diff --git a/etc/standalone-pc/README.txt b/etc/standalone-pc/README.txt
index b940187..c71fda7 100644
--- a/etc/standalone-pc/README.txt
+++ b/etc/standalone-pc/README.txt
@@ -8,6 +8,9 @@ alternatively copy an existing agent directory
Copy the standalone.(sh|bat) script to this agent directory in bin/ next to the
existing rhq-agent.(sh|bat) scripts
+AS OF RHQ 4.5 the scripts are already installed as standalone-pc.(sh|bat) in the
+bin/ directory of the agent.
+
If you have no plugins in the plugin/ directory, then copy at least the rhq-platform-*.jar
to plugins/ (e.g. from the rhq.ear/rhq-ownloads/rhq-plugins) directory of the server.
diff --git a/etc/standalone-pc/standalone.bat b/etc/standalone-pc/standalone.bat
deleted file mode 100644
index c8da8a3..0000000
--- a/etc/standalone-pc/standalone.bat
+++ /dev/null
@@ -1,9 +0,0 @@
-@echo off
-
-rem uncomment below if you want to enable JPDA debugging
-rem set RHQ_AGENT_ADDITIONAL_JAVA_OPTS=-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=9797,server=y,suspend=n
-
-setlocal
-set RHQ_AGENT_MAINCLASS=org.rhq.core.pc.StandaloneContainer
-call rhq-agent.bat %*
-endlocal
diff --git a/etc/standalone-pc/standalone.sh b/etc/standalone-pc/standalone.sh
deleted file mode 100755
index d8ffef6..0000000
--- a/etc/standalone-pc/standalone.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-_DOLLARZERO=`readlink "$0" 2>/dev/null || echo "$0"`
-RHQ_AGENT_BIN_DIR_PATH=`dirname "$_DOLLARZERO"`
-RHQ_AGENT_MAINCLASS=org.rhq.core.pc.StandaloneContainer
-export RHQ_AGENT_MAINCLASS
-
-# uncomment below if you want to enable JPDA debugging
-#RHQ_AGENT_ADDITIONAL_JAVA_OPTS="-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=9797,server=y,suspend=n"
-#export RHQ_AGENT_ADDITIONAL_JAVA_OPTS
-
-$RHQ_AGENT_BIN_DIR_PATH/rhq-agent.sh $*
diff --git a/modules/enterprise/agent/src/etc/standalone-pc.bat b/modules/enterprise/agent/src/etc/standalone-pc.bat
new file mode 100644
index 0000000..c8da8a3
--- /dev/null
+++ b/modules/enterprise/agent/src/etc/standalone-pc.bat
@@ -0,0 +1,9 @@
+@echo off
+
+rem uncomment below if you want to enable JPDA debugging
+rem set RHQ_AGENT_ADDITIONAL_JAVA_OPTS=-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=9797,server=y,suspend=n
+
+setlocal
+set RHQ_AGENT_MAINCLASS=org.rhq.core.pc.StandaloneContainer
+call rhq-agent.bat %*
+endlocal
diff --git a/modules/enterprise/agent/src/etc/standalone-pc.sh b/modules/enterprise/agent/src/etc/standalone-pc.sh
new file mode 100755
index 0000000..d8ffef6
--- /dev/null
+++ b/modules/enterprise/agent/src/etc/standalone-pc.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+_DOLLARZERO=`readlink "$0" 2>/dev/null || echo "$0"`
+RHQ_AGENT_BIN_DIR_PATH=`dirname "$_DOLLARZERO"`
+RHQ_AGENT_MAINCLASS=org.rhq.core.pc.StandaloneContainer
+export RHQ_AGENT_MAINCLASS
+
+# uncomment below if you want to enable JPDA debugging
+#RHQ_AGENT_ADDITIONAL_JAVA_OPTS="-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=9797,server=y,suspend=n"
+#export RHQ_AGENT_ADDITIONAL_JAVA_OPTS
+
+$RHQ_AGENT_BIN_DIR_PATH/rhq-agent.sh $*
commit 7da515fa212ddf4903984c1b24092523fc4136a0
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Jul 25 09:23:49 2012 -0400
Fix a small typo.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
index c032481..5ee68f4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
@@ -58,7 +58,7 @@ public interface AlertHandlerLocal {
@GZIP
@GET
@Path("/")
- @ApiOperation(value = "List all alerts", multiValueResponse = true, responseClass = "List<AlertRest")
+ @ApiOperation(value = "List all alerts", multiValueResponse = true, responseClass = "List<AlertRest>")
Response listAlerts(
@ApiParam(value = "Page number", defaultValue = "0") @QueryParam("page") int page,
@ApiParam(value = "Limit to priority", allowableValues = "High, Medium, Low, All") @DefaultValue("All") @QueryParam("prio") String prio,
commit 0170a5ac909fd4120fd88f9d01fb039851289261
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Sat Jul 21 15:46:03 2012 -0400
[BZ 840512] Fix for issue with Obfuscated properties affecting CSP credentials.
- Removed earlier workaround for failed deobfuscation
- Reimplement Obfuscation without symmetric Hibernate annotations
- Now PostLoad is only used to deobfuscate for in memory use of Obfuscated properties.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java
index 779b795..07b3467 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java
@@ -26,10 +26,6 @@ import java.io.ObjectOutputStream;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.PostLoad;
-import javax.persistence.PostPersist;
-import javax.persistence.PostUpdate;
-import javax.persistence.PrePersist;
-import javax.persistence.PreUpdate;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@@ -43,6 +39,9 @@ import org.rhq.core.util.obfuscation.Obfuscator;
* This is a specialization of {@link PropertySimple} that provides password obfuscation
* methods.
*
+ * In memory, the value is always kept in clear text. It is only at persisting or
+ * serialization time that the value is stored in its obfuscated form.
+ *
* @author Lukas Krejci
*/
@DiscriminatorValue("obfuscated")
@@ -51,10 +50,15 @@ import org.rhq.core.util.obfuscation.Obfuscator;
@XmlRootElement
public class ObfuscatedPropertySimple extends PropertySimple {
+ //note that while there were changes since RHQ 4.4.0.GA (or JON 3.1.0.GA) version of this class
+ //the serialization has NOT changed. The over-the-wire format of this class remained the same.
+ //Hence, serializationVersionUID is still at 1.
private static final long serialVersionUID = 1L;
private static final Log LOG = LogFactory.getLog(ObfuscatedPropertySimple.class);
+ private transient String clearTextValue;
+
public ObfuscatedPropertySimple() {
}
@@ -74,6 +78,16 @@ public class ObfuscatedPropertySimple extends PropertySimple {
*/
protected ObfuscatedPropertySimple(PropertySimple original, boolean keepId) {
super(original, keepId);
+ setValue(original.getStringValue());
+ }
+
+ /**
+ * @param original
+ * @param keepId
+ */
+ protected ObfuscatedPropertySimple(ObfuscatedPropertySimple original, boolean keepId) {
+ super(original, keepId);
+ this.clearTextValue = original.clearTextValue;
}
/**
@@ -81,7 +95,8 @@ public class ObfuscatedPropertySimple extends PropertySimple {
* @param value
*/
public ObfuscatedPropertySimple(String name, Object value) {
- super(name, value);
+ super(name, null);
+ setValue(value);
}
@Override
@@ -89,50 +104,132 @@ public class ObfuscatedPropertySimple extends PropertySimple {
return new ObfuscatedPropertySimple(this, keepId);
}
+ @PostLoad
+ protected void initClearTextValue() {
+ clearTextValue = deobfuscate(getObfuscatedStringValue());
+ }
+
/**
- * We deobfuscate right after the entity has been loaded from the database or right
- * after we persist or update the value.
- *
- * Because we change the value before persist or update, we have to swap the value back
- * as soon as those DB changes are done, so that we only use the raw value in memory.
+ * @return the value as being stored in the database
*/
- @PostLoad
- @PostPersist
- @PostUpdate
- protected void deobfuscate() {
- String value = getStringValue();
- if (value != null) {
- try {
- setStringValue(Obfuscator.decode(getStringValue()));
- } catch (Exception e) {
- LOG.error("Failed to deobfuscate property value: [" + value + "]", e);
- }
+ public String getObfuscatedStringValue() {
+ return super.getStringValue();
+ }
+
+ /**
+ * The value of this property as string. Note that this is always in "clear text". I.e. the value
+ * you get from this method is NOT obfuscated (but it gets stored in the database obfuscated).
+ */
+ @Override
+ public String getStringValue() {
+ return clearTextValue;
+ }
+
+ /**
+ * Sets the value of this property. You should pass the "clear text" value - the obfuscation of
+ * the value in the database is done for you behind the scenes.
+ */
+ @Override
+ public void setValue(Object value) {
+ //just use the logic in the superclass to set the value
+ super.setValue(value);
+ //and obtain the result
+ this.clearTextValue = super.getStringValue();
+
+ //now set the underlying value to the obfuscated one
+ super.setValue(obfuscate(clearTextValue));
+
+ //now we have the clear text string representation of the value in "clearTextValue",
+ //the stringValue in the superclass contains the corresponding obfuscated string.
+ }
+
+
+ @Override
+ public Boolean getBooleanValue() {
+ String val = getStringValue();
+ return val == null ? null : Boolean.valueOf(val);
+ }
+
+ @Override
+ public Long getLongValue() {
+ String val = getStringValue();
+ return val == null ? null : Long.valueOf(val);
+ }
+
+ @Override
+ public Integer getIntegerValue() {
+ String val = getStringValue();
+ return val == null ? null : Integer.valueOf(val);
+ }
+
+ @Override
+ public Float getFloatValue() {
+ String val = getStringValue();
+ return val == null ? null : Float.valueOf(val);
+ }
+
+ @Override
+ public Double getDoubleValue() {
+ String val = getStringValue();
+ return val == null ? null : Double.valueOf(val);
+ }
+
+ @Override
+ public boolean isMasked() {
+ return MASKED_VALUE.equals(getStringValue());
+ }
+
+ @Override
+ public void mask() {
+ if (getStringValue() != null) {
+ setValue(MASKED_VALUE);
+ }
+ }
+
+ protected String deobfuscate(String value) {
+ try {
+ return value == null ? null : Obfuscator.decode(value);
+ } catch (NumberFormatException nfe) {//detect unobfuscated properties from before patch
+ //Assuming that this was in incorrect state from BZ840512
+ //logging that we found an unobfuscated value and if it's not part of patch/upgrade contact administrator
+ LOG.error("Failed to deobfuscate property value: [" + value + "]. If this is not part of a patch/upgrade "
+ + "then you should contact System Administrator to have the property details reset.");
+ //Returning plain value to prevent Content Source load failure. On save should be correctly obfuscated
+ return value;
+ } catch (Exception e) {
+ LOG.error("Failed to deobfuscate property value: [" + value + "]", e);
+ throw new IllegalArgumentException("Failed to deobfuscate property value: [" + value + "]", e);
}
}
/**
* Obfuscate the value right before it gets pushed down to the database.
*/
- @PrePersist
- @PreUpdate
- protected void obfuscate() {
- String value = getStringValue();
- if (value != null) {
- try {
- setStringValue(Obfuscator.encode(value));
- } catch (Exception e) {
- LOG.error("Failed to obfuscate property value: [" + value + "]", e);
- }
+ protected String obfuscate(String value) {
+ try {
+ return value == null ? null : Obfuscator.encode(value);
+ } catch (Exception e) {
+ LOG.error("Failed to obfuscate property value: [" + value + "]", e);
+ throw new IllegalArgumentException("Failed to obfuscate property value: [" + value + "]", e);
}
}
+ /**
+ * Overriden to not leak the unobfuscated value in the toString() method, output of which
+ * might end up in logs, etc.
+ */
+ @Override
+ protected void appendToStringInternals(StringBuilder str) {
+ str.append(", obfuscated-value=").append(getObfuscatedStringValue());
+ str.append(", override=").append(getOverride());
+ };
+
private void writeObject(ObjectOutputStream str) throws IOException {
- obfuscate();
str.defaultWriteObject();
}
private void readObject(ObjectInputStream str) throws IOException, ClassNotFoundException {
str.defaultReadObject();
- deobfuscate();
+ initClearTextValue();
}
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertySimple.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertySimple.java
index 8edc331..dd7aebd 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertySimple.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertySimple.java
@@ -55,7 +55,7 @@ public class PropertySimple extends Property implements Serializable {
* clients from being able to view the current value of PASSWORD properties. The value is made obscure enough to
* make the chances of it being the same as the property's unmasked value next to nil.
*/
- private static final String MASKED_VALUE = "_._._[MaSKeD]_._._";
+ public static final String MASKED_VALUE = "_._._[MaSKeD]_._._";
@Column(name = "string_value", length = MAX_VALUE_LENGTH)
private String stringValue;
diff --git a/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java b/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java
index 4b3516a..4061980 100644
--- a/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java
+++ b/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java
@@ -21,6 +21,8 @@ package org.rhq.enterprise.server.plugins.jboss.software;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import churchillobjects.rss4j.RssDocument;
@@ -38,7 +40,6 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
-import org.rhq.core.util.obfuscation.Obfuscator;
import org.rhq.enterprise.server.plugin.pc.content.ContentProvider;
import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails;
import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
@@ -221,16 +222,6 @@ public class JBossSoftwareContentSourceAdapter implements ContentProvider, Packa
int status = client.executeMethod(method);
- //BZ840512: check for issue deobfuscating the password:
- if (status == 401 || status == 403) {
- password = Obfuscator.decode(password);//in case de/unobfuscation failed.
- UsernamePasswordCredentials upc = new UsernamePasswordCredentials(username, password);
- client.getState().setCredentials("users", method.getHostConfiguration().getHost(), upc);
- log.warn("You have either input bad Content Source credentials or"
- + " there is a problem retrieving obfuscated passwords. Retrying...");
- status = client.executeMethod(method);
- }
-
//Check to see if redirection has occurred
String currentUrl = method.getURI().getURI();
//if redirection has occurred, reconnect with correct address.
commit 4f7c64deab774aee682daa5c37352509ed0422ac
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri Jul 20 11:31:48 2012 -0400
BZ 839080 - accept pid files that also contain whitespace or line endings (\n \r )
diff --git a/modules/core/native-system/src/main/java/org/rhq/core/system/pquery/ProcessInfoQuery.java b/modules/core/native-system/src/main/java/org/rhq/core/system/pquery/ProcessInfoQuery.java
index 82486ca..1e9eeb3 100644
--- a/modules/core/native-system/src/main/java/org/rhq/core/system/pquery/ProcessInfoQuery.java
+++ b/modules/core/native-system/src/main/java/org/rhq/core/system/pquery/ProcessInfoQuery.java
@@ -470,6 +470,6 @@ public class ProcessInfoQuery {
contents = "";
}
- return contents;
+ return contents.trim();
}
}
\ No newline at end of file
diff --git a/modules/core/native-system/src/test/java/org/rhq/core/system/pquery/ProcessInfoQueryTest.java b/modules/core/native-system/src/test/java/org/rhq/core/system/pquery/ProcessInfoQueryTest.java
index bc8d77d..466983a 100644
--- a/modules/core/native-system/src/test/java/org/rhq/core/system/pquery/ProcessInfoQueryTest.java
+++ b/modules/core/native-system/src/test/java/org/rhq/core/system/pquery/ProcessInfoQueryTest.java
@@ -291,6 +291,61 @@ public class ProcessInfoQueryTest {
}
/**
+ * Test PID files.
+ *
+ * @throws Exception
+ */
+ public void testPIQLPidfileNL() throws Exception {
+ File pidfile = File.createTempFile("test", ".pid");
+ try {
+ FileOutputStream fos = new FileOutputStream(pidfile);
+ fos.write("3\n".getBytes());
+ fos.flush();
+ fos.close();
+
+ results = query.query("process|pidfile|match=" + pidfile.getCanonicalPath());
+ assert results.size() == 1 : results;
+ assertPidExists(3, results, "pidfile had pid #3 in it and should have matched pid 3");
+
+ results = query.query("process|pidfile|nomatch=" + pidfile.getCanonicalPath());
+ assert results.size() == (query.getProcesses().size() - 1) : "should match all but pid 3:" + results;
+ assertPidDoesNotExist(3, results, "pidfile had pid #3 in it so .ne should not have matched pid 3");
+
+ results = query.query("process|pidfile|match|parent=" + pidfile.getCanonicalPath());
+ assert results.size() == 2 : "there are two child procs of parent process found in pidfile:" + results;
+ assertPidExists(4, results, "");
+ assertPidExists(5, results, "");
+ } finally {
+ pidfile.delete();
+ }
+ }
+
+ public void testPIQLPidfileNLLF() throws Exception {
+ File pidfile = File.createTempFile("test", ".pid");
+ try {
+ FileOutputStream fos = new FileOutputStream(pidfile);
+ fos.write("3\r\n".getBytes());
+ fos.flush();
+ fos.close();
+
+ results = query.query("process|pidfile|match=" + pidfile.getCanonicalPath());
+ assert results.size() == 1 : results;
+ assertPidExists(3, results, "pidfile had pid #3 in it and should have matched pid 3");
+
+ results = query.query("process|pidfile|nomatch=" + pidfile.getCanonicalPath());
+ assert results.size() == (query.getProcesses().size() - 1) : "should match all but pid 3:" + results;
+ assertPidDoesNotExist(3, results, "pidfile had pid #3 in it so .ne should not have matched pid 3");
+
+ results = query.query("process|pidfile|match|parent=" + pidfile.getCanonicalPath());
+ assert results.size() == 2 : "there are two child procs of parent process found in pidfile:" + results;
+ assertPidExists(4, results, "");
+ assertPidExists(5, results, "");
+ } finally {
+ pidfile.delete();
+ }
+ }
+
+ /**
* Test regular expressions.
*/
public void testPIQLProcessNameRegularExpression() {
commit c5d2853bba213e53a2e50b1e67394f32b1f43fc1
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Jul 18 16:00:02 2012 -0400
Explicitly remove availability entries, as there is no cascade delete from resource to availability.
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/drift/JPADriftChangeSetTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/drift/JPADriftChangeSetTest.java
index b2eddb3..d6bf7c1 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/drift/JPADriftChangeSetTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/drift/JPADriftChangeSetTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011-2012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -34,11 +34,11 @@ import org.testng.annotations.Test;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.drift.DriftConfigurationDefinition.DriftHandlingMode;
+import org.rhq.core.domain.measurement.Availability;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.shared.ResourceBuilder;
import org.rhq.core.domain.shared.ResourceTypeBuilder;
-import org.rhq.core.domain.test.AbstractEJB3Test;
import org.rhq.test.TransactionCallback;
public class JPADriftChangeSetTest extends DriftDataAccessTest {
@@ -79,6 +79,11 @@ public class JPADriftChangeSetTest extends DriftDataAccessTest {
private void purgeDB() {
EntityManager em = getEntityManager();
+ List<Availability> avails = (List<Availability>) em.createQuery("SELECT a FROM Availability a").getResultList();
+ for (Availability a : avails) {
+ em.remove(a);
+ }
+
List<Resource> resources = (List<Resource>) em.createQuery("from Resource where resourceType.name = :name")
.setParameter("name", RESOURCE_TYPE_NAME).getResultList();
for (Resource resource : resources) {
commit 82777d7d70ec46338aaa1b662099b0dcb653c67d
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Jul 18 15:44:03 2012 -0400
Test very long tokens.
diff --git a/modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityTest.java b/modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityTest.java
index a7e9f77..93bd5b8 100644
--- a/modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityTest.java
+++ b/modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityTest.java
@@ -76,6 +76,19 @@ public class ObjectNameQueryUtilityTest {
onqu = new ObjectNameQueryUtility("a:b=c,d={e},f={g}", c);
System.out.println("Template: " + onqu.getQueryTemplate());
assert onqu.getQueryTemplate().equals("a:b=c,d=foo,f=bar");
+
+ // Test some very long replacement tokens inspired by BZ 828596
+ onqu = new ObjectNameQueryUtility("*:type=HttpMetricInspector,name=%name%");
+ assert onqu.getQueryTemplate().equals("*:type=HttpMetricInspector,name=%name%");
+ assert onqu.getVariableProperties().size() == 1;
+ assert onqu.getVariableProperties().get("name").equals("name");
+ testON = new ObjectName("FooBarABCDEFGHIJKLMNOPQRSTUVWXYZ:type=HttpMetricInspector,name=ABCDEFGHIJKLMNOPQRSTUVWXYZöABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ onqu.setMatchedKeyValues(testON.getKeyPropertyList());
+ formulatedMessageTemplate = "Http metrics for endpoint {name}";
+ String res = onqu.formatMessage(formulatedMessageTemplate);
+ assert res.equals("Http metrics for endpoint ABCDEFGHIJKLMNOPQRSTUVWXYZöABCDEFGHIJKLMNOPQRSTUVWXYZ") : res;
+
+
}
@Test
commit d554ac2d56373ecf1e692e5c356f9e7c22a0a6e5
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Wed Jul 18 14:42:52 2012 +0200
adding a plugin for creating the dependency graph among maven modules when running mvn site:site
diff --git a/pom.xml b/pom.xml
index 8e99665..3dcca11 100644
--- a/pom.xml
+++ b/pom.xml
@@ -721,6 +721,26 @@
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>${animal.sniffer.version}</version>
</plugin>
+ <plugin>
+ <groupId>com.googlecode.maven-overview-plugin</groupId>
+ <artifactId>maven-overview-plugin</artifactId>
+ <version>RELEASE</version>
+ <configuration>
+ <width>4096</width>
+ <height>4096</height>
+ <maxDepth>0</maxDepth>
+ <suppressedScopes>provided, test</suppressedScopes>
+ <includes>${rhq.groupId}</includes>
+ <exclusions>
+ <exclusion>
+ <scope>test</scope>
+ </exclusion>
+ <!--<exclusion>
+ <scope>provided</scope>
+ </exclusion>-->
+ </exclusions>
+ </configuration>
+ </plugin>
</plugins>
</pluginManagement>
@@ -1294,6 +1314,11 @@
<reporting>
<plugins>
+ <plugin>
+ <groupId>com.googlecode.maven-overview-plugin</groupId>
+ <artifactId>maven-overview-plugin</artifactId>
+ </plugin>
+
<!--
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
@@ -1438,6 +1463,12 @@
<timezone>+1</timezone>
</developer>
<developer>
+ <name>Jirka Kremser</name>
+ <email>jkremser(a)redhat.com</email>
+ <timezone>+1</timezone>
+ <url>http://serviceasaservice.wordpress.com/</url>
+ </developer>
+ <developer>
<name>Joseph Marques</name>
<url>http://josephmarques.wordpress.com/</url>
<timezone>-5</timezone>
commit 1704544f28ee4781e5b8a18cb93c3622e74e551b
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jul 17 11:25:42 2012 -0700
[BZ 815305] Min/max constraints. Fix db-upgrade.xml to addColumn instead of alterColumn and change column names to MIN_ENTRIES from MIN and MAX_ENTRIES from MAX so that we dont have any conflicts with other databases.
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml
index 7e189d9..d5d937e 100644
--- a/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml
+++ b/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml
@@ -27,8 +27,8 @@
<column name="NAME" type="VARCHAR2" required="false" size="255"/>
<column name="DISPLAY_NAME" type="VARCHAR2" required="false" size="100"/>
<column name="DESCRIPTION" type="VARCHAR2" required="false" size="1000"/>
- <column name="MIN" type="INTEGER" required="false" />
- <column name="MAX" type="INTEGER" required="false" />
+ <column name="MIN_ENTRIES" type="INTEGER" required="false" />
+ <column name="MAX_ENTRIES" type="INTEGER" required="false" />
<column name="DEFAULT_VALUE" type="VARCHAR2" required="false" size="2000"/>
<column name="REQUIRED" type="BOOLEAN" required="false"/>
<column name="READONLY" type="BOOLEAN" required="false"/>
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index 2aafb72..2cee9f4 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -4008,8 +4008,8 @@
</schemaSpec>
<schemaSpec version="2.122">
- <schema-alterColumn table="RHQ_CONFIG_PROP_DEF" column="MIN" columnType="INTEGER"/>
- <schema-alterColumn table="RHQ_CONFIG_PROP_DEF" column="MAX" columnType="INTEGER"/>
+ <schema-addColumn table="RHQ_CONFIG_PROP_DEF" column="MIN_ENTRIES" columnType="INTEGER"/>
+ <schema-addColumn table="RHQ_CONFIG_PROP_DEF" column="MAX_ENTRIES" columnType="INTEGER"/>
</schemaSpec>
</dbupgrade>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
index a3b11a6..adf1f34 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
@@ -25,6 +25,7 @@ package org.rhq.core.domain.configuration.definition;
import java.lang.Integer;
import javax.persistence.CascadeType;
+import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
@@ -49,8 +50,10 @@ import org.jetbrains.annotations.NotNull;
public class PropertyDefinitionList extends PropertyDefinition {
private static final long serialVersionUID = 1L;
+ @Column(name = "MIN_ENTRIES")
private int min = 0;
+ @Column(name = "MAX_ENTRIES")
private int max = Integer.MAX_VALUE;
@JoinColumn(name = "parent_list_definition_id")
commit 04b9e55a116c31d5da3d919e213bb29a33e37f4b
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue Jul 17 13:41:13 2012 -0400
[Bug 839256 - FailoverListManagerBeanTest fail on OpenJDK 1.7]
The fixes that helped java7 hurt java6, so for java6's sake, relax the
unit test balancing validation a tick more.
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java
index 1c59b16..ac07e18 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java
@@ -242,8 +242,13 @@ public class FailoverListManagerBeanTest extends AbstractEJB3Test {
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 through tertiary levels that's pretty good.
- if (level > 3) {
+ // 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;
}
commit 58a4d6fb96fde3310ca27de7b344ff89c2c684aa
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Jul 16 16:47:23 2012 -0700
Fix imports to follow RHQ eclipse standards.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
index 92c8df6..a3b11a6 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
@@ -22,6 +22,8 @@
*/
package org.rhq.core.domain.configuration.definition;
+import java.lang.Integer;
+
import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@@ -33,7 +35,6 @@ import javax.xml.bind.annotation.XmlSeeAlso;
import org.jetbrains.annotations.NotNull;
-import java.lang.Integer;
/**
* The definition of a list of properties where each member of the list has the same definition. The definition of the
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
index 31e58e6..d82d2ee 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
@@ -25,11 +25,19 @@ import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.util.BooleanCallback;
import com.smartgwt.client.util.SC;
-import com.smartgwt.client.widgets.*;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.HTMLFlow;
+import com.smartgwt.client.widgets.IButton;
+import com.smartgwt.client.widgets.Img;
+import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.events.DoubleClickHandler;
-import com.smartgwt.client.widgets.form.fields.*;
+import com.smartgwt.client.widgets.form.fields.FormItem;
+import com.smartgwt.client.widgets.form.fields.HiddenItem;
+import com.smartgwt.client.widgets.form.fields.SelectItem;
+import com.smartgwt.client.widgets.form.fields.SpinnerItem;
+import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import com.smartgwt.client.widgets.form.fields.events.KeyPressEvent;
@@ -44,9 +52,23 @@ import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.RefreshableView;
import org.rhq.enterprise.gui.coregui.client.components.buttons.BackButton;
import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedSearchBarItem;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.*;
-
-import java.util.*;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableHLayout;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableIButton;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableIMenuButton;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableMenu;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableToolStrip;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
* Similar to (i.e. originally a copy of) Table but instead of encapsulating a ListGrid, it manages a list of
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
index b2084df..9bb1dfa 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
@@ -18,6 +18,24 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.resource;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.AVAILABILITY;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.CATEGORY;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.CTIME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.DESCRIPTION;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.ITIME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.KEY;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.LOCATION;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.MODIFIER;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.MTIME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.NAME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.PLUGIN;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.TYPE;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.VERSION;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
@@ -28,6 +46,7 @@ import com.smartgwt.client.data.fields.DataSourceIntegerField;
import com.smartgwt.client.data.fields.DataSourceTextField;
import com.smartgwt.client.rpc.RPCResponse;
import com.smartgwt.client.widgets.grid.ListGridRecord;
+
import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.resource.Resource;
@@ -44,12 +63,6 @@ import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.*;
-
/**
* @author Greg Hinkle
*/
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java
index 4a1a06f..2f0ad01 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java
@@ -18,8 +18,25 @@
*/
package org.rhq.enterprise.gui.coregui.client.util;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
import com.google.gwt.core.client.JavaScriptObject;
-import com.smartgwt.client.data.*;
+import com.smartgwt.client.data.Criteria;
+import com.smartgwt.client.data.DSRequest;
+import com.smartgwt.client.data.DSResponse;
+import com.smartgwt.client.data.DataSource;
+import com.smartgwt.client.data.DataSourceField;
+import com.smartgwt.client.data.Record;
+import com.smartgwt.client.data.SortSpecifier;
import com.smartgwt.client.data.fields.DataSourceIntegerField;
import com.smartgwt.client.data.fields.DataSourceTextField;
import com.smartgwt.client.rpc.RPCResponse;
@@ -30,6 +47,7 @@ import com.smartgwt.client.util.JSOHelper;
import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator;
import com.smartgwt.client.widgets.form.validator.LengthRangeValidator;
import com.smartgwt.client.widgets.grid.ListGridRecord;
+
import org.rhq.core.domain.alert.AlertPriority;
import org.rhq.core.domain.criteria.BaseCriteria;
import org.rhq.core.domain.drift.DriftCategory;
@@ -47,8 +65,6 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message;
import org.rhq.enterprise.gui.coregui.client.util.rpc.DataSourceResponseStatistics;
import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
-import java.util.*;
-
/**
* Base GWT-RPC oriented DataSource class.
*
@@ -594,7 +610,7 @@ public abstract class RPCDataSource<T, C extends BaseCriteria> extends DataSourc
Map<String, Object> criteriaMap = criteria.getValues();
for (Map.Entry<String, Object> nextEntry : criteriaMap.entrySet()) {
- Log.debug("Request Criteria: "+nextEntry.getKey() + ":" + nextEntry.getValue());
+ Log.debug("Request Criteria: " + nextEntry.getKey() + ":" + nextEntry.getValue());
}
}
@@ -628,13 +644,12 @@ public abstract class RPCDataSource<T, C extends BaseCriteria> extends DataSourc
}
//if (Log.isDebugEnabled() && result != null) {
- Log.debug("Filter: " + paramName + "=[" + result + "]");
+ Log.debug("Filter: " + paramName + "=[" + result + "]");
//}
return result;
}
-
protected static DataSourceTextField createTextField(String name, String title, Integer minLength,
Integer maxLength, Boolean required) {
DataSourceTextField textField = new DataSourceTextField(name, title);
commit 0fe3c6d7b0f6c6845bfc4ef59c767fc6ad8715c0
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Jul 16 14:55:06 2012 -0700
[BZ 815305] Min/max constraints. This second part of the fix addresses the database schema change and upgrade to schema 2.122.
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index 3947b19..d4b5505 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -17,7 +17,7 @@
<description>Database schema setup, upgrade and other utilities</description>
<properties>
- <db.schema.version>2.121</db.schema.version>
+ <db.schema.version>2.122</db.schema.version>
<rhq.ds.type-mapping>${rhq.test.ds.type-mapping}</rhq.ds.type-mapping>
<rhq.ds.server-name>${rhq.test.ds.server-name}</rhq.ds.server-name>
<rhq.ds.db-name>${rhq.test.ds.db-name}</rhq.ds.db-name>
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml
index 07f101d..7e189d9 100644
--- a/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml
+++ b/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml
@@ -27,6 +27,8 @@
<column name="NAME" type="VARCHAR2" required="false" size="255"/>
<column name="DISPLAY_NAME" type="VARCHAR2" required="false" size="100"/>
<column name="DESCRIPTION" type="VARCHAR2" required="false" size="1000"/>
+ <column name="MIN" type="INTEGER" required="false" />
+ <column name="MAX" type="INTEGER" required="false" />
<column name="DEFAULT_VALUE" type="VARCHAR2" required="false" size="2000"/>
<column name="REQUIRED" type="BOOLEAN" required="false"/>
<column name="READONLY" type="BOOLEAN" required="false"/>
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index 312da82..2aafb72 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -4006,6 +4006,12 @@
<schemaSpec version="2.121">
<schema-javaTask className="ContentSourceConfigurationObfuscationUpgradeTask" />
</schemaSpec>
+
+ <schemaSpec version="2.122">
+ <schema-alterColumn table="RHQ_CONFIG_PROP_DEF" column="MIN" columnType="INTEGER"/>
+ <schema-alterColumn table="RHQ_CONFIG_PROP_DEF" column="MAX" columnType="INTEGER"/>
+ </schemaSpec>
+
</dbupgrade>
</target>
</project>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
index 1b1f248..92c8df6 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
@@ -48,10 +48,8 @@ import java.lang.Integer;
public class PropertyDefinitionList extends PropertyDefinition {
private static final long serialVersionUID = 1L;
- @Transient
private int min = 0;
- @Transient
private int max = Integer.MAX_VALUE;
@JoinColumn(name = "parent_list_definition_id")
commit be31334f300fda868fddc5a88d7525e7f333828e
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri Jul 13 10:06:10 2012 -0700
[BZ 733487 - Search bar saved searches menu ignores clicks] Replace existing GWT search bar with new smartgwt search bar.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java
index 987dca6..e586406 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java
@@ -88,6 +88,16 @@ public enum IconEnum {
BUNDLE_REVERT("subsystems/bundle/BundleAction_Revert_16.png", "subsystems/bundle/BundleAction_Revert_24.png"),
/////////////////////////////
+ // Search
+ /////////////////////////////
+ STAR_OFF("search/star1.png"),
+ STAR_ACTIVE("search/star2.png"),
+ STAR_ON("search/star3.png"),
+ ARROW_WHITE("search/menu_arrow.png"),
+ ARROW_GRAY("search/menu_arrow_down.png"),
+ TRASH("search/trash.png"),
+
+ /////////////////////////////
// Administration Tab
/////////////////////////////
ADMIN("global/Admin_16.png", "global/Admin_24.png"),
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
index a89e1e2..31e58e6 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
@@ -18,15 +18,6 @@
*/
package org.rhq.enterprise.gui.coregui.client.components.carousel;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import com.google.gwt.event.dom.client.KeyCodes;
import com.smartgwt.client.data.Criteria;
import com.smartgwt.client.types.Overflow;
@@ -34,19 +25,11 @@ import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.util.BooleanCallback;
import com.smartgwt.client.util.SC;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.HTMLFlow;
-import com.smartgwt.client.widgets.IButton;
-import com.smartgwt.client.widgets.Img;
-import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.*;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.events.DoubleClickHandler;
-import com.smartgwt.client.widgets.form.fields.FormItem;
-import com.smartgwt.client.widgets.form.fields.HiddenItem;
-import com.smartgwt.client.widgets.form.fields.SelectItem;
-import com.smartgwt.client.widgets.form.fields.SpinnerItem;
-import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.form.fields.*;
import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import com.smartgwt.client.widgets.form.fields.events.KeyPressEvent;
@@ -56,20 +39,14 @@ import com.smartgwt.client.widgets.layout.LayoutSpacer;
import com.smartgwt.client.widgets.menu.IMenuButton;
import com.smartgwt.client.widgets.menu.MenuItem;
import com.smartgwt.client.widgets.menu.events.MenuItemClickEvent;
-
import org.rhq.core.domain.search.SearchSubsystem;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.RefreshableView;
import org.rhq.enterprise.gui.coregui.client.components.buttons.BackButton;
-import org.rhq.enterprise.gui.coregui.client.components.form.SearchBarItem;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableHLayout;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableIButton;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableIMenuButton;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableMenu;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableToolStrip;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
+import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedSearchBarItem;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.*;
+
+import java.util.*;
/**
* Similar to (i.e. originally a copy of) Table but instead of encapsulating a ListGrid, it manages a list of
@@ -193,8 +170,7 @@ public abstract class Carousel extends LocatableHLayout implements RefreshableVi
} else {
if (!this.hideSearchBar) {
- final SearchBarItem searchFilter = new SearchBarItem("search", MSG.common_button_search(),
- getSearchSubsystem(), getInitialSearchBarSearchText());
+ final EnhancedSearchBarItem searchFilter = new EnhancedSearchBarItem("search", getSearchSubsystem(), getInitialSearchBarSearchText());
setFilterFormItems(searchFilter);
}
}
@@ -877,7 +853,7 @@ public abstract class Carousel extends LocatableHLayout implements RefreshableVi
com.google.gwt.event.dom.client.KeyPressHandler {
private Carousel carousel;
- private SearchBarItem searchBarItem;
+ private EnhancedSearchBarItem searchBarItem;
private HiddenItem hiddenItem;
public CarouselFilter(Carousel carousel) {
@@ -898,13 +874,13 @@ public abstract class Carousel extends LocatableHLayout implements RefreshableVi
nextFormItem.addKeyPressHandler(this);
} else if (nextFormItem instanceof SelectItem) {
nextFormItem.addChangedHandler(this);
- } else if (nextFormItem instanceof SearchBarItem) {
- searchBarItem = (SearchBarItem) nextFormItem;
- searchBarItem.getSearchBar().addKeyPressHandler(this);
+ } else if (nextFormItem instanceof EnhancedSearchBarItem) {
+ //searchBarItem = (SearchBarItem) nextFormItem;
+ //searchBarItem.getSearchBar().addKeyPressHandler(this);
String name = searchBarItem.getName();
searchBarItem.setName(name + "_hidden");
hiddenItem = new HiddenItem(name);
- hiddenItem.setValue(searchBarItem.getSearchBar().getValue());
+ //hiddenItem.setValue(searchBarItem.getSearchBar().getValue());
}
}
@@ -943,7 +919,7 @@ public abstract class Carousel extends LocatableHLayout implements RefreshableVi
return;
}
// TODO: figure out why this event is being sent twice
- hiddenItem.setValue(searchBarItem.getSearchBar().getValue());
+ //hiddenItem.setValue(searchBarItem.getSearchBar().getValue());
fetchFilteredCarouselData();
}
}
@@ -1103,7 +1079,7 @@ public abstract class Carousel extends LocatableHLayout implements RefreshableVi
* Execute the action with the currently selected record(s) as the target(s).
*
* @param selection the currently selected record(s)
- * @param actionValue a value optionally supplied by the action (for example, a menuItem action's selection)
+ * @param actionValue a value optionally supplied by the action (for example, a menuItem action's selection)
*/
void executeAction(Object actionValue); //TODO add arg
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/EnhancedSearchBarItem.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/EnhancedSearchBarItem.java
new file mode 100644
index 0000000..bb0a453b
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/EnhancedSearchBarItem.java
@@ -0,0 +1,62 @@
+/*
+ * 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.gui.coregui.client.components.form;
+
+import com.smartgwt.client.types.VerticalAlignment;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.form.fields.CanvasItem;
+import org.rhq.core.domain.search.SearchSubsystem;
+import org.rhq.enterprise.gui.coregui.client.searchbar.EnhancedSearchBar;
+
+/**
+ * Wrap the SearchBar component in CanvasItem so it can be put into a DynamicForm.
+ * @author Mike Thompson
+ */
+public class EnhancedSearchBarItem extends CanvasItem {
+ private Canvas canvas = new Canvas();
+ private EnhancedSearchBar searchBar;
+
+ public EnhancedSearchBarItem(String name, SearchSubsystem subsystem, String initialSearchText) {
+ super(name, null);
+ setShowTitle(false);
+
+ searchBar = new EnhancedSearchBar(subsystem, initialSearchText);
+
+ searchBar.setHeight("30px");
+ searchBar.setWidth100();
+ canvas.addChild(searchBar);
+ canvas.setWidth100();
+
+ setCanvas(canvas);
+ setHeight(30);
+ setWidth("100%");
+ setTitleVAlign(VerticalAlignment.TOP);
+ }
+
+ @Override
+ public Canvas getCanvas() {
+ return canvas;
+ }
+
+ public EnhancedSearchBar getSearchBar() {
+ return searchBar;
+ }
+
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/ImgButtonItem.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/ImgButtonItem.java
new file mode 100644
index 0000000..48f9314
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/ImgButtonItem.java
@@ -0,0 +1,67 @@
+/*
+ * 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.gui.coregui.client.components.form;
+
+import com.smartgwt.client.types.VerticalAlignment;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.ImgButton;
+import com.smartgwt.client.widgets.form.fields.CanvasItem;
+
+/**
+ * Image Button Item is a convenience class to use ImgButton in a DynamicForm.
+ *
+ * @author Mike Thompson
+ */
+public class ImgButtonItem extends CanvasItem{
+
+ private Canvas canvas = new Canvas();
+ private ImgButton imageButton;
+
+ public ImgButtonItem(){
+ construct(null);
+ }
+
+ public ImgButtonItem(String imagePath) {
+ construct(imagePath);
+ }
+
+ private void construct(String imagePath) {
+ imageButton = new ImgButton();
+
+ if(null != imagePath){
+ imageButton.setIcon(imagePath);
+ }
+ imageButton.setHeight("30px");
+ canvas.addChild(imageButton);
+ setShowTitle(false);
+
+ setCanvas(canvas);
+ setHeight(30);
+ setTitleVAlign(VerticalAlignment.TOP);
+ }
+
+ @Override
+ public Canvas getCanvas() {
+ return canvas;
+ }
+
+ public ImgButton getImageButton() {
+ return imageButton;
+ }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/SearchBarItem.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/SearchBarItem.java
deleted file mode 100644
index a0a5689..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/SearchBarItem.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.gui.coregui.client.components.form;
-
-import com.smartgwt.client.types.VerticalAlignment;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.form.fields.CanvasItem;
-
-import org.rhq.core.domain.search.SearchSubsystem;
-import org.rhq.enterprise.gui.coregui.client.search.FlexSearchBar;
-
-/**
- * @author Joseph Marques
- */
-public class SearchBarItem extends CanvasItem {
-
- private Canvas canvas = new Canvas();
- private FlexSearchBar searchBar;
-
- public SearchBarItem(String name, String title, SearchSubsystem subsystem) {
- this(name, title, subsystem, null);
- }
-
- public SearchBarItem(String name, String title, SearchSubsystem subsystem, String initialSearchText) {
- super(name, title);
-
- searchBar = new FlexSearchBar(subsystem, initialSearchText);
-
- searchBar.setHeight("30px");
- canvas.addChild(searchBar);
-
- setCanvas(canvas);
- setHeight(30);
- setTitleVAlign(VerticalAlignment.TOP);
- }
-
- @Override
- public Canvas getCanvas() {
- return canvas;
- }
-
- public FlexSearchBar getSearchBar() {
- return searchBar;
- }
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
index 27692b8..2eea340 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
@@ -26,7 +26,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.Timer;
import com.smartgwt.client.data.Criteria;
import com.smartgwt.client.data.DSCallback;
@@ -50,6 +49,7 @@ import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.events.DoubleClickEvent;
import com.smartgwt.client.widgets.events.DoubleClickHandler;
+import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.HiddenItem;
import com.smartgwt.client.widgets.form.fields.SelectItem;
@@ -76,7 +76,7 @@ import org.rhq.enterprise.gui.coregui.client.InitializableView;
import org.rhq.enterprise.gui.coregui.client.RefreshableView;
import org.rhq.enterprise.gui.coregui.client.components.TitleBar;
import org.rhq.enterprise.gui.coregui.client.components.form.DateFilterItem;
-import org.rhq.enterprise.gui.coregui.client.components.form.SearchBarItem;
+import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedSearchBarItem;
import org.rhq.enterprise.gui.coregui.client.util.CriteriaUtility;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
@@ -286,7 +286,7 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
* </pre>
* This is called from onInit() and guarantees grid not null.
*
- * @param ListGrid grid
+ * @param grid
*/
protected void configureListGrid(ListGrid grid) {
listGrid.setWidth100();
@@ -310,8 +310,8 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
configureTableFilters();
} else {
if (!this.hideSearchBar) {
- final SearchBarItem searchFilter = new SearchBarItem("search", MSG.common_button_search(),
- getSearchSubsystem(), getInitialSearchBarSearchText());
+ final EnhancedSearchBarItem searchFilter = new EnhancedSearchBarItem("search", getSearchSubsystem(),
+ getInitialSearchBarSearchText());
setFilterFormItems(searchFilter);
}
}
@@ -771,10 +771,7 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
final ListGrid listGrid = getListGrid();
Criteria criteria = getCurrentCriteria();
- if (Log.isDebugEnabled()) {
- Log.debug(getClass().getName() + ".refresh() using criteria [" + CriteriaUtility.toString(criteria)
- + "]...");
- }
+ Log.debug(getClass().getName() + ".refresh() using criteria [" + CriteriaUtility.toString(criteria) + "]...");
listGrid.setCriteria(criteria);
if (resetPaging) {
@@ -1150,11 +1147,10 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
*
* @author Joseph Marques
*/
- private static class TableFilter extends LocatableDynamicForm implements KeyPressHandler, ChangedHandler,
- com.google.gwt.event.dom.client.KeyPressHandler {
+ private static class TableFilter extends LocatableDynamicForm implements KeyPressHandler, ChangedHandler {
private Table<?> table;
- private SearchBarItem searchBarItem;
+ private EnhancedSearchBarItem searchBarItem;
private HiddenItem hiddenItem;
public TableFilter(Table<?> table) {
@@ -1175,22 +1171,29 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
nextFormItem.addChangedHandler(this);
} else if (nextFormItem instanceof DateFilterItem) {
nextFormItem.addChangedHandler(this);
- } else if (nextFormItem instanceof SearchBarItem) {
- searchBarItem = (SearchBarItem) nextFormItem;
- searchBarItem.getSearchBar().addKeyPressHandler(this);
+ } else if (nextFormItem instanceof EnhancedSearchBarItem) {
+ searchBarItem = (EnhancedSearchBarItem) nextFormItem;
+ searchBarItem.getSearchBar().getSearchComboboxItem().addKeyPressHandler(this);
String name = searchBarItem.getName();
+ // postfix the name of the item so it is not processed by the filters and that the
+ // hidden item is used instead.
searchBarItem.setName(name + "_hidden");
hiddenItem = new HiddenItem(name);
- hiddenItem.setValue(searchBarItem.getSearchBar().getValue());
+ hiddenItem.setValue(searchBarItem.getSearchBar().getSearchComboboxItem().getValueAsString());
}
}
if (hiddenItem != null) {
+ Log.debug("Found hidden items");
+ // Add the hidden item if it exists
FormItem[] tmpItems = new FormItem[items.length + 1];
System.arraycopy(items, 0, tmpItems, 0, items.length);
tmpItems[items.length] = hiddenItem;
items = tmpItems;
}
+ for (FormItem item : items) {
+ Log.debug(" ******** Form Items sent: " + item.getName() + ": " + item.getValue());
+ }
super.setItems(items);
}
@@ -1203,7 +1206,22 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
public void onKeyPress(KeyPressEvent event) {
if (event.getKeyName().equals("Enter")) {
Log.debug("Table.TableFilter Pressed Enter key");
- fetchFilteredTableData();
+
+ if (null != searchBarItem) {
+ ComboBoxItem comboBoxItem = searchBarItem.getSearchBar().getSearchComboboxItem();
+ String searchBarValue = comboBoxItem.getValueAsString();
+ String hiddenValue = (String) hiddenItem.getValue();
+ Log.debug("Table.TableFilter searchBarValue :" + searchBarValue + ", hiddenValue" + hiddenValue);
+
+ // Only send a fetch request if the user actually changed the search expression.
+ if (!equals(searchBarValue, hiddenValue)) {
+ hiddenItem.setValue(searchBarValue);
+ Log.debug("Table.TableFilter fetchFilteredTableData");
+ fetchFilteredTableData();
+ }
+ } else {
+ fetchFilteredTableData();
+ }
}
}
@@ -1216,25 +1234,6 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
return super.getFields().length != 0;
}
- @Override
- public void onKeyPress(com.google.gwt.event.dom.client.KeyPressEvent event) {
- if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
- // TODO (ips, 10/14/11): Figure out why this event is being sent twice. However, this is not urgent,
- // since the if check below will prevent the 2nd event from triggering a redundant
- // fetch request.
- Log.debug("Table.TableFilter Pressed Enter key2");
- String searchBarValue = searchBarItem.getSearchBar().getValue();
- String hiddenValue = (String) hiddenItem.getValue();
- Log.debug("Table.TableFilter searchBarValue :" + searchBarValue + ", hiddenValue" + hiddenValue);
- // Only send a fetch request if the user actually changed the search expression.
- if (!equals(searchBarValue, hiddenValue)) {
- hiddenItem.setValue(searchBarValue);
- Log.debug("Table.TableFilter fetchFilteredTableData");
- fetchFilteredTableData();
- }
- }
- }
-
private static boolean equals(String string1, String string2) {
if (string1 == null) {
return (string2 == null);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
index 1b34b6d..b2084df 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
@@ -18,24 +18,6 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.resource;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.AVAILABILITY;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.CATEGORY;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.CTIME;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.DESCRIPTION;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.ITIME;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.KEY;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.LOCATION;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.MODIFIER;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.MTIME;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.NAME;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.PLUGIN;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.TYPE;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.VERSION;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
@@ -46,7 +28,6 @@ import com.smartgwt.client.data.fields.DataSourceIntegerField;
import com.smartgwt.client.data.fields.DataSourceTextField;
import com.smartgwt.client.rpc.RPCResponse;
import com.smartgwt.client.widgets.grid.ListGridRecord;
-
import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.resource.Resource;
@@ -59,9 +40,16 @@ import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.TypesLoadedCallback;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.*;
+
/**
* @author Greg Hinkle
*/
@@ -230,7 +218,7 @@ public class ResourceDatasource extends RPCDataSource<Resource, ResourceCriteria
protected ResourceCriteria getFetchCriteria(final DSRequest request) {
ResourceCriteria criteria = new ResourceCriteria();
- //printRequestCriteria(request);
+ printRequestCriteria(request);
criteria.addFilterId(getFilter(request, "id", Integer.class));
criteria.addFilterParentResourceId(getFilter(request, "parentId", Integer.class));
criteria.addFilterCurrentAvailability(getFilter(request, AVAILABILITY.propertyName(), AvailabilityType.class));
@@ -245,6 +233,8 @@ public class ResourceDatasource extends RPCDataSource<Resource, ResourceCriteria
criteria.addFilterTagName(getFilter(request, "tagName", String.class));
criteria.addFilterVersion(getFilter(request, "version", String.class));
criteria.addFilterParentResourceCategory(getFilter(request, FILTER_PARENT_CATEGORY, ResourceCategory.class));
+ //@todo: Remove me when finished debugging search expression
+ Log.debug(" *** ResourceCriteria Search String: " + getFilter(request, "search", String.class));
criteria.setSearchExpression(getFilter(request, "search", String.class));
return criteria;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
index 52e3c69..4e87eb0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
@@ -47,7 +47,6 @@ import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.ResourceD
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.MetadataType;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.TypeLoadedCallback;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
import org.rhq.enterprise.gui.coregui.client.util.message.MessageCenter;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableIButton;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/AbstractSearchBar.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/AbstractSearchBar.java
index 7758c4a..d26913a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/AbstractSearchBar.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/AbstractSearchBar.java
@@ -19,14 +19,13 @@
package org.rhq.enterprise.gui.coregui.client.search;
import com.google.gwt.user.client.ui.Composite;
-
import org.rhq.core.domain.search.SearchSubsystem;
/**
* Abstract class for SearchBar, so that a separate implementation can be written alongside the original.
- *
* @author Joseph Marques
*/
+@Deprecated
public abstract class AbstractSearchBar extends Composite {
public abstract SearchSubsystem getSearchSubsystem();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/FlexSearchBar.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/FlexSearchBar.java
index cb39479..4875c92 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/FlexSearchBar.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/FlexSearchBar.java
@@ -18,32 +18,11 @@
*/
package org.rhq.enterprise.gui.coregui.client.search;
-import java.util.List;
-
-import java.util.logging.Logger;
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.dom.client.MouseOutEvent;
-import com.google.gwt.event.dom.client.MouseOutHandler;
-import com.google.gwt.event.dom.client.MouseOverEvent;
-import com.google.gwt.event.dom.client.MouseOverHandler;
+import com.google.gwt.event.dom.client.*;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.Panel;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.TextBox;
-
+import com.google.gwt.user.client.ui.*;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.criteria.SavedSearchCriteria;
import org.rhq.core.domain.search.SavedSearch;
@@ -59,9 +38,12 @@ import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
+import java.util.List;
+
/**
* @author Joseph Marques
*/
+@Deprecated
public class FlexSearchBar extends AbstractSearchBar {
private static final Messages MSG = CoreGUI.getMessages();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/SearchBar.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/SearchBar.java
deleted file mode 100644
index c4dc6eb..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/SearchBar.java
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 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.gui.coregui.client.search;
-
-import java.util.List;
-
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.dom.client.MouseOutEvent;
-import com.google.gwt.event.dom.client.MouseOutHandler;
-import com.google.gwt.event.dom.client.MouseOverEvent;
-import com.google.gwt.event.dom.client.MouseOverHandler;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.TextBox;
-
-import org.rhq.core.domain.auth.Subject;
-import org.rhq.core.domain.criteria.SavedSearchCriteria;
-import org.rhq.core.domain.search.SavedSearch;
-import org.rhq.core.domain.search.SearchSubsystem;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.Messages;
-import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.search.favorites.SavedSearchGrid;
-import org.rhq.enterprise.gui.coregui.client.search.favorites.SavedSearchGrid.SavedSearchSelectionHandler;
-import org.rhq.enterprise.gui.coregui.client.search.suggest.SuggestTextBox_v3;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.message.Message;
-import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
-
-/**
- * @author Joseph Marques
- */
-public class SearchBar extends AbstractSearchBar {
-
- private static final Messages MSG = CoreGUI.getMessages();
-
- public static final String DEFAULT_PATTERN_NAME = MSG.view_searchBar_defaultPattern();
-
- private static final String IMAGE_DIR = "/coregui/images/search/";
-
- private static final String STAR_OFF_URL = IMAGE_DIR + "star1.png";
- private static final String STAR_ACTIVE_URL = IMAGE_DIR + "star2.png";
- private static final String STAR_ON_URL = IMAGE_DIR + "star3.png";
-
- private static final String ARROW_WHITE_URL = IMAGE_DIR + "menu_arrow.png";
- private static final String ARROW_GRAY_URL = IMAGE_DIR + "menu_arrow_down.png";
-
- public static final String TRASH = IMAGE_DIR + "trash.png";
-
- private final TextBox patternField = new TextBox();
- private final SuggestTextBox_v3 autoCompletePatternField = new SuggestTextBox_v3(this, patternField);
- private final TextBox patternNameField = new TextBox();
- private final Label patternNameLabel = new Label();
-
- private final Image starImage = new Image(STAR_OFF_URL);
- private final Image arrowImage = new Image(ARROW_WHITE_URL);
-
- private final PopupPanel savedSearchesPanel = new PopupPanel(true);
- private SavedSearchGrid savedSearchesGrid;
-
- private Integer currentSearchId = 0;
- private long lastNameFieldBlurTime = 0;
-
- private SearchSubsystem searchSubsystem;
- private String defaultSearchText;
- private String defaultSavedSearchPatternId;
- private String selectedTab;
-
- private Element searchButton;
-
- private AsyncCallback<Void> blackHoleCallback = new AsyncCallback<Void>() {
- @Override
- public void onFailure(Throwable caught) {
- // old search bar can't access CoreGUI.getErrorHandler(), silently ignore the error
- }
-
- @Override
- public void onSuccess(Void result) {
- // old search bar can't access CoreGUI.getMessageCenter(), silently continue with success path
- }
- };
-
- public static boolean existsOnPage() {
- return getSearchBarElement() != null;
- }
-
- private static Element getSearchBarElement() {
- return DOM.getElementById("searchBar");
- }
-
- public void loadAdditionalDataFromDivAttributes() {
- Element searchBarElement = getSearchBarElement();
-
- String searchButtonId = searchBarElement.getAttribute("searchButtonId");
- searchButton = DOM.getElementById(searchButtonId);
-
- // Don't know what this originally was going to be used for, but if you notice,
- // after all the if-stmts are evaluated true, the only piece of code to be invoked
- // (prepareSearchExecution()) has been commented out. So this is a no-op. In addition
- // the second if-stmt (getEventTarget().equals(searchButton) doesn't look correct and
- // may not ever evaluate to true anyway. Commenting this out, in case something like this
- // is needed in the future, but we'll havee to probably fix that if-stmt first.
-
- // Event.addNativePreviewHandler(new NativePreviewHandler() {
- // public void onPreviewNativeEvent(NativePreviewEvent event) {
- // if (event.getNativeEvent() != null && event.getNativeEvent().getEventTarget() != null) {
- // if (event.getNativeEvent().getEventTarget().equals(searchButton)
- // && event.getTypeInt() == Event.ONMOUSEDOWN) {
- // //prepareSearchExecution();
- // }
- // }
- // }
- // });
-
- String searchSubsystem = searchBarElement.getAttribute("searchSubsystem");
- setSearchSubsystem(SearchSubsystem.valueOf(searchSubsystem.toUpperCase()));
-
- String defaultSearchText = searchBarElement.getAttribute("defaultSearchText");
- setDefaultSearchText(defaultSearchText);
-
- String defaultSavedSearchPatternId = searchBarElement.getAttribute("defaultSavedSearchPatternId");
- setDefaultSavedSearchPatternId(defaultSavedSearchPatternId);
-
- String tab = searchBarElement.getAttribute("subtab");
- if (tab != null) {
- tab = tab.trim().toLowerCase();
- if (tab.equals("") || tab.equals("all")) {
- tab = null;
- }
- }
- this.selectedTab = tab;
- }
-
- public SearchBar() {
- Log.info("Loading SearchBar...");
-
- // in the future, will be instantiated directly from a higher-level widget
- if (existsOnPage()) {
- loadAdditionalDataFromDivAttributes();
- }
-
- RootPanel.get("patternFieldContainer").add(autoCompletePatternField);
- RootPanel.get("patternNameFieldContainer").add(patternNameField);
- RootPanel.get("patternNameLabelContainer").add(patternNameLabel);
- RootPanel.get("starImageContainer").add(starImage);
- RootPanel.get("arrowImageContainer").add(arrowImage);
- RootPanel.get("savedSearchesContainer").add(savedSearchesPanel);
-
- setupAutoCompletingPatternField();
- setupPatternNameField();
- setupPatternNameLabel();
- setupStarImage();
- setupArrowImage();
- setupSavedSearches();
-
- //
- if (defaultSearchText != null) {
- this.autoCompletePatternField.setText(defaultSearchText);
- click(searchButton); // execute the search with this default search expression
- } else if (defaultSavedSearchPatternId != null) {
- try {
- Integer savedSearchId = Integer.valueOf(defaultSavedSearchPatternId);
- activateSavedSearch(savedSearchId);
- } catch (Exception e) {
- this.autoCompletePatternField.setText(MSG
- .view_searchBar_savedSearch_failFind(defaultSavedSearchPatternId));
- click(searchButton); // execute the search, which will help to further highlight the error
- }
- }
-
- // presume the enclosing page logic loads results without a button click
- }
-
- public void setSearchSubsystem(SearchSubsystem searchSubsystem) {
- this.searchSubsystem = searchSubsystem;
- savedSearchesGrid = new SavedSearchGrid(searchSubsystem);
- }
-
- public SearchSubsystem getSearchSubsystem() {
- return searchSubsystem;
- }
-
- public void setDefaultSearchText(String defaultSearchText) {
- if (defaultSearchText == null || defaultSearchText.trim().equals("")) {
- return; // do nothing
- }
-
- this.defaultSearchText = defaultSearchText;
- }
-
- public String getDefaultSearchText() {
- return defaultSearchText;
- }
-
- public void setDefaultSavedSearchPatternId(String defaultSavedSearchPatternId) {
- if (defaultSavedSearchPatternId == null || defaultSavedSearchPatternId.trim().equals("")) {
- return; // do nothing
- }
-
- this.defaultSavedSearchPatternId = defaultSavedSearchPatternId;
- }
-
- public String getSelectedTab() {
- return selectedTab;
- }
-
- public String getDefaultSavedSearchPatternId() {
- return defaultSavedSearchPatternId;
- }
-
- private void setupAutoCompletingPatternField() {
- autoCompletePatternField.getElement().setId("patternField");
- autoCompletePatternField.setStyleName("patternField");
-
- AutoCompletePatternFieldEventHandler handler = new AutoCompletePatternFieldEventHandler();
- autoCompletePatternField.getTextBox().addFocusHandler(handler);
- autoCompletePatternField.getTextBox().addBlurHandler(handler);
- autoCompletePatternField.addKeyPressHandler(handler);
- }
-
- private void setupPatternNameField() {
- patternNameField.setStyleName("patternNameField");
- patternNameField.setVisible(false);
-
- PatternNameFieldEventHandler handler = new PatternNameFieldEventHandler();
- patternNameField.addKeyPressHandler(handler);
- patternNameField.addClickHandler(handler);
- patternNameField.addBlurHandler(handler);
- }
-
- private void setupPatternNameLabel() {
- patternNameLabel.setStyleName("patternNameLabel");
- patternNameLabel.setVisible(false);
-
- PatternNameLabelEventHandler handler = new PatternNameLabelEventHandler();
- patternNameLabel.addClickHandler(handler);
- }
-
- private void setupStarImage() {
- StarImageEventHandler handler = new StarImageEventHandler();
- starImage.addClickHandler(handler);
- starImage.addMouseOverHandler(handler);
- starImage.addMouseOutHandler(handler);
- }
-
- private void setupArrowImage() {
- ArrowImageEventHandler handler = new ArrowImageEventHandler();
- arrowImage.addClickHandler(handler);
- }
-
- private void setupSavedSearches() {
- savedSearchesPanel.add(savedSearchesGrid);
- savedSearchesPanel.setStyleName("savedSearchesPanel");
- savedSearchesGrid.addStyleName("savedSearchesPanel");
-
- // panel position will be re-calculated on down-arrow click
- savedSearchesPanel.show();
- savedSearchesPanel.hide();
-
- SavedSearchesEventHandler handler = new SavedSearchesEventHandler();
- savedSearchesPanel.addCloseHandler(handler);
- savedSearchesGrid.setSavedSearchSelectionHandler(handler);
- }
-
- private void turnNameFieldIntoLabel() {
- String name = patternNameField.getText();
-
- if (name.equalsIgnoreCase(DEFAULT_PATTERN_NAME)) {
- name = "";
- }
-
- arrowImage.setVisible(true);
- patternNameField.setVisible(false);
-
- if (name.equals("")) {
- GWTServiceLookup.getSearchService().deleteSavedSearch(currentSearchId, blackHoleCallback);
- currentSearchId = 0;
- starImage.setUrl(STAR_OFF_URL);
- } else {
- // NOTE: currently do not support updated a saved search pattern
- if (currentSearchId == 0) {
- String pattern = autoCompletePatternField.getText();
- createSavedSearch(name, pattern);
- } else {
- updateSavedSearchName(currentSearchId, name);
- }
- patternNameLabel.setText(elipse(name));
- patternNameLabel.setVisible(true);
- starImage.setUrl(STAR_ON_URL);
- }
- }
-
- private void turnNameLabelIntoField() {
- patternNameField.setText(patternNameLabel.getText());
- patternNameField.setVisible(true);
- patternNameLabel.setVisible(false);
- patternNameField.setFocus(true);
- }
-
- private String elipse(String data) {
- if (data.length() > 14) {
- return data.substring(0, 14) + "...";
- }
- return data;
- }
-
- private void createSavedSearch(final String name, final String pattern) {
- Subject subject = UserSessionManager.getSessionSubject();
- SavedSearch newSavedSearch = new SavedSearch(searchSubsystem, name, pattern, subject);
- GWTServiceLookup.getSearchService().createSavedSearch(newSavedSearch, new AsyncCallback<Integer>() {
- @Override
- public void onSuccess(Integer newSavedSearchId) {
- currentSearchId = newSavedSearchId;
- }
-
- @Override
- public void onFailure(Throwable caught) {
- }
- });
- }
-
- private void updateSavedSearchName(final int savedSearchId, final String newName) {
- GWTServiceLookup.getSearchService().updateSavedSearchName(savedSearchId, newName, new AsyncCallback<Boolean>() {
- @Override
- public void onSuccess(Boolean hadUpdates) {
- // no message bar to send update message to if hadUpdates
- }
-
- @Override
- public void onFailure(Throwable caught) {
- }
- });
- }
-
- /*
- * Event Handlers
- */
- class AutoCompletePatternFieldEventHandler implements KeyPressHandler, FocusHandler, BlurHandler {
- public void onKeyPress(KeyPressEvent event) {
- // hide pattern field/label, turn off star
- if (event.getCharCode() == KeyCodes.KEY_ENTER) {
- return;
- }
-
- patternNameLabel.setText("");
- patternNameLabel.setVisible(false);
- patternNameField.setValue("", true);
- patternNameField.setVisible(false);
- currentSearchId = 0;
- starImage.setUrl(STAR_OFF_URL);
-
- if (event.getCharCode() == KeyCodes.KEY_ESCAPE) {
- autoCompletePatternField.hideSuggestionList();
- event.preventDefault();
- event.stopPropagation();
- }
- }
-
- public void onFocus(FocusEvent event) {
- autoCompletePatternField.showSuggestionList();
- savedSearchesPanel.hide();
- }
-
- public void onBlur(BlurEvent event) {
- savedSearchesPanel.hide();
- }
- }
-
- class PatternNameFieldEventHandler implements KeyPressHandler, ClickHandler, BlurHandler {
- public void onKeyPress(KeyPressEvent event) {
- //if (event.getCharCode() == KeyCodes.KEY_ENTER) {
- if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
- Log.debug("ENTER key press on pattern name field");
- turnNameFieldIntoLabel();
- }
- }
-
- public void onClick(ClickEvent event) {
- if (patternNameField.getText().equals(DEFAULT_PATTERN_NAME)) {
- patternNameField.setValue("", false);
- }
- }
-
- public void onBlur(BlurEvent event) {
- Log.debug("onblur event on pattern name field");
- lastNameFieldBlurTime = System.currentTimeMillis();
- turnNameFieldIntoLabel();
- }
- }
-
- class PatternNameLabelEventHandler implements ClickHandler {
- public void onClick(ClickEvent event) {
- turnNameLabelIntoField();
- }
- }
-
- class StarImageEventHandler implements ClickHandler, MouseOverHandler, MouseOutHandler {
- public void onClick(ClickEvent event) {
- Log.debug("onClick for StarImage");
- lastNameFieldBlurTime = System.currentTimeMillis();
- long diff = System.currentTimeMillis() - lastNameFieldBlurTime;
- if (Math.abs(diff) < 750) {
- /*
- * This event propagation is annoying. If the threshold is set too low, then both
- * the name field blur event and this star image click event fire...but the blur
- * event fires first, which turns the star white. Then a click on a white star
- * triggers edit mode, re-enabling the name field. However, setting the threshold
- * too high will prevent the click event from being handled when the user naturally
- * wants to click on the star in rapid succession within the threshold time frame.
- * It is hoped that 750ms will strike a nice balance, and that most users will never
- * experienced any oddities from this trade-off.
- */
- return;
- }
-
- if (starImage.getUrl().endsWith(STAR_ACTIVE_URL)) {
- patternNameField.setText(DEFAULT_PATTERN_NAME);
- patternNameField.setVisible(true);
- patternNameField.selectAll();
- patternNameField.setFocus(true);
- patternNameLabel.setVisible(false);
- } else if (starImage.getUrl().endsWith(STAR_ON_URL)) {
- starImage.setUrl(STAR_ACTIVE_URL);
- patternNameField.setVisible(false);
- patternNameLabel.setVisible(false);
- GWTServiceLookup.getSearchService().deleteSavedSearch(currentSearchId, blackHoleCallback);
- }
- }
-
- public void onMouseOver(MouseOverEvent event) {
- if (starImage.getUrl().endsWith(STAR_OFF_URL)) {
- starImage.setUrl(STAR_ACTIVE_URL);
-
- }
- }
-
- public void onMouseOut(MouseOutEvent event) {
- if (starImage.getUrl().endsWith(STAR_ACTIVE_URL) && !patternNameField.isVisible()) {
- starImage.setUrl(STAR_OFF_URL);
- }
- }
- }
-
- class ArrowImageEventHandler implements ClickHandler {
- public void onClick(ClickEvent event) {
- Log.debug("onClick for ArrowImage");
- savedSearchesGrid.updateModel(new AsyncCallback<List<SavedSearch>>() {
- @Override
- public void onFailure(Throwable caught) {
- // nothing needs to be done
- }
-
- @Override
- public void onSuccess(List<SavedSearch> updatedGridData) {
- int left = autoCompletePatternField.getAbsoluteLeft();
- int top = autoCompletePatternField.getAbsoluteTop() + autoCompletePatternField.getOffsetHeight();
- savedSearchesPanel.setPopupPosition(left, top + 5);
- savedSearchesPanel.show();
- arrowImage.setUrl(ARROW_GRAY_URL);
- }
- });
- }
- }
-
- class SavedSearchesEventHandler implements CloseHandler<PopupPanel>, SavedSearchSelectionHandler {
- public void onClose(CloseEvent<PopupPanel> event) {
- arrowImage.setUrl(ARROW_WHITE_URL);
- }
-
- public void handleSelection(final int rowIndex, final int columnIndex, final SavedSearch savedSearch) {
- Log.debug("SavedSearchesEventHandler.handleSelection(" + rowIndex + "," + columnIndex + "," + savedSearch
- + ")");
- if (columnIndex == 1) {
- GWTServiceLookup.getSearchService().deleteSavedSearch(savedSearch.getId(), new AsyncCallback<Void>() {
- @Override
- public void onFailure(Throwable caught) {
- }
-
- @Override
- public void onSuccess(Void result) {
- if (currentSearchId == savedSearch.getId()) {
- currentSearchId = 0;
- patternNameField.setValue("", true);
- patternNameField.setVisible(false);
- patternNameLabel.setText("");
- patternNameLabel.setVisible(false);
- autoCompletePatternField.setFocus(true);
- starImage.setUrl(STAR_OFF_URL);
- savedSearchesPanel.hide();
- }
-
- // is user deleting the one and only element in the list?
- if (savedSearchesGrid.size() == 1) {
- savedSearchesPanel.hide();
- }
- savedSearchesGrid.removeRow(rowIndex);
- }
- });
- } else {
- activateSavedSearch(savedSearch); // activating the saved search also clicks the button
- }
- }
- }
-
- private static native void click(Element button)
- /*-{
- button.click();
- }-*/;
-
- public void activateSavedSearch(Integer savedSearchId) {
- activeSavedSearchByIdOrName(savedSearchId, null);
- }
-
- public void activateSavedSearch(String savedSearchName) {
- activeSavedSearchByIdOrName(null, savedSearchName);
- }
-
- private void activeSavedSearchByIdOrName(Integer savedSearchId, String savedSearchName) {
- Subject subject = UserSessionManager.getSessionSubject();
- SavedSearchCriteria criteria = new SavedSearchCriteria();
- criteria.addFilterSubjectId(subject.getId());
- criteria.addFilterId(savedSearchId); // null OK
- criteria.addFilterName(savedSearchName); // null OK
-
- GWTServiceLookup.getSearchService().findSavedSearchesByCriteria(criteria,
- new AsyncCallback<List<SavedSearch>>() {
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError("Failure to select saved search", caught);
- }
-
- @Override
- public void onSuccess(List<SavedSearch> results) {
- if (results.size() != 1) {
- CoreGUI.getMessageCenter().notify(new Message("Error selecting saved search", Severity.Error));
- } else {
- SavedSearch savedSearch = results.get(0);
- activateSavedSearch(savedSearch);
- }
- }
- });
- }
-
- public void activateSavedSearch(SavedSearch savedSearch) {
- currentSearchId = savedSearch.getId();
- autoCompletePatternField.setValue(savedSearch.getPattern(), true);
- patternNameField.setValue(savedSearch.getName(), true);
- Log.debug("search results change: [" + savedSearch.getName() + "," + savedSearch.getPattern() + "]");
- turnNameFieldIntoLabel();
- savedSearchesPanel.hide();
- click(searchButton);
- }
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/favorites/SavedSearchGrid.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/favorites/SavedSearchGrid.java
index 8965900..3845a27 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/favorites/SavedSearchGrid.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/favorites/SavedSearchGrid.java
@@ -18,15 +18,11 @@
*/
package org.rhq.enterprise.gui.coregui.client.search.favorites;
-import java.util.ArrayList;
-import java.util.List;
-
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Grid;
-
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.criteria.SavedSearchCriteria;
import org.rhq.core.domain.search.SavedSearch;
@@ -35,11 +31,14 @@ import org.rhq.core.domain.util.PageOrdering;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.search.SearchBar;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* @author Joseph Marques
*/
+@Deprecated
public class SavedSearchGrid extends Grid {
private SavedSearchSelectionHandler patternSelectionHandler;
@@ -130,7 +129,7 @@ public class SavedSearchGrid extends Grid {
protected void onRowOver(Element row) {
Element actionCell = DOM.getChild(row, 1);
- DOM.setStyleAttribute(actionCell, "backgroundImage", "url(" + SearchBar.TRASH + ")");
+ //DOM.setStyleAttribute(actionCell, "backgroundImage", "url(" + SearchBar.TRASH + ")");
DOM.setStyleAttribute(actionCell, "backgroundRepeat", "no-repeat");
DOM.setStyleAttribute(actionCell, "backgroundPosition", "center");
DOM.setStyleAttribute(actionCell, "width", "24px");
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/suggest/SuggestTextBox_v3.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/suggest/SuggestTextBox_v3.java
index 8030b2b..c4b91c5 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/suggest/SuggestTextBox_v3.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/suggest/SuggestTextBox_v3.java
@@ -18,47 +18,17 @@
*/
package org.rhq.enterprise.gui.coregui.client.search.suggest;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.HandlesAllKeyEvents;
-import com.google.gwt.event.dom.client.HasAllFocusHandlers;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.dom.client.KeyUpEvent;
-import com.google.gwt.event.dom.client.KeyUpHandler;
-import com.google.gwt.event.logical.shared.HasSelectionHandlers;
-import com.google.gwt.event.logical.shared.SelectionEvent;
-import com.google.gwt.event.logical.shared.SelectionHandler;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.dom.client.*;
+import com.google.gwt.event.logical.shared.*;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HasText;
-import com.google.gwt.user.client.ui.HasValue;
-import com.google.gwt.user.client.ui.MenuBar;
-import com.google.gwt.user.client.ui.MenuItem;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.SuggestOracle;
+import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.client.ui.SuggestOracle.Callback;
import com.google.gwt.user.client.ui.SuggestOracle.Request;
import com.google.gwt.user.client.ui.SuggestOracle.Response;
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.TextBoxBase;
-
import org.rhq.core.domain.search.SearchSuggestion;
import org.rhq.core.domain.search.SearchSuggestion.Kind;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
@@ -68,7 +38,14 @@ import org.rhq.enterprise.gui.coregui.client.gwt.SearchGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.search.AbstractSearchBar;
import org.rhq.enterprise.gui.coregui.client.util.Log;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+@Deprecated
public class SuggestTextBox_v3 extends Composite implements HasText, HasAllFocusHandlers, HasValue<String>,
+
HasSelectionHandlers<Suggestion> {
private static final Messages MSG = CoreGUI.getMessages();
@@ -648,6 +625,7 @@ public class SuggestTextBox_v3 extends Composite implements HasText, HasAllFocus
}
}
+ @Deprecated
class SearchSuggestOracle extends SuggestOracle {
private SearchGWTServiceAsync searchService = GWTServiceLookup.getSearchService();
@@ -738,6 +716,7 @@ public class SuggestTextBox_v3 extends Composite implements HasText, HasAllFocus
}
}
+ @Deprecated
class SearchSuggestionRequest extends SuggestOracle.Request {
private int cursorPosition;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/AbstractSearchStrategy.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/AbstractSearchStrategy.java
new file mode 100644
index 0000000..bfd0bd7
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/AbstractSearchStrategy.java
@@ -0,0 +1,91 @@
+/*
+ * 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.gui.coregui.client.searchbar;
+
+import com.smartgwt.client.widgets.form.fields.events.FocusEvent;
+import com.smartgwt.client.widgets.form.fields.events.KeyUpEvent;
+import com.smartgwt.client.widgets.grid.CellFormatter;
+import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.gwt.SearchGWTServiceAsync;
+
+
+/**
+ * AbstractSearchStrategy defines common search strategy behaviors the subclasses must implement.
+ * Also, houses common functionality such as user auth and searching the domain.
+ *
+ * @author Mike Thompson
+ */
+public abstract class AbstractSearchStrategy implements RecordClickHandler, CellFormatter
+{
+ protected static final Messages MSG = CoreGUI.getMessages();
+ public static final String ATTR_ID = "id";
+ public static final String ATTR_KIND = "kind"; // not for saved search
+ public static final String ATTR_NAME = "name";
+ public static final String ATTR_DESCRIPTION = "description";
+ public static final String ATTR_RESULT_COUNT = "resultCount";
+ public static final String ATTR_PATTERN = "pattern";
+ public static final String ATTR_VALUE = "value";
+
+ protected final SearchGWTServiceAsync searchService = GWTServiceLookup.getSearchService();
+
+ final Subject subject;
+ protected final EnhancedSearchBar searchBar;
+
+ public AbstractSearchStrategy(EnhancedSearchBar searchBar){
+ this.searchBar = searchBar;
+ subject = UserSessionManager.getSessionSubject();
+ }
+
+ /**
+ * Handle the key press event in the search bar. Must be overridden in subclass.
+ * @param keyUpEvent
+ */
+ public abstract void searchKeyUpHandler(KeyUpEvent keyUpEvent);
+
+ /**
+ * Handle the focus event in the search bar. Must be overridden in subclass.
+ * @param focusEvent
+ */
+ public abstract void searchFocusHandler(FocusEvent focusEvent);
+
+ /**
+ * Search results can have different heights (i.e. 1 row or 2 rows). Must be overridden
+ * in subclass.
+ * @return height in pixels
+ */
+ public abstract int getCellHeight();
+
+
+ /**
+ * When return key is pressed in the search bar do I want to do any further
+ * customization. Optionally, overridden by subclass.
+ * @param keyUpEvent
+ */
+ public void searchReturnKeyHandler(KeyUpEvent keyUpEvent){
+ // do nothing by default
+ }
+
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
new file mode 100644
index 0000000..cf40099
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
@@ -0,0 +1,245 @@
+/*
+ * 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.gui.coregui.client.searchbar;
+
+import java.util.List;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.data.DataSource;
+import com.smartgwt.client.data.fields.DataSourceTextField;
+import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
+import com.smartgwt.client.widgets.form.fields.events.FocusEvent;
+import com.smartgwt.client.widgets.form.fields.events.KeyUpEvent;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+
+import org.rhq.core.domain.criteria.SavedSearchCriteria;
+import org.rhq.core.domain.search.SavedSearch;
+import org.rhq.core.domain.search.SearchSubsystem;
+import org.rhq.core.domain.search.SearchSuggestion;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message;
+
+/**
+ * This is the general search strategy implementation used for most searches.
+ * These strategy classes operate by providing the standard functionality
+ * needed by searches as defined by the super class {@link AbstractSearchStrategy}
+ * This strategy works in conjunction with the {@link FavoritesSearchStrategy} for
+ * saved searches.
+ * @author Mike Thompson
+ */
+public class BasicSearchStrategy extends AbstractSearchStrategy {
+
+ private String lastExpression;
+
+ public BasicSearchStrategy(EnhancedSearchBar searchBar) {
+ super(searchBar);
+ }
+
+ @Override
+ public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
+
+ Log.debug("Using BasicSearch Formatter");
+
+ String name = record.getAttribute(ATTR_NAME);
+ String kind = record.getAttribute(ATTR_KIND);
+
+ String style = "font-variant: small-caps; font-weight: bold; font-size: 11px; float: left; margin-left: 2px; width: 50px;";
+ StringBuilder sb = new StringBuilder();
+ sb.append("<div style='height:30px;width:400px;float:left;white-space:nowrap;overflow:hidden;' >");
+ String color = (kind.equals(SearchSuggestion.Kind.GlobalSavedSearch.getDisplayName()) || kind
+ .equals(SearchSuggestion.Kind.UserSavedSearch.getDisplayName())) ? "color:green;" : "color:grey";
+ sb.append("<span style='" + style + color + "' >");
+ sb.append(kind);
+ sb.append("</span>");
+ sb.append("<span style='" + style + "' >");
+ sb.append(name);
+ sb.append("</span>");
+ sb.append("</div>");
+
+ return sb.toString();
+ }
+
+ /**
+ * Executed when this field is clicked on. Note that if {@link
+ * com.smartgwt.client.widgets.grid.ListGrid#addRecordClickHandler ListGrid.recordClick} is also defined, it will be fired
+ * for fields that define a recordClick handler if the field-level handler returns true. Call {@link com.smartgwt.client.widgets.grid.events.RecordClickEvent#cancel()} from within {@link com.smartgwt.client.widgets.grid.events.RecordClickHandler#onRecordClick} to prevent the
+ * grid-level handler from firing.
+ *
+ * @param event the event
+ */
+ @Override
+ public void onRecordClick(RecordClickEvent event) {
+ Log.debug("BasicSearchStrategy click");
+ String kind = event.getRecord().getAttribute(ATTR_KIND);
+ if (kind.equals("SAVED") || kind.equals("GLOBAL")) {
+ searchBar.switchToSavedSearchMode();
+ String savedSearchName = event.getRecord().getAttribute(ATTR_VALUE);
+ searchBar.getSaveSearchTextItem().setValue(savedSearchName);
+ assignSavedSearchExpression(savedSearchName, searchBar.getSearchComboboxItem());
+ } else {
+
+ String clickedExpression = event.getRecord().getAttribute(ATTR_NAME);
+ searchBar.getSearchComboboxItem().setValue(clickedExpression);
+ if (null != clickedExpression && clickedExpression.length() > 0) {
+ getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE, clickedExpression, clickedExpression.length());
+ }
+ }
+ }
+
+ private void assignSavedSearchExpression(final String savedSearchName, final ComboBoxItem searchComboBoxItem) {
+ SavedSearchCriteria criteria = new SavedSearchCriteria();
+ criteria.addFilterSubjectId(subject.getId());
+ criteria.addFilterName(savedSearchName); // null OK
+ criteria.setStrict(true);
+
+ GWTServiceLookup.getSearchService().findSavedSearchesByCriteria(criteria,
+ new AsyncCallback<List<SavedSearch>>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError(MSG.view_searchBar_savedSearch_failFind(savedSearchName),
+ caught);
+ }
+
+ @Override
+ public void onSuccess(List<SavedSearch> results) {
+ if (results.size() == 0) {
+ CoreGUI.getMessageCenter().notify(
+ new Message(MSG.view_searchBar_savedSearch_failFind(savedSearchName),
+ Message.Severity.Error));
+ } else {
+ SavedSearch savedSearch = results.get(0);
+ searchComboBoxItem.setValue(savedSearch.getPattern());
+ }
+ }
+ });
+
+ }
+
+ @Override
+ public void searchFocusHandler(FocusEvent event) {
+ Log.debug("focus in BasicSearchStrategy");
+ String searchExpression = searchBar.getSearchComboboxItem().getValueAsString();
+ if (null != searchExpression && searchExpression.length() > 0) {
+ getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE,
+ searchBar.getSearchComboboxItem().getValueAsString(), searchBar.getSearchComboboxItem()
+ .getValueAsString().length());
+ } else {
+ getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE, "", 0);
+ }
+ }
+
+ @Override
+ public void searchKeyUpHandler(KeyUpEvent keyUpEvent) {
+ Log.debug("Keyup in BasicSearchStrategy: " + keyUpEvent.getKeyName());
+ String searchExpression = searchBar.getSearchComboboxItem().getValueAsString();
+ if (null != searchExpression && searchExpression.length() > 0) {
+ getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE,
+ searchBar.getSearchComboboxItem().getValueAsString(), searchBar.getSearchComboboxItem()
+ .getValueAsString().length());
+ } else {
+ getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE, "", 0);
+ }
+
+ }
+
+ @Override
+ public void searchReturnKeyHandler(KeyUpEvent keyUpEvent) {
+ // Do nothing here; standard Table.TableFilter will handle normally
+ }
+
+ @Override
+ public int getCellHeight() {
+ return 25;
+ }
+
+ private void getTabAwareSearchSuggestions(SearchSubsystem searchSubsystem, final String expression,
+ int caretPosition) {
+
+ if (expression.equals(lastExpression)) {
+ Log.debug("search tab aware Suggestions: ignoring duplicate search for: " + expression);
+ return;
+ }
+ lastExpression = expression;
+
+ final long suggestStart = System.currentTimeMillis();
+
+ searchService.getTabAwareSuggestions(searchSubsystem, expression, caretPosition, null,
+ new AsyncCallback<List<SearchSuggestion>>() {
+
+ public void onSuccess(List<SearchSuggestion> results) {
+ ComboBoxItem comboBox = searchBar.getSearchComboboxItem();
+
+ // If the value has already changed assume a subsequent search is what they want
+ if (!expression.equals(comboBox.getValueAsString())) {
+ Log.debug("search tab aware Suggestions: ignoring obsolete results for: " + expression);
+ return;
+ }
+
+ DataSource ds = comboBox.getOptionDataSource();
+
+ if (null == ds) {
+ ds = new DataSource();
+ ds.setClientOnly(true);
+ DataSourceTextField idField = new DataSourceTextField(ATTR_ID, "Id");
+ idField.setPrimaryKey(true);
+ DataSourceTextField valueField = new DataSourceTextField(ATTR_VALUE, "Value");
+ DataSourceTextField kindField = new DataSourceTextField(ATTR_KIND, "Kind");
+ DataSourceTextField nameField = new DataSourceTextField(ATTR_NAME, "Name");
+ ds.setFields(idField, valueField, kindField, nameField);
+
+ comboBox.setOptionDataSource(ds);
+
+ } else {
+ ds.invalidateCache();
+ }
+
+ for (SearchSuggestion searchSuggestion : results) {
+ Log.debug("search tab aware Suggestions: " + searchSuggestion.getKind() + ", "
+ + searchSuggestion.getValue() + ", " + searchSuggestion.getLabel());
+ ListGridRecord record = new ListGridRecord();
+ record.setAttribute(ATTR_ID, searchSuggestion.getValue());
+ if (null != searchSuggestion.getKind()) {
+ record.setAttribute(ATTR_KIND, searchSuggestion.getKind().getDisplayName());
+ }
+ record.setAttribute(ATTR_NAME, searchSuggestion.getLabel());
+ record.setAttribute(ATTR_VALUE, searchSuggestion.getValue());
+ ds.addData(record);
+ }
+
+ try {
+ comboBox.fetchData();
+ } catch (Exception e) {
+ Log.debug("Caught exception on fetchData: " + e);
+ }
+
+ long suggestFetchTime = System.currentTimeMillis() - suggestStart;
+ Log.debug(results.size() + " suggestions searches fetched in: " + suggestFetchTime + "ms");
+ }
+
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError("Failed to retrieve search suggestion", caught);
+ }
+
+ });
+ }
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java
new file mode 100644
index 0000000..e793f9f
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java
@@ -0,0 +1,279 @@
+/*
+ * 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.gui.coregui.client.searchbar;
+
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.types.TextMatchStyle;
+import com.smartgwt.client.widgets.events.ClickEvent;
+import com.smartgwt.client.widgets.events.ClickHandler;
+import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.form.fields.events.FocusEvent;
+import com.smartgwt.client.widgets.form.fields.events.FocusHandler;
+import com.smartgwt.client.widgets.form.fields.events.KeyUpEvent;
+import com.smartgwt.client.widgets.form.fields.events.KeyUpHandler;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.toolbar.ToolStrip;
+import com.smartgwt.client.widgets.toolbar.ToolStripButton;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.search.SavedSearch;
+import org.rhq.core.domain.search.SearchSubsystem;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.IconEnum;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.gwt.SearchGWTServiceAsync;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message;
+
+/**
+ * The class defines the UI component of the search bar.
+ * Behavior related to the retrieving/saving of searches is delegated to the Search Strategies.
+ * The enumMaps confine us to just setting the search modes and the modes determine the strategies.
+ * This is a little safer than typical strategy pattern where we can set any strategy regardless of the
+ * search mode (in this case, the search mode and strategies can get out of sync). In fact,
+ * there is no setter for the search strategy, as you cant set it is setup by the enumMap only.
+ *
+ * @author Mike Thompson
+ */
+public class EnhancedSearchBar extends ToolStrip {
+ private static final Messages MSG = CoreGUI.getMessages();
+ private SearchSubsystem searchSubsystem;
+ private Integer currentSearchId = 0;
+ private ToolStripButton saveSearchButton;
+ private ComboBoxItem searchComboboxItem;
+ private ListGrid pickListGrid;
+ private TextItem saveSearchTextItem;
+ private final FavoritesSearchStrategy favoritesSearchStrategy;
+ private final BasicSearchStrategy basicSearchStrategy;
+
+ private final SearchGWTServiceAsync searchService = GWTServiceLookup.getSearchService();
+
+ private static final List IGNORED_KEYS;
+
+ static {
+ IGNORED_KEYS = new ArrayList(2);
+ IGNORED_KEYS.add("Arrow_Down");
+ IGNORED_KEYS.add("Arrow_Up");
+ }
+
+ enum SearchMode {
+ BASIC_SEARCH_MODE, SAVED_SEARCH_MODE
+ }
+
+ private SearchMode searchMode = SearchMode.BASIC_SEARCH_MODE;
+
+ /**
+ * The enumMap will act as a simple state machine defining the mappings of search strategy behavior and
+ * eliminating any if logic.
+ */
+ private EnumMap<SearchMode, AbstractSearchStrategy> searchStrategies = new EnumMap<SearchMode, AbstractSearchStrategy>(
+ SearchMode.class);
+
+ public EnhancedSearchBar(SearchSubsystem searchSubsystem) {
+ this(searchSubsystem, null);
+ }
+
+ public EnhancedSearchBar(SearchSubsystem searchSubsystem, String initialSearchText) {
+ if (null == searchSubsystem) {
+ this.searchSubsystem = SearchSubsystem.RESOURCE; // default to resource
+ } else {
+ this.searchSubsystem = searchSubsystem;
+ }
+ setAutoHeight();
+ setWidth100();
+ addSpacer(40);
+
+ searchComboboxItem = new ComboBoxItem("search", MSG.common_button_search());
+ // now that we have searchComboBoxItem setup dependent objects
+ favoritesSearchStrategy = new FavoritesSearchStrategy(this);
+ basicSearchStrategy = new BasicSearchStrategy(this);
+ // now we can fill our enumMap
+ searchStrategies.put(SearchMode.BASIC_SEARCH_MODE, basicSearchStrategy);
+ searchStrategies.put(SearchMode.SAVED_SEARCH_MODE, favoritesSearchStrategy);
+
+ searchComboboxItem.setWidth(670);
+ searchComboboxItem.setBrowserSpellCheck(false);
+ //we manually fetch each time we update the picklist values. That makes the delay setting meaningless.
+ searchComboboxItem.setAutoFetchData(false);
+ searchComboboxItem.setFetchDelay(300); // I'm not sure if this has an affect with no autoFetch
+
+ pickListGrid = new ListGrid();
+ configureCommonHandlers();
+
+ searchComboboxItem.setTextMatchStyle(TextMatchStyle.SUBSTRING);
+ searchComboboxItem.setShowPickListOnKeypress(true);
+ searchComboboxItem.setRedrawOnChange(true);
+ // this changes it to autocomplete field from combobox
+ searchComboboxItem.setShowPickerIcon(true);
+ searchComboboxItem.addKeyUpHandler(new KeyUpHandler() {
+ @Override
+ public void onKeyUp(KeyUpEvent keyUpEvent) {
+ Log.debug("onKeyUp search Mode: " + searchMode);
+
+ if (IGNORED_KEYS.contains(keyUpEvent.getKeyName())) {
+ return;
+ }
+
+ if (keyUpEvent.getKeyName().equals("Enter")) {
+ getSearchStrategy().searchReturnKeyHandler(keyUpEvent);
+ searchComboboxItem.focusInItem();
+ } else {
+ getSearchStrategy().searchKeyUpHandler(keyUpEvent);
+ }
+ }
+ });
+
+ searchComboboxItem.addFocusHandler(new FocusHandler() {
+ @Override
+ public void onFocus(FocusEvent event) {
+ Log.debug("onFocus search Mode: " + searchMode);
+
+ getSearchStrategy().searchFocusHandler(event);
+ }
+ });
+
+ searchComboboxItem.setPickListProperties(pickListGrid);
+ addFormItem(searchComboboxItem);
+
+ saveSearchButton = new ToolStripButton();
+ saveSearchButton.setIcon(IconEnum.STAR_OFF.getIcon16x16Path());
+ saveSearchButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ toggleFavoriteSearch();
+ }
+ });
+ addButton(saveSearchButton);
+
+ saveSearchTextItem = new TextItem("savedSearchName");
+ saveSearchTextItem.setShowTitle(false);
+ saveSearchTextItem.setWidth(150);
+ addFormItem(saveSearchTextItem);
+ saveSearchTextItem.hide();
+
+ saveSearchTextItem.addKeyUpHandler(new KeyUpHandler() {
+ @Override
+ public void onKeyUp(KeyUpEvent keyUpEvent) {
+ if (keyUpEvent.getKeyName().equals("Enter")) {
+ saveFavoriteSearch();
+ }
+ }
+ });
+
+ // set the default search provider
+ switchToBasicSearchMode();
+
+ this.draw();
+ }
+
+ private void saveFavoriteSearch() {
+ Log.debug("Saving Favorite Search: " + saveSearchTextItem.getValueAsString());
+ createSavedSearch(saveSearchTextItem.getValueAsString(), searchComboboxItem.getValueAsString());
+ toggleFavoriteSearch();
+ }
+
+ public SearchMode getSearchMode() {
+ return searchMode;
+ }
+
+ public void setSearchMode(SearchMode searchMode) {
+ this.searchMode = searchMode;
+ }
+
+ /**
+ * This is the one method where the searchMode state is allowed to change.
+ */
+ public void toggleFavoriteSearch() {
+ if (getSearchMode().equals(SearchMode.SAVED_SEARCH_MODE)) {
+ switchToBasicSearchMode();
+ } else {
+ switchToSavedSearchMode();
+ }
+
+ Log.debug("toggleFavorites searchMode set to: " + searchMode);
+ configureCommonHandlers();
+
+ }
+
+ public void switchToBasicSearchMode() {
+ setSearchMode(SearchMode.BASIC_SEARCH_MODE);
+ saveSearchButton.setIcon(IconEnum.STAR_OFF.getIcon16x16Path());
+ saveSearchTextItem.hide();
+ configureCommonHandlers();
+ }
+
+ public void switchToSavedSearchMode() {
+ setSearchMode(SearchMode.SAVED_SEARCH_MODE);
+ saveSearchButton.setIcon(IconEnum.STAR_ON.getIcon16x16Path());
+ saveSearchTextItem.show();
+ saveSearchTextItem.setValue(MSG.search_name_your_search());
+ saveSearchTextItem.setSelectOnFocus(true);
+ saveSearchTextItem.selectValue();
+ configureCommonHandlers();
+ }
+
+ private void configureCommonHandlers() {
+ pickListGrid.setCellHeight(getSearchStrategy().getCellHeight());
+ pickListGrid.addRecordClickHandler(getSearchStrategy());
+ pickListGrid.setCellFormatter(getSearchStrategy());
+ pickListGrid.redraw();
+ }
+
+ public String getValue() {
+ return searchComboboxItem.getValueAsString();
+ }
+
+ private void createSavedSearch(final String name, final String pattern) {
+ Subject subject = UserSessionManager.getSessionSubject();
+ SavedSearch newSavedSearch = new SavedSearch(searchSubsystem, name, pattern, subject);
+ searchService.createSavedSearch(newSavedSearch, new AsyncCallback<Integer>() {
+ @Override
+ public void onSuccess(Integer newSavedSearchId) {
+ currentSearchId = newSavedSearchId;
+ Message message = new Message("Successfully Saved Search: " + name, Message.Severity.Info);
+ CoreGUI.getMessageCenter().notify(message);
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ Message message = new Message("Failure to Save Search " + name, Message.Severity.Error);
+ CoreGUI.getMessageCenter().notify(message);
+ }
+ });
+ }
+
+ public AbstractSearchStrategy getSearchStrategy() {
+ return searchStrategies.get(searchMode);
+ }
+
+ public ComboBoxItem getSearchComboboxItem() {
+ return searchComboboxItem;
+ }
+
+ public TextItem getSaveSearchTextItem() {
+ return saveSearchTextItem;
+ }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java
new file mode 100644
index 0000000..a04a000
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java
@@ -0,0 +1,156 @@
+/*
+ * 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.gui.coregui.client.searchbar;
+
+import java.util.List;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.data.DataSource;
+import com.smartgwt.client.data.fields.DataSourceIntegerField;
+import com.smartgwt.client.data.fields.DataSourceTextField;
+import com.smartgwt.client.widgets.form.fields.events.FocusEvent;
+import com.smartgwt.client.widgets.form.fields.events.KeyUpEvent;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.criteria.SavedSearchCriteria;
+import org.rhq.core.domain.search.SavedSearch;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+
+/**
+ * Search Strategy for the Favorite Saved Searches.
+ * If you wish to save your searches for later use this search strategy
+ * will facilitate favorite searches.
+ *
+ * @author Mike Thompson
+ */
+public class FavoritesSearchStrategy extends AbstractSearchStrategy {
+
+ public FavoritesSearchStrategy(EnhancedSearchBar searchBar){
+ super(searchBar);
+ }
+
+ @Override
+ public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
+
+ Log.debug("Using Favorites Formatter");
+
+ String name = record.getAttribute(ATTR_NAME);
+ Integer resultCount = record.getAttributeAsInt(ATTR_RESULT_COUNT);
+ String pattern = record.getAttribute(ATTR_PATTERN);
+
+ String resultAsString = (resultCount != null) ? "("+String.valueOf(resultCount)+")" : "";
+ final String styleStr = "font-family:arial;font-size:11px;white-space:nowrap;overflow:hidden;";
+ String formatString = "<table>" +
+ "<tr><td ><span style='" + styleStr + "width:170px;color:green;float:left'>" + name + "</span></td>" +
+ "<td align='right'><span style='" + styleStr + "width:50px;float:right;font-weight:bold'>" + resultAsString+ "</span></td></tr>" +
+ "<tr><td colSpan=2><span style='" + styleStr + "width:220px;float:left'>" + pattern + "</span></td></tr></table>";
+
+ return formatString;
+ }
+
+
+ /**
+ * Executed when this field is clicked on. Note that if {@link
+ * com.smartgwt.client.widgets.grid.ListGrid#addRecordClickHandler ListGrid.recordClick} is also defined, it will be fired
+ * for fields that define a recordClick handler if the field-level handler returns true. Call {@link com.smartgwt.client.widgets.grid.events.RecordClickEvent#cancel()} from within {@link com.smartgwt.client.widgets.grid.events.RecordClickHandler#onRecordClick} to prevent the
+ * grid-level handler from firing.
+ *
+ * @param event the event
+ */
+ @Override
+ public void onRecordClick(RecordClickEvent event) {
+ // do nothing here; just here if we need to do something
+ searchBar.getSaveSearchTextItem().setValue(event.getRecord().getAttribute(ATTR_NAME));
+ searchBar.getSearchComboboxItem().setValue(event.getRecord().getAttribute(ATTR_PATTERN));
+
+ }
+
+ @Override
+ public void searchKeyUpHandler(KeyUpEvent keyUpEvent) {
+ populateSearchComboboxSavedSearchesWithAutoComplete();
+ }
+
+
+ @Override
+ public void searchFocusHandler(FocusEvent focusEvent) {
+ // nothing currently
+ }
+
+ private void populateSearchComboboxSavedSearchesWithAutoComplete(){
+
+ SavedSearchCriteria savedSearchCriteria = new SavedSearchCriteria();
+ Subject subject = UserSessionManager.getSessionSubject();
+ savedSearchCriteria.addFilterSubjectId(subject.getId());
+ savedSearchCriteria.setStrict(true);
+ final long start = System.currentTimeMillis();
+
+ searchService.findSavedSearchesByCriteria(savedSearchCriteria, new AsyncCallback<List<SavedSearch>>() {
+
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError(MSG.search_failed_to_retrieve_saved_search(), caught);
+ }
+
+ public void onSuccess(List<SavedSearch> result) {
+ long fetchTime = System.currentTimeMillis() - start;
+ Log.debug(result.size() + " saved searches fetched in: " + fetchTime + "ms");
+
+ DataSource dataSource = new DataSource();
+ dataSource.setClientOnly(true);
+ DataSourceTextField valueField = new DataSourceTextField(ATTR_ID, "Id");
+ valueField.setPrimaryKey(true);
+ DataSourceTextField kindField = new DataSourceTextField(ATTR_KIND, "Kind");
+ DataSourceTextField nameField = new DataSourceTextField(ATTR_NAME, "Name");
+ DataSourceTextField patternField = new DataSourceTextField(ATTR_PATTERN, "Pattern");
+ DataSourceTextField descriptionField = new DataSourceTextField(ATTR_DESCRIPTION, "Description");
+ DataSourceIntegerField recordCount = new DataSourceIntegerField(ATTR_RESULT_COUNT, "Result Count");
+ dataSource.setFields(valueField, kindField,nameField,patternField,descriptionField,recordCount);
+
+ for (SavedSearch savedSearch : result) {
+ Log.debug("savedSearch: " + savedSearch.getName());
+ ListGridRecord record = new ListGridRecord();
+ record.setAttribute(ATTR_ID, savedSearch.getId());
+ record.setAttribute(ATTR_KIND, "Saved");
+ record.setAttribute(ATTR_NAME, savedSearch.getName());
+ record.setAttribute(ATTR_DESCRIPTION, savedSearch.getDescription());
+ record.setAttribute(ATTR_PATTERN, savedSearch.getPattern());
+ if (savedSearch.getResultCount() != null)
+ record.setAttribute(ATTR_RESULT_COUNT, savedSearch.getResultCount());
+ dataSource.addData(record);
+ }
+
+ searchBar.getSearchComboboxItem().setOptionDataSource(dataSource);
+ }
+ });
+ }
+
+ @Override
+ public int getCellHeight() {
+ return 35;
+ }
+
+ @Override
+ public void searchReturnKeyHandler(KeyUpEvent keyUpEvent) {
+ // do nothing
+ Log.debug("return key in SavedSearchProvider");
+ }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java
index b7944a4..4a1a06f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java
@@ -19,7 +19,6 @@
package org.rhq.enterprise.gui.coregui.client.util;
import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.user.client.Window;
import com.smartgwt.client.data.*;
import com.smartgwt.client.data.fields.DataSourceIntegerField;
import com.smartgwt.client.data.fields.DataSourceTextField;
@@ -595,7 +594,7 @@ public abstract class RPCDataSource<T, C extends BaseCriteria> extends DataSourc
Map<String, Object> criteriaMap = criteria.getValues();
for (Map.Entry<String, Object> nextEntry : criteriaMap.entrySet()) {
- Window.alert(nextEntry.getKey() + ":" + nextEntry.getValue());
+ Log.debug("Request Criteria: "+nextEntry.getKey() + ":" + nextEntry.getValue());
}
}
@@ -628,9 +627,9 @@ public abstract class RPCDataSource<T, C extends BaseCriteria> extends DataSourc
}
}
- if (Log.isDebugEnabled() && result != null) {
+ //if (Log.isDebugEnabled() && result != null) {
Log.debug("Filter: " + paramName + "=[" + result + "]");
- }
+ //}
return result;
}
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 56766cd..2e371d9 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -413,6 +413,8 @@ filter_from_date = From
filter_to_date = To
group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+search_name_your_search = name you search
util_ancestry_parentAncestry = Parent Ancestry for:
util_errorHandler_nullException = exception was null
util_monitoringRequestCallback_error_checkServerStatusFailure = Unable to determine login status - check Server status.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index f7d4ef7..275fe4d 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -432,6 +432,8 @@ filter_from_date = Od
filter_to_date = Do
group_tree_groupOfResourceType = Skupina: [{0}]
group_tree_partialClusterTooltip = {0} z {1} Älenů skupiny má "{2}" zdroj
+##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_name_your_search = name you search
util_ancestry_parentAncestry = Původ rodiÄe pro:
util_errorHandler_nullException = vÃœjimka byla null
util_monitoringRequestCallback_error_checkServerStatusFailure = NepodaÅilo se urÄit stav pÅihlaÅ¡ovánà - zkontrolujte stav serveru.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index a40cb2f..ddd07fd 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -397,6 +397,8 @@ filter_from_date = Von
filter_to_date = Bis
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} der {1} Gruppenmitglieder haben eine ''{2}'' Ressource
+##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_name_your_search = name you search
util_disambiguationReportDecorator_pluginSuffix = ({0} Plugin)
util_errorHandler_nullException = Exception war null
##util_monitoringRequestCallback_error_checkServerStatusFailure = Unable to determine login status - check Server status.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index e135c0d..6eb5212 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -410,6 +410,8 @@ filter_from_date = éå§
filter_to_date = çµäº
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {1} ã®äžã® {0} ã°ã«ãŒãã¡ã³ããŒã ''{2}'' ãªãœãŒã¹ãæã£ãŠããŸã
+##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_name_your_search = name you search
util_ancestry_parentAncestry = 芪ã®å
ç¥ :
util_disambiguationReportDecorator_pluginSuffix = ({0} ãã©ã°ã€ã³)
util_errorHandler_nullException = äŸå€ã¯ null ã§ãã
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 843d5d2..900b847 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -416,6 +416,8 @@ favorites_resources = Recursos Favoritos
##filter_to_date = To
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_name_your_search = name you search
util_ancestry_parentAncestry = Ancestral para:
util_errorHandler_nullException = Exce\u00E7\u00E3o nula
util_monitoringRequestCallback_error_checkServerStatusFailure = Imposs\u00EDvel verificar o status do login - verifique o status do Servidor.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 512e087..43abe46 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -403,6 +403,8 @@
#filter_from_date = From
#filter_to_date = To
#group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_name_your_search = name you search
#util_ancestry_parentAncestry = Parent Ancestry for:
#util_errorHandler_nullException = exception was null
#util_monitoringRequestCallback_error_checkServerStatusFailure = Unable to determine login status - check Server status.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 269ed1c..9f3fd76 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -405,6 +405,8 @@ favorites_resources = \u8d44\u6e90\u6536\u85cf\u5939
##filter_to_date = To
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = \u9664\u53bb {1},{0}\u7684\u7ec4\u6210\u5458\u62e5\u6709 \u4e00\u4e2a''{2}''\u8d44\u6e90
+##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_name_your_search = name you search
util_ancestry_parentAncestry = Parent Ancestry for:
util_errorHandler_nullException = \u5f02\u5e38\u662f null
util_monitoringRequestCallback_error_checkServerStatusFailure = \u65e0\u6cd5\u786e\u5b9a\u767b\u5f55\u72b6\u6001- \u68c0\u67e5\u670d\u52a1\u5668\u72b6\u6001.
commit 39e949017892c6845a026c8f86d6618796108b87
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Mon Jul 16 15:44:28 2012 -0400
[BZ 840512] workaround bug in persistence container.
diff --git a/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java b/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java
index 2758e2b..4b3516a 100644
--- a/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java
+++ b/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java
@@ -38,6 +38,7 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.util.obfuscation.Obfuscator;
import org.rhq.enterprise.server.plugin.pc.content.ContentProvider;
import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails;
import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
@@ -220,6 +221,16 @@ public class JBossSoftwareContentSourceAdapter implements ContentProvider, Packa
int status = client.executeMethod(method);
+ //BZ840512: check for issue deobfuscating the password:
+ if (status == 401 || status == 403) {
+ password = Obfuscator.decode(password);//in case de/unobfuscation failed.
+ UsernamePasswordCredentials upc = new UsernamePasswordCredentials(username, password);
+ client.getState().setCredentials("users", method.getHostConfiguration().getHost(), upc);
+ log.warn("You have either input bad Content Source credentials or"
+ + " there is a problem retrieving obfuscated passwords. Retrying...");
+ status = client.executeMethod(method);
+ }
+
//Check to see if redirection has occurred
String currentUrl = method.getURI().getURI();
//if redirection has occurred, reconnect with correct address.
commit b98e5f305e20dfc04baa38036c6b4e1e377052f8
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Jul 16 16:09:28 2012 -0400
[Bug 839256 - FailoverListManagerBeanTest fail on OpenJDK 1.7]
Tweak algorithm for better distribution and also relax test verification to
allow for minor imbalance at deeper levels of failover.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/FailoverListManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/FailoverListManagerBean.java
index f38d1ae..97ba097 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/FailoverListManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/FailoverListManagerBean.java
@@ -44,8 +44,8 @@ import org.rhq.core.domain.cloud.PartitionEvent;
import org.rhq.core.domain.cloud.PartitionEventDetails;
import org.rhq.core.domain.cloud.Server;
import org.rhq.core.domain.cloud.composite.FailoverListComposite;
-import org.rhq.core.domain.cloud.composite.FailoverListDetailsComposite;
import org.rhq.core.domain.cloud.composite.FailoverListComposite.ServerEntry;
+import org.rhq.core.domain.cloud.composite.FailoverListDetailsComposite;
import org.rhq.core.domain.resource.Agent;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.core.AgentManagerLocal;
@@ -210,27 +210,27 @@ public class FailoverListManagerBean implements FailoverListManagerLocal {
agentServerListMap.put(next, new ArrayList<ServerBucket>(servers.size()));
}
- // assign server lists level by level: primary, then secondary, the tertiary, etc
+ // assign server lists level by level: primary, then secondary, then tertiary, etc
for (int level = 0; (level < servers.size()); ++level) {
// Initialize the bucket loads for the next round
initBuckets(buckets, existingLoads, level);
- // assign a server for this level to each agent, balancing as we go
- for (Agent next : agents) {
+ // assign a server for this level to each agent, balancing as we go
+ // keep track of the how many agents have been assignd on this pass
+ int agentsAssigned = 0;
+ // introduce more list disparity by changing the bucket iteration direction on each level
+ int rotate = (((level % 2) == 0) ? -1 : 1);
+
+ for (Agent next : agents) {
List<ServerBucket> serverList = agentServerListMap.get(next);
// When assigning primary (i.e. level 0), supply the current primary as the preferred server.
- // This should reduce connection churn by letting most agents stay put (but affects balancing, we'll deal with
- // that below)
+ // This should reduce connection churn by letting most agents stay put (but affects balancing, we'll
+ // deal with that below)
ServerBucket bestBucket = null;
- // Rotate the list (makes the last entry the first entry) on each iteration. This
- // enhances bucket distribution amongst the levels and ensures that we don't starve
- // buckets at the end of the list.
- Collections.rotate(buckets, 1);
-
if ((0 == level) && (null != next.getServer())) {
bestBucket = ServerBucket.getBestBucket(buckets, serverList, next.getAffinityGroup(), next
.getServer().getName());
@@ -238,6 +238,18 @@ public class FailoverListManagerBean implements FailoverListManagerLocal {
bestBucket = ServerBucket.getBestBucket(buckets, serverList, next.getAffinityGroup(), null);
}
+ // Rotate the list on each iteration. This enhances bucket distribution amongst the levels and ensures
+ // that we don't starve buckets at the end of the list. Also, we alternate the rotation direction on
+ // each level which seems to help.
+ Collections.rotate(buckets, rotate);
+
+ // Reverse the buckets completely each time we have assigned an agent to each server. This avoids
+ // duplicating failover lists completely by not repeating the same server sequence over and over on the
+ // same level.
+ if ((++agentsAssigned % buckets.size() == 0)) {
+ Collections.reverse(buckets);
+ }
+
if (null == bestBucket) {
// this should never happen but let's defensively check and log
log.error("Unexpected Condition! null bucket in getForAllAgents()");
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/ServerBucket.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/ServerBucket.java
index 931c1d0..b98aaf0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/ServerBucket.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/ServerBucket.java
@@ -43,6 +43,11 @@ public class ServerBucket {
assignedAgents = new ArrayList<Agent>();
}
+ @Override
+ public String toString() {
+ return serverEntry.toString();
+ }
+
static ServerBucket getBestBucket(List<ServerBucket> buckets, List<ServerBucket> usedBuckets,
AffinityGroup affinityGroup, String preferredServerName) {
ServerBucket result = null;
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java
index 29e9e58..1c59b16 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java
@@ -225,11 +225,15 @@ public class FailoverListManagerBeanTest extends AbstractEJB3Test {
validateBasic(result, numServers, numAgents);
// validate balance level by level
- for (int i = 0; (i < numServers); ++i) {
+ 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);
- FailoverListComposite.ServerEntry server = flc.get(i);
+ // 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);
}
@@ -237,8 +241,16 @@ public class FailoverListManagerBeanTest extends AbstractEJB3Test {
double div = (double) numAgents / (double) numServers;
int ceil = (int) Math.ceil(div);
int floor = (int) Math.floor(div);
- assert agentsOnServer <= ceil;
- assert agentsOnServer >= floor;
+ // 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 through tertiary levels that's pretty good.
+ if (level > 3) {
+ ++ceil;
+ --floor;
+ }
+ assert agentsOnServer <= ceil : "AgentsOnServer [" + agentsOnServer + "] > ceiling [" + ceil
+ + "] (level " + level + ")";
+ assert agentsOnServer >= floor : "AgentsOnServer [" + agentsOnServer + "] < floor [" + floor
+ + "] (level " + level + ")";
}
}
@@ -261,7 +273,8 @@ public class FailoverListManagerBeanTest extends AbstractEJB3Test {
Integer agentId = Integer.valueOf(agent.getAddress());
Integer serverId = Integer.valueOf(server.address);
if ((level < numAffinityServers) && (agentId < numAffinityAgents))
- assert (serverId < numAffinityServers);
+ assert (serverId < numAffinityServers) : "serverId [" + serverId + "] >= numAffinityServers ["
+ + numAffinityServers + "]";
Integer count = distributionMap.get(serverId);
distributionMap.put(serverId, (null == count) ? 1 : ++count);
}
@@ -275,8 +288,8 @@ public class FailoverListManagerBeanTest extends AbstractEJB3Test {
}
int ceil = (int) Math.ceil(div);
int floor = (int) Math.floor(div);
- assert agentsOnServer <= ceil;
- assert agentsOnServer >= floor;
+ assert agentsOnServer <= ceil : "AgentsOnServer [" + agentsOnServer + "] > ceiling [" + ceil + "]";
+ assert agentsOnServer >= floor : "AgentsOnServer [" + agentsOnServer + "] < floor [" + floor + "]";
}
}
}
@@ -585,5 +598,4 @@ public class FailoverListManagerBeanTest extends AbstractEJB3Test {
assert serverLists.get(0).equals(serverLists.get(2));
assert serverLists.get(1).equals(serverLists.get(2));
}
-
}
\ No newline at end of file
commit 06f1af5e7ec0dbdc2dcfbd4dc1fd40b5831ac89e
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Mon Jul 16 21:01:24 2012 +0200
[BZ 839720] tests
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementDataManagerTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementDataManagerTest.java
index 424145a..a6abea9 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementDataManagerTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementDataManagerTest.java
@@ -18,10 +18,19 @@
*/
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;
@@ -30,10 +39,14 @@ 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.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;
@@ -46,11 +59,13 @@ 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;
@@ -68,10 +83,12 @@ public class MeasurementDataManagerTest extends AbstractEJB3Test {
private Subject overlord;
private Resource resource1, resource2;
- private MeasurementDefinition definitionCt1;
- private MeasurementDefinition definitionCt2;
+ 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;
@BeforeMethod
public void beforeMethod() {
@@ -79,6 +96,7 @@ public class MeasurementDataManagerTest extends AbstractEJB3Test {
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)!
@@ -95,6 +113,7 @@ public class MeasurementDataManagerTest extends AbstractEJB3Test {
callTimeDataManager.purgeCallTimeData(new Date());
EntityManager em = beginTx();
+
// delete keys
List<Integer> resourceIds = new ArrayList<Integer>();
resourceIds.add(resource1.getId());
@@ -119,10 +138,20 @@ public class MeasurementDataManagerTest extends AbstractEJB3Test {
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);
@@ -141,16 +170,6 @@ public class MeasurementDataManagerTest extends AbstractEJB3Test {
setupResources(em);
- MeasurementSchedule schedule1 = new MeasurementSchedule(definitionCt1, resource1);
- em.persist(schedule1);
- definitionCt1.addSchedule(schedule1);
- resource1.addSchedule(schedule1);
-
- MeasurementSchedule schedule2 = new MeasurementSchedule(definitionCt1, resource2);
- em.persist(schedule2);
- definitionCt1.addSchedule(schedule2);
- resource2.addSchedule(schedule2);
-
em.flush();
long now = System.currentTimeMillis();
@@ -200,16 +219,6 @@ public class MeasurementDataManagerTest extends AbstractEJB3Test {
setupResources(em);
- MeasurementSchedule schedule1 = new MeasurementSchedule(definitionCt1, resource1);
- em.persist(schedule1);
- definitionCt1.addSchedule(schedule1);
- resource1.addSchedule(schedule1);
-
- MeasurementSchedule schedule2 = new MeasurementSchedule(definitionCt2, resource1);
- em.persist(schedule2);
- definitionCt1.addSchedule(schedule2);
- resource2.addSchedule(schedule2);
-
em.flush();
long now = System.currentTimeMillis();
@@ -282,6 +291,195 @@ public class MeasurementDataManagerTest extends AbstractEJB3Test {
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;
+ String name1 = "a";
+ String name2 = "b";
+ String name3 = "c";
+ String value1 = "test-value1";
+ String value2 = "test-value2";
+ String value3 = "test-value3";
+
+ // 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);
+
+ 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);
+
+ // 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
+ }
+ }
+
+ 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 {
commit 2d6b3d400552fb087acb21feb856f082f446ae5e
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Mon Jul 16 12:08:58 2012 +0200
[BZ 808175] typo
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
index a285a7f..1878a8f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
@@ -181,7 +181,7 @@ public interface MeasurementDataManagerLocal {
*
* @return MeasurementData for this Schedule
*/
- Set<MeasurementData> findLiveDataForGroup(Subject subject, int groupId, int[] resourceId, int[] definitionIds);
+ Set<MeasurementData> findLiveDataForGroup(Subject subject, int groupId, int[] resourceIds, int[] definitionIds);
/**
* Returns a list of numeric data point lists for the given compatible group - one per specified measurement
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java
index d3163ec..b452adf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java
@@ -76,7 +76,7 @@ public interface MeasurementDataManagerRemote {
Set<MeasurementData> findLiveDataForGroup(//
@WebParam(name = "subject") Subject subject, //
@WebParam(name = "groupId") int groupId,//
- @WebParam(name = "resourceId") int[] resourceId, //
+ @WebParam(name = "resourceId") int[] resourceIds, //
@WebParam(name = "definitionIds") int[] definitionIds);
@WebMethod
commit edb9cf72684d5f5cccc9cf5c0c0f068f17042ea3
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri Jul 13 14:49:53 2012 -0400
Add some null/empty string protection, even though the string really should
never be empty.
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java
index df8ac21..4476173 100644
--- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java
@@ -290,12 +290,21 @@ public class ServerStartScriptDiscoveryUtility {
}
int startScriptIndex;
- // Advance past any shell (e.g. /bin/sh or cmd.exe) options.
+ // Advance past any shell (e.g. /bin/sh or cmd.exe) options or empty args
for (startScriptIndex = 1; (startScriptIndex < serverParentProcessCommandLine.length); ++startScriptIndex) {
- if (serverParentProcessCommandLine[startScriptIndex].charAt(0) != OPTION_PREFIX) {
+ // the arg should not be null or empty, but we've seen empty args from Sigar...
+ String arg = serverParentProcessCommandLine[startScriptIndex];
+
+ if (arg != null && !arg.isEmpty() && arg.charAt(0) != OPTION_PREFIX) {
break;
}
}
+
+ // for whatever unanticipated reason, we advanced past all of the args
+ if (startScriptIndex == serverParentProcessCommandLine.length) {
+ return null;
+ }
+
String possibleStartScript = serverParentProcessCommandLine[startScriptIndex];
return (isScript(possibleStartScript)) ? startScriptIndex : null;
}
commit 6e4d8cd596e81674ec3eacc625be9f3eb3d04f2a
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Fri Jul 13 16:56:55 2012 +0200
Making the package scanning of the python language support configurable
through additional RHQ-specific system variables.
Update the RHQ server startup scripts to configure the python's package
scanning so that it properly discovers domain jar and its packages and
classes. This is then used to pre-import domain classes into the script
context for the alert scripts.
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
index e868204..3a030f4 100644
--- a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
@@ -51,8 +51,8 @@ public class PythonScriptEngineInitializer implements ScriptEngineInitializer {
static {
Properties props = new Properties();
- props.put("python.packages.paths", "java.class.path,sun.boot.class.path");
- props.put("python.packages.directories", "java.ext.dirs");
+ props.put("python.packages.paths", "rhq.python.additional.classpath,java.class.path,sun.boot.class.path");
+ props.put("python.packages.directories", "rhq.python.additional.package.dirs,java.ext.dirs");
props.put("python.cachedir.skip", false);
PythonInterpreter.initialize(System.getProperties(), props, null);
}
diff --git a/modules/enterprise/server/container/src/main/bin-resources/bin/rhq-server.sh b/modules/enterprise/server/container/src/main/bin-resources/bin/rhq-server.sh
index 1a38161..f481201 100644
--- a/modules/enterprise/server/container/src/main/bin-resources/bin/rhq-server.sh
+++ b/modules/enterprise/server/container/src/main/bin-resources/bin/rhq-server.sh
@@ -284,6 +284,12 @@ if $JAVA -version 2>&1 | grep "IBM J9" >/dev/null 2>&1; then
fi
fi
+#-----------------------------------------------------------------------
+# Setup the Python package scanning in case we have Python scripting available
+#-----------------------------------------------------------------------
+JYTHON_CACHE_DIR="$RHQ_SERVER_HOME/jbossas/server/default/data/jython.cachedir"
+PYTHON_ADDITIONAL_CLASSPATH="$RHQ_SERVER_HOME/jbossas/server/default/deploy/rhq.ear/rhq-core-domain-ejb3.jar/./"
+
# ----------------------------------------------------------------------
# Prepare the VM command line options to be passed in
# ----------------------------------------------------------------------
@@ -293,7 +299,7 @@ if [ -z "$RHQ_SERVER_JAVA_OPTS" ]; then
fi
# Add the JVM opts that we always want to specify, whether or not the user set RHQ_SERVER_JAVA_OPTS.
# Note that the double equals for the policy file specification IS INTENTIONAL
-RHQ_SERVER_JAVA_OPTS="-Dapp.name=rhq-server $RHQ_SERVER_JAVA_OPTS -Djava.awt.headless=true -Djboss.platform.mbeanserver -Dsun.lang.ClassLoader.allowArraySyntax=true -Djava.util.logging.config.file=$RHQ_SERVER_HOME/jbossas/server/default/conf/logging.properties -Djava.security.manager -Djava.security.policy==$RHQ_SERVER_HOME/bin/rhq-server.security-policy"
+RHQ_SERVER_JAVA_OPTS="-Dapp.name=rhq-server $RHQ_SERVER_JAVA_OPTS -Djava.awt.headless=true -Djboss.platform.mbeanserver -Dsun.lang.ClassLoader.allowArraySyntax=true -Djava.util.logging.config.file=$RHQ_SERVER_HOME/jbossas/server/default/conf/logging.properties -Djava.security.manager -Djava.security.policy==$RHQ_SERVER_HOME/bin/rhq-server.security-policy -Dpython.cachedir=$JYTHON_CACHE_DIR -Drhq.python.additional.classpath=$PYTHON_ADDITIONAL_CLASSPATH"
debug_msg "RHQ_SERVER_JAVA_OPTS: $RHQ_SERVER_JAVA_OPTS"
debug_msg "RHQ_SERVER_ADDITIONAL_JAVA_OPTS: $RHQ_SERVER_ADDITIONAL_JAVA_OPTS"
diff --git a/modules/enterprise/server/container/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf b/modules/enterprise/server/container/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
index b4f178b..cf30c5a 100644
--- a/modules/enterprise/server/container/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
+++ b/modules/enterprise/server/container/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
@@ -71,6 +71,9 @@ wrapper.java.additional.11=-Dsun.lang.ClassLoader.allowArraySyntax=true
wrapper.java.additional.12=-Djava.security.manager
# the double equals for the policy file specification IS INTENTIONAL
wrapper.java.additional.13="-Djava.security.policy==%RHQ_SERVER_HOME%/bin/rhq-server.security-policy"
+#Setup up a cache dir for jython in case python script support was available in the server
+wrapper.java.additional.14="-Dpython.cachedir=%RHQ_SERVER_HOME%/jbossas/server/default/data/jython.cachedir"
+wrapper.java.additional.15="-Drhq.python.additional.classpath=%RHQ_SERVER_HOME%/jbossas/server/default/deploy/rhq.ear/rhq-core-domain-ejb3.jar/./"
# We want to make sure the Server starts in the JBossAS bin directory
wrapper.working.dir=%RHQ_SERVER_HOME%/jbossas/bin
commit 33db4718581ca09afc259a8e73310ce65a573025
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Fri Jul 13 16:54:14 2012 +0200
[BZ 839780] - The scriptengine providers now can tell the file extension of
the scripts they support. The alert-cli plugin then picks the correct
script engine implementation for a script based on its file name extension.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
index 9887958..6bba114 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
@@ -114,6 +114,25 @@ public class ScriptEngineFactory {
return new HashSet<String>(KNOWN_PROVIDERS.keySet());
}
+ public static String getLanguageByScriptFileExtension(String fileExtension) {
+ for (ScriptEngineProvider p : KNOWN_PROVIDERS.values()) {
+ if (fileExtension.equals(p.getScriptFileExtension())) {
+ return p.getSupportedLanguage();
+ }
+ }
+
+ return null;
+ }
+
+ public static String getFileExtensionForLanguage(String language) {
+ ScriptEngineProvider provider = KNOWN_PROVIDERS.get(language);
+ if (provider == null) {
+ return null;
+ }
+
+ return provider.getScriptFileExtension();
+ }
+
/**
* Initializes the script engine for given language.
*
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
index 067ed90..f5b619e 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
@@ -47,6 +47,12 @@ public interface ScriptEngineProvider {
String getSupportedLanguage();
/**
+ * @return the file extension of files written in the language supported by this provider.
+ * The returned string is the extension without the leading dot.
+ */
+ String getScriptFileExtension();
+
+ /**
* @return an implementation of {@link ScriptEngineInitializer} that can instantiate
* and initialize a script engine for the supported language for use with RHQ.
*/
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
index 02d54eb..63c5023 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
@@ -36,6 +36,11 @@ public class JsEngineProvider implements ScriptEngineProvider {
}
@Override
+ public String getScriptFileExtension() {
+ return "js";
+ }
+
+ @Override
public ScriptEngineInitializer getInitializer() {
return new JsEngineInitializer();
}
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java
index c0bfcac..2d71f85 100644
--- a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java
@@ -36,6 +36,11 @@ public class PythonScriptEngineProvider implements ScriptEngineProvider {
}
@Override
+ public String getScriptFileExtension() {
+ return "py";
+ }
+
+ @Override
public ScriptEngineInitializer getInitializer() {
return new PythonScriptEngineInitializer();
}
diff --git a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
index 0bca2fa..5eb9360 100644
--- a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
+++ b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
@@ -30,8 +30,11 @@ import java.io.PipedOutputStream;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.util.ArrayDeque;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Queue;
import javax.script.ScriptEngine;
@@ -71,8 +74,6 @@ import org.rhq.scripting.ScriptSourceProviderFactory;
*/
public class CliSender extends AlertSender<CliComponent> {
- private static final String ENGINE_NAME = "javascript";
-
private static final int MAX_RESULT_SIZE = 4000;
public static final String PROP_PACKAGE_ID = "packageId";
@@ -91,7 +92,7 @@ public class CliSender extends AlertSender<CliComponent> {
//no more than 10 concurrently running CLI notifications..
//is that enough?
private static final int MAX_SCRIPT_ENGINES = 10;
- private static Queue<ScriptEngine> SCRIPT_ENGINES = new ArrayDeque<ScriptEngine>(MAX_SCRIPT_ENGINES);
+ private static Map<String, Queue<ScriptEngine>> SCRIPT_ENGINES = new HashMap<String, Queue<ScriptEngine>>();
private static int ENGINES_IN_USE = 0;
/**
@@ -108,12 +109,18 @@ public class CliSender extends AlertSender<CliComponent> {
public Throwable throwable;
}
+ private static class BitsAndFileExtension {
+ InputStream packageBits;
+ String scriptFileExtension;
+ }
+
public SenderResult send(Alert alert) {
SenderResult result = new SenderResult();
BufferedReader reader = null;
ScriptEngine engine = null;
Subject subjectWithSession = null;
final SessionManager sessionManager = SessionManager.getInstance();
+ String language = null;
try {
final Config config = getConfig();
@@ -127,9 +134,25 @@ public class CliSender extends AlertSender<CliComponent> {
ByteArrayOutputStream scriptOutputStream = new ByteArrayOutputStream();
PrintWriter scriptOut = new PrintWriter(scriptOutputStream);
- engine = getScriptEngine(alert, scriptOut, config);
+ BitsAndFileExtension packageData = getPackageBits(config.packageId, config.repoId);
+
+ InputStream packageBits = packageData.packageBits;
+ String scriptFileExtension = packageData.scriptFileExtension;
+ language = ScriptEngineFactory.getLanguageByScriptFileExtension(scriptFileExtension);
+
+ if (language == null) {
+ ArrayList<String> supportedExtensions = new ArrayList<String>();
+ for (String lang : ScriptEngineFactory.getSupportedLanguages()) {
+ supportedExtensions.add(ScriptEngineFactory.getFileExtensionForLanguage(lang));
+ }
+
+ throw new IllegalArgumentException(
+ "Could not determine the script engine to use based on the script file extension '"
+ + scriptFileExtension + "'. Only the following extensions are currently supported: "
+ + supportedExtensions);
+ }
- InputStream packageBits = getPackageBits(config.packageId, config.repoId);
+ engine = getScriptEngine(alert, scriptOut, config, language);
reader = new BufferedReader(new InputStreamReader(packageBits));
@@ -166,7 +189,7 @@ public class CliSender extends AlertSender<CliComponent> {
exceptionHolder.scriptException);
//make things pretty for the UI
- ScriptEngineInitializer initializer = ScriptEngineFactory.getInitializer(ENGINE_NAME);
+ ScriptEngineInitializer initializer = ScriptEngineFactory.getInitializer(language);
String message = initializer.extractUserFriendlyErrorMessage(exceptionHolder.scriptException);
int col = exceptionHolder.scriptException.getColumnNumber();
int line = exceptionHolder.scriptException.getLineNumber();
@@ -203,7 +226,7 @@ public class CliSender extends AlertSender<CliComponent> {
sessionManager.invalidate(subjectWithSession.getSessionId());
}
if (engine != null) {
- returnEngine(engine);
+ returnEngine(engine, language);
}
if (reader != null) {
@@ -264,7 +287,8 @@ public class CliSender extends AlertSender<CliComponent> {
return results;
}
- private static ScriptEngine getScriptEngine(Alert alert, PrintWriter output, Config config) throws ScriptException,
+ private static ScriptEngine getScriptEngine(Alert alert, PrintWriter output, Config config, String language)
+ throws ScriptException,
IOException, InterruptedException {
Subject user = config.subject;
@@ -273,14 +297,14 @@ public class CliSender extends AlertSender<CliComponent> {
StandardBindings bindings = new StandardBindings(output, client);
bindings.put("alert", alert);
- ScriptEngine engine = takeEngine(bindings);
+ ScriptEngine engine = takeEngine(bindings, language);
engine.getContext().setWriter(output);
engine.getContext().setErrorWriter(output);
return engine;
}
- private static InputStream getPackageBits(int packageId, int repoId) throws IOException {
+ private static BitsAndFileExtension getPackageBits(int packageId, int repoId) throws IOException {
final ContentSourceManagerLocal csm = LookupUtil.getContentSourceManager();
RepoManagerLocal rm = LookupUtil.getRepoManagerLocal();
final PackageVersion versionToUse = rm.getLatestPackageVersion(LookupUtil.getSubjectManager().getOverlord(),
@@ -293,8 +317,8 @@ public class CliSender extends AlertSender<CliComponent> {
+ " either doesn't exist at all or doesn't have any version. Can't execute a CLI script without a script to run.");
}
- PipedInputStream ret = new PipedInputStream();
- final PipedOutputStream out = new PipedOutputStream(ret);
+ PipedInputStream bits = new PipedInputStream();
+ final PipedOutputStream out = new PipedOutputStream(bits);
Thread reader = new Thread(new Runnable() {
public void run() {
@@ -320,6 +344,20 @@ public class CliSender extends AlertSender<CliComponent> {
reader.setDaemon(true);
reader.start();
+ BitsAndFileExtension ret = new BitsAndFileExtension();
+ ret.packageBits = bits;
+ String fileName = versionToUse.getFileName();
+ String extension = "";
+
+ if (fileName != null) {
+ int dotIdx = fileName.lastIndexOf('.');
+ if (dotIdx >= 0) {
+ extension = fileName.substring(dotIdx + 1);
+ }
+ }
+
+ ret.scriptFileExtension = extension;
+
return ret;
}
@@ -417,17 +455,24 @@ public class CliSender extends AlertSender<CliComponent> {
}
}
- private static ScriptEngine takeEngine(StandardBindings bindings) throws InterruptedException, ScriptException,
+ private static ScriptEngine takeEngine(StandardBindings bindings, String language) throws InterruptedException,
+ ScriptException,
IOException {
synchronized (SCRIPT_ENGINES) {
if (ENGINES_IN_USE >= MAX_SCRIPT_ENGINES) {
SCRIPT_ENGINES.wait();
}
- ScriptEngine engine = SCRIPT_ENGINES.poll();
+ Queue<ScriptEngine> q = SCRIPT_ENGINES.get(language);
+ if (q == null) {
+ q = new ArrayDeque<ScriptEngine>();
+ SCRIPT_ENGINES.put(language, q);
+ }
+
+ ScriptEngine engine = q.poll();
if (engine == null) {
- engine = ScriptEngineFactory.getSecuredScriptEngine(ENGINE_NAME,
+ engine = ScriptEngineFactory.getSecuredScriptEngine(language,
new PackageFinder(Collections.<File> emptyList()), bindings, new StandardScriptPermissions());
}
//TODO is this OK, or should we use a different classloader than the context classloader?
@@ -440,9 +485,16 @@ public class CliSender extends AlertSender<CliComponent> {
}
}
- private static void returnEngine(ScriptEngine engine) {
+ private static void returnEngine(ScriptEngine engine, String language) {
synchronized (SCRIPT_ENGINES) {
- SCRIPT_ENGINES.offer(engine);
+ Queue<ScriptEngine> q = SCRIPT_ENGINES.get(language);
+ if (q == null) {
+ //hmm... this is very strange and should not happen, because we should have initied the queue in the
+ //takeEngine() method...
+ q = new ArrayDeque<ScriptEngine>();
+ SCRIPT_ENGINES.put(language, q);
+ }
+ q.offer(engine);
--ENGINES_IN_USE;
SCRIPT_ENGINES.notify();
}
commit 5f0388a7ba23c1f395892950c322e3d649840d2f
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Fri Jul 13 13:10:34 2012 +0200
[BZ 839720 - The alert notifications dialog initially shows wrong UI] This was caused by commit 1c7723b
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewNotificationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewNotificationEditor.java
index 9cf0850..c66b207 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewNotificationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewNotificationEditor.java
@@ -118,6 +118,7 @@ public class NewNotificationEditor extends LocatableDynamicForm {
notificationSenderSelectItem.setDisabled(false);
notificationSenderSelectItem.redraw();
+ notificationSenderSelectItem.setValue(result[0]);
switchToAlertSender(result[0]);
senderCanvasItem.show();
} else {
commit f5bbb1ef7b8b7ae50086dac59ab36b61aeceb762
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Fri Jul 13 11:29:40 2012 +0200
Fixing the dev profile of the lang support modules to copy the final
repackaged jars to the dev-container.
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index 06bed89..38ead44 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -86,7 +86,7 @@
<execution>
<id>deploy</id>
- <phase>compile</phase>
+ <phase>install</phase>
<configuration>
<tasks>
<mkdir dir="${rhq.deploymentDir}" />
@@ -94,8 +94,7 @@
location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
<echo>*** Updating
${deployment.file}...</echo>
- <jar destfile="${deployment.file}"
- basedir="${project.build.outputDirectory}" />
+ <copy tofile="${deployment.file}" file="${project.build.directory}/${project.build.finalName}.jar" />
</tasks>
</configuration>
<goals>
diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
index b657dd2..39d3895 100644
--- a/modules/enterprise/scripting/python/pom.xml
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -85,14 +85,14 @@
<execution>
<id>deploy</id>
- <phase>compile</phase>
+ <phase>install</phase>
<configuration>
<tasks>
<mkdir dir="${rhq.deploymentDir}" />
<property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
<echo>*** Updating
${deployment.file}...</echo>
- <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
+ <copy tofile="${deployment.file}" file="${project.build.directory}/${project.build.finalName}.jar" />
</tasks>
</configuration>
<goals>
commit 97c9424489cbb8cf65f44d83c06015ed4b0b7c32
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu Jul 12 15:49:38 2012 -0700
HotFix: The min/max fields on PropertyDefinitionList broke some other plugins. I didn't see this until I created new schema. This is a temp fix until real fix.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
index 92c8df6..1b1f248 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
@@ -48,8 +48,10 @@ import java.lang.Integer;
public class PropertyDefinitionList extends PropertyDefinition {
private static final long serialVersionUID = 1L;
+ @Transient
private int min = 0;
+ @Transient
private int max = Integer.MAX_VALUE;
@JoinColumn(name = "parent_list_definition_id")
commit c80c45065a6e0f1977e0c04fae5a8f05593ecd40
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu Jul 12 14:14:36 2012 -0700
For Test page move save button to bottom of screen for consistency.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
index 9d2d1a2..52e3c69 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
@@ -80,13 +80,11 @@ public class ResourceConfigurationEditView extends LocatableVLayout implements P
protected void onDraw() {
super.onDraw();
- //createButtonBar();
-
refresh();
if (!this.resourcePermission.isConfigureWrite()) {
- Message message = new Message(MSG.view_configurationDetails_noPermission(), Message.Severity.Info, EnumSet
- .of(Message.Option.Transient, Message.Option.Sticky));
+ Message message = new Message(MSG.view_configurationDetails_noPermission(), Message.Severity.Info,
+ EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
CoreGUI.getMessageCenter().notify(message);
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
index 31d17a3..b0d9154 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
@@ -51,6 +51,7 @@ public class TestConfigurationView
private ConfigurationEditor editor;
private LocatableIButton saveButton;
+ private LocatableToolStrip buttonBar;
private ConfigurationDefinition configurationDefinition;
private Configuration configuration;
@@ -67,7 +68,16 @@ public class TestConfigurationView
public void build() {
setWidth100();
setHeight100();
-
+
+ buttonBar = createButtonBar();
+
+ this.configurationDefinition = TestConfigurationFactory.createConfigurationDefinition();
+ this.configuration = TestConfigurationFactory.createConfiguration();
+
+ reloadConfiguration();
+ }
+
+ private LocatableToolStrip createButtonBar() {
LocatableToolStrip toolStrip = new LocatableToolStrip(extendLocatorId("ToolStrip"));
toolStrip.setWidth100();
@@ -81,13 +91,8 @@ public class TestConfigurationView
});
this.saveButton.disable();
toolStrip.addMember(this.saveButton);
-
- addMember(toolStrip);
-
- this.configurationDefinition = TestConfigurationFactory.createConfigurationDefinition();
- this.configuration = TestConfigurationFactory.createConfiguration();
-
- reloadConfiguration();
+ toolStrip.addSpacer(40);
+ return toolStrip;
}
@Override
@@ -120,10 +125,13 @@ public class TestConfigurationView
if (editor != null) {
editor.destroy();
removeMember(editor);
+ buttonBar.destroy();
+ removeMember(buttonBar);
}
editor = createConfigurationEditor();
addMember(editor);
+ addMember(createButtonBar());
markForRedraw();
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java
index d2d9c94..054af8e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java
@@ -53,6 +53,7 @@ public class TestGroupConfigurationView
private ConfigurationEditor editor;
private LocatableIButton saveButton;
+ private ToolStrip buttonBar;
private ConfigurationDefinition configurationDefinition;
private List<GroupMemberConfiguration> memberConfigurations;
@@ -67,22 +68,6 @@ public class TestGroupConfigurationView
setWidth100();
setHeight100();
- ToolStrip toolStrip = new ToolStrip();
- toolStrip.setWidth100();
-
- toolStrip.addMember(new LayoutSpacer());
-
- this.saveButton = new LocatableIButton(this.extendLocatorId("Save"), "Save");
- this.saveButton.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent clickEvent) {
- save();
- }
- });
- this.saveButton.disable();
- toolStrip.addMember(this.saveButton);
-
- addMember(toolStrip);
-
this.configurationDefinition = TestConfigurationFactory.createConfigurationDefinition();
this.memberConfigurations = new ArrayList<GroupMemberConfiguration>(GROUP_SIZE);
for (int i = 0; i < GROUP_SIZE; i++) {
@@ -91,10 +76,26 @@ public class TestGroupConfigurationView
configuration);
this.memberConfigurations.add(memberConfiguration);
}
-
reloadConfiguration();
}
+ private ToolStrip createButtonBar() {
+ buttonBar = new ToolStrip();
+ buttonBar.setWidth100();
+ buttonBar.addMember(new LayoutSpacer());
+
+ this.saveButton = new LocatableIButton(this.extendLocatorId("Save"), "Save");
+ this.saveButton.addClickHandler(new ClickHandler() {
+ public void onClick(ClickEvent clickEvent) {
+ save();
+ }
+ });
+ this.saveButton.disable();
+ buttonBar.addMember(this.saveButton);
+ buttonBar.addSpacer(40);
+ return buttonBar;
+ }
+
@Override
public void propertyValueChanged(PropertyValueChangeEvent event) {
MessageCenter messageCenter = CoreGUI.getMessageCenter();
@@ -120,14 +121,17 @@ public class TestGroupConfigurationView
}
private void reloadConfiguration() {
- this.saveButton.disable();
if (editor != null) {
editor.destroy();
removeMember(editor);
+ buttonBar.destroy();
+ removeMember(buttonBar);
}
editor = createConfigurationEditor();
addMember(editor);
+ addMember(createButtonBar());
+ markForRedraw();
}
protected GroupConfigurationEditor createConfigurationEditor() {
commit 336ce7c5c794775f7517fbc3a0770ffa2d3e7974
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu Jul 12 13:02:59 2012 -0700
[BZ 815305] Min/max constraints on plugin PropertyList not honored in UI.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
index 4c85a62..92c8df6 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
@@ -33,6 +33,8 @@ import javax.xml.bind.annotation.XmlSeeAlso;
import org.jetbrains.annotations.NotNull;
+import java.lang.Integer;
+
/**
* The definition of a list of properties where each member of the list has the same definition. The definition of the
* entries may be null in the case of arbitrary lists.
@@ -46,17 +48,9 @@ import org.jetbrains.annotations.NotNull;
public class PropertyDefinitionList extends PropertyDefinition {
private static final long serialVersionUID = 1L;
- /**
- * See JBNADM-1595
- */
- @Transient
- private int min;
+ private int min = 0;
- /**
- * See JBNADM-1595
- */
- @Transient
- private int max;
+ private int max = Integer.MAX_VALUE;
@JoinColumn(name = "parent_list_definition_id")
@OneToOne(cascade = CascadeType.ALL)
@@ -99,4 +93,4 @@ public class PropertyDefinitionList extends PropertyDefinition {
public void setMin(int min) {
this.min = min;
}
-}
\ No newline at end of file
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
index 48df2d6..aec7274 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
@@ -293,78 +293,86 @@ public class ConfigurationEditor extends LocatableVLayout {
if (configurationDefinition == null || configuration == null) {
if (configType == ConfigType.resource) {
- configurationService.getResourceConfiguration(resourceId, new AsyncCallback<Configuration>() {
- public void onFailure(Throwable caught) {
- showError(caught);
- if (loadHandler != null) {
- loadHandler.loadedConfiguration(null);
- }
- }
+ loadResourceConfiguration(start);
- public void onSuccess(Configuration result) {
- configuration = result;
- Log.info("Config retrieved in: " + (System.currentTimeMillis() - start));
- reload();
- if (loadHandler != null) {
- loadHandler.loadedConfiguration(configuration);
- }
- }
- });
+ } else if (configType == ConfigType.plugin) {
+ loadPluginConfiguration(start);
+ }
+ }
- ResourceTypeRepository.Cache.getInstance().getResourceTypes(new Integer[] { resourceTypeId },
- EnumSet.of(ResourceTypeRepository.MetadataType.resourceConfigurationDefinition),
- new ResourceTypeRepository.TypesLoadedCallback() {
- public void onTypesLoaded(Map<Integer, ResourceType> types) {
- Log.debug("ConfigDef retrieved in: " + (System.currentTimeMillis() - start));
- configurationDefinition = types.get(resourceTypeId).getResourceConfigurationDefinition();
- if (configurationDefinition == null) {
- loadingLabel.hide();
- showError(MSG.view_configEdit_error_1());
- }
- reload();
- if (loadHandler != null) {
- loadHandler.loadedConfigurationDefinition(configurationDefinition);
- }
- }
- });
+ reload();
+ }
- } else if (configType == ConfigType.plugin) {
- configurationService.getPluginConfiguration(resourceId, new AsyncCallback<Configuration>() {
- public void onFailure(Throwable caught) {
- showError(caught);
- if (loadHandler != null) {
- loadHandler.loadedConfiguration(null);
- }
- }
+ private void loadPluginConfiguration(final long start) {
+ configurationService.getPluginConfiguration(resourceId, new AsyncCallback<Configuration>() {
+ public void onFailure(Throwable caught) {
+ showError(caught);
+ if (loadHandler != null) {
+ loadHandler.loadedConfiguration(null);
+ }
+ }
- public void onSuccess(Configuration result) {
- configuration = result;
- reload();
- if (loadHandler != null) {
- loadHandler.loadedConfiguration(configuration);
- }
+ public void onSuccess(Configuration result) {
+ configuration = result;
+ reload();
+ if (loadHandler != null) {
+ loadHandler.loadedConfiguration(configuration);
+ }
+ }
+ });
+
+ ResourceTypeRepository.Cache.getInstance().getResourceTypes(new Integer[] { resourceTypeId },
+ EnumSet.of(ResourceTypeRepository.MetadataType.pluginConfigurationDefinition),
+ new ResourceTypeRepository.TypesLoadedCallback() {
+ public void onTypesLoaded(Map<Integer, ResourceType> types) {
+ Log.debug("ConfigDef retrieved in: " + (System.currentTimeMillis() - start));
+ configurationDefinition = types.get(resourceTypeId).getPluginConfigurationDefinition();
+ if (configurationDefinition == null) {
+ showError(MSG.view_configEdit_error_2());
}
- });
+ reload();
+ if (loadHandler != null) {
+ loadHandler.loadedConfigurationDefinition(configurationDefinition);
+ }
+ }
+ });
+ }
- ResourceTypeRepository.Cache.getInstance().getResourceTypes(new Integer[] { resourceTypeId },
- EnumSet.of(ResourceTypeRepository.MetadataType.pluginConfigurationDefinition),
- new ResourceTypeRepository.TypesLoadedCallback() {
- public void onTypesLoaded(Map<Integer, ResourceType> types) {
- Log.debug("ConfigDef retrieved in: " + (System.currentTimeMillis() - start));
- configurationDefinition = types.get(resourceTypeId).getPluginConfigurationDefinition();
- if (configurationDefinition == null) {
- showError(MSG.view_configEdit_error_2());
- }
- reload();
- if (loadHandler != null) {
- loadHandler.loadedConfigurationDefinition(configurationDefinition);
- }
- }
- });
+ private void loadResourceConfiguration(final long start) {
+ configurationService.getResourceConfiguration(resourceId, new AsyncCallback<Configuration>() {
+ public void onFailure(Throwable caught) {
+ showError(caught);
+ if (loadHandler != null) {
+ loadHandler.loadedConfiguration(null);
+ }
}
- }
- reload();
+ public void onSuccess(Configuration result) {
+ configuration = result;
+ Log.info("Config retrieved in: " + (System.currentTimeMillis() - start));
+ reload();
+ if (loadHandler != null) {
+ loadHandler.loadedConfiguration(configuration);
+ }
+ }
+ });
+
+ ResourceTypeRepository.Cache.getInstance().getResourceTypes(new Integer[] { resourceTypeId },
+ EnumSet.of(ResourceTypeRepository.MetadataType.resourceConfigurationDefinition),
+ new ResourceTypeRepository.TypesLoadedCallback() {
+ public void onTypesLoaded(Map<Integer, ResourceType> types) {
+ Log.debug("ConfigDef retrieved in: " + (System.currentTimeMillis() - start));
+ configurationDefinition = types.get(resourceTypeId).getResourceConfigurationDefinition();
+ if (configurationDefinition == null) {
+ loadingLabel.hide();
+ showError(MSG.view_configEdit_error_1());
+ }
+ reload();
+ if (loadHandler != null) {
+ loadHandler.loadedConfigurationDefinition(configurationDefinition);
+ }
+ }
+ });
}
public void reload() {
@@ -389,7 +397,7 @@ public class ConfigurationEditor extends LocatableVLayout {
if (configurationDefinition.getConfigurationFormat() == ConfigurationFormat.STRUCTURED
|| configurationDefinition.getConfigurationFormat() == ConfigurationFormat.STRUCTURED_AND_RAW) {
- Log.info("Building structured configuration editor...");
+ Log.debug("Building structured configuration editor...");
LocatableVLayout structuredConfigLayout = buildStructuredPane();
addMember(structuredConfigLayout);
} else {
@@ -561,31 +569,18 @@ public class ConfigurationEditor extends LocatableVLayout {
}
private void addHeaderItems(List<FormItem> fields) {
- final String CELL_STYLE = "configurationEditorHeaderCell";
-
- StaticTextItem nameHeader = new StaticTextItem();
- nameHeader.setValue(MSG.view_configEdit_property());
- nameHeader.setShowTitle(false);
- nameHeader.setCellStyle(CELL_STYLE);
- fields.add(nameHeader);
+ fields.add(createHeaderTextItem(MSG.view_configEdit_property()));
+ fields.add(createHeaderTextItem(MSG.view_configEdit_unset()));
+ fields.add(createHeaderTextItem(MSG.common_title_value()));
+ fields.add(createHeaderTextItem(MSG.common_title_description()));
+ }
+ private StaticTextItem createHeaderTextItem(String value){
StaticTextItem unsetHeader = new StaticTextItem();
- unsetHeader.setValue(MSG.view_configEdit_unset());
+ unsetHeader.setValue(value);
unsetHeader.setShowTitle(false);
- unsetHeader.setCellStyle(CELL_STYLE);
- fields.add(unsetHeader);
-
- StaticTextItem valueHeader = new StaticTextItem();
- valueHeader.setValue(MSG.common_title_value());
- valueHeader.setShowTitle(false);
- valueHeader.setCellStyle(CELL_STYLE);
- fields.add(valueHeader);
-
- StaticTextItem descriptionHeader = new StaticTextItem();
- descriptionHeader.setValue(MSG.common_title_description());
- descriptionHeader.setShowTitle(false);
- descriptionHeader.setCellStyle(CELL_STYLE);
- fields.add(descriptionHeader);
+ unsetHeader.setCellStyle("configurationEditorHeaderCell");
+ return unsetHeader;
}
private void addItemsForPropertiesRecursively(String locatorId, Collection<PropertyDefinition> propertyDefinitions,
@@ -618,6 +613,7 @@ public class ConfigurationEditor extends LocatableVLayout {
fieldsForThisProperty = buildFieldsForPropertySimple(propertyDefinition, propertyDefinitionSimple,
propertySimple);
} else if (propertyDefinition instanceof PropertyDefinitionList) {
+ ///@TODO
PropertyDefinitionList propertyDefinitionList = (PropertyDefinitionList) propertyDefinition;
PropertyDefinition memberDefinition = propertyDefinitionList.getMemberDefinition();
PropertyList propertyList = (PropertyList) property;
@@ -688,7 +684,6 @@ public class ConfigurationEditor extends LocatableVLayout {
} else if (memberDefinition instanceof PropertyDefinitionSimple) {
SpacerItem spacerItem = new SpacerItem();
fields.add(spacerItem);
-
CanvasItem listOfSimplesItem = buildListOfSimplesField(locatorId, propertyDefinitionList, propertyList);
fields.add(listOfSimplesItem);
@@ -1005,12 +1000,16 @@ public class ConfigurationEditor extends LocatableVLayout {
SC.confirm(MSG.view_configEdit_confirm_2(), new BooleanCallback() {
public void execute(Boolean confirmed) {
if (confirmed) {
- PropertyMapListGridRecord recordToBeDeleted = (PropertyMapListGridRecord) recordClickEvent
- .getRecord();
- propertyList.getList().remove(recordToBeDeleted.getIndex());
- ListGridRecord[] rows = buildSummaryRecords(propertyList, propertyDefinitions);
- summaryTable.setData(rows);
- firePropertyChangedEvent(propertyList, propertyDefinitionList, true);
+ if( summaryTable.getRecordList().getLength() <= propertyDefinitionList.getMin()){
+ SC.say(MSG.view_configEdit_minBoundsExceeded(String.valueOf(propertyDefinitionList.getMin())));
+ }else {
+ PropertyMapListGridRecord recordToBeDeleted = (PropertyMapListGridRecord) recordClickEvent
+ .getRecord();
+ propertyList.getList().remove(recordToBeDeleted.getIndex());
+ ListGridRecord[] rows = buildSummaryRecords(propertyList, propertyDefinitions);
+ summaryTable.setData(rows);
+ firePropertyChangedEvent(propertyList, propertyDefinitionList, true);
+ }
}
}
});
@@ -1109,7 +1108,6 @@ public class ConfigurationEditor extends LocatableVLayout {
final DynamicForm listGrid = new DynamicForm();
vLayout.addMember(listGrid);
- // TODO (ips, 03/14/11): Make this a ListGrid, rather than a SelectItem.
final SelectItem membersItem = new SelectItem(propertyList.getName());
membersItem.setShowTitle(false);
membersItem.setMultiple(true);
@@ -1138,28 +1136,32 @@ public class ConfigurationEditor extends LocatableVLayout {
final String noun = (selectedValues.length == 1) ? MSG.common_label_item() : MSG
.common_label_items();
String message = MSG.view_configEdit_confirm_3(Integer.toString(selectedValues.length), noun);
- SC.ask(message, new BooleanCallback() {
- public void execute(Boolean confirmed) {
- if (confirmed) {
- for (int i = selectedValues.length - 1; i >= 0; i--) {
- String selectedValue = selectedValues[i];
- int index = Integer.valueOf(selectedValue);
- propertyList.getList().remove(index);
-
- // Rebuild the select item options.
- LinkedHashMap<String, String> memberValueToIndexMap = buildValueMap(propertyList);
- membersItem.setValueMap(memberValueToIndexMap);
-
- deleteButton.disable();
-
- firePropertyChangedEvent(propertyList, propertyDefinitionList, true);
- CoreGUI.getMessageCenter().notify(
- new Message(MSG.view_configEdit_msg_3(Integer.toString(selectedValues.length),
- noun), EnumSet.of(Message.Option.Transient)));
+ if(propertyList.getList().size() <= propertyDefinitionList.getMin()){
+ SC.say("You cannot delete this entry because the minimum size bounds has been met: "+ propertyDefinitionList.getMin());
+ }else {
+ SC.ask(message, new BooleanCallback() {
+ public void execute(Boolean confirmed) {
+ if (confirmed) {
+ for (int i = selectedValues.length - 1; i >= 0; i--) {
+ String selectedValue = selectedValues[i];
+ int index = Integer.valueOf(selectedValue);
+ propertyList.getList().remove(index);
+
+ // Rebuild the select item options.
+ LinkedHashMap<String, String> memberValueToIndexMap = buildValueMap(propertyList);
+ membersItem.setValueMap(memberValueToIndexMap);
+
+ deleteButton.disable();
+
+ firePropertyChangedEvent(propertyList, propertyDefinitionList, true);
+ CoreGUI.getMessageCenter().notify(
+ new Message(MSG.view_configEdit_msg_3(Integer.toString(selectedValues.length),
+ noun), EnumSet.of(Message.Option.Transient)));
+ }
}
}
- }
- });
+ });
+ }
}
});
footer.addMember(deleteButton);
@@ -1178,93 +1180,92 @@ public class ConfigurationEditor extends LocatableVLayout {
newButton.setTooltip(MSG.view_configEdit_tooltip_2());
newButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
public void onClick(ClickEvent clickEvent) {
- final Window popup = new Window();
- popup.setTitle(MSG.view_configEdit_addItem());
- popup.setWidth(300);
- popup.setHeight(145);
- popup.setIsModal(true);
- popup.setShowModalMask(true);
- popup.setShowCloseButton(false);
- popup.centerInPage();
-
- VLayout vLayout = new VLayout();
- vLayout.setMargin(10);
-
- HTMLFlow description = new HTMLFlow(propertyDefinitionList.getDescription());
- vLayout.addMember(description);
-
- final DynamicForm form = new DynamicForm();
-
- PropertyDefinitionSimple memberPropertyDefinitionSimple = (PropertyDefinitionSimple) propertyDefinitionList
- .getMemberDefinition();
- final String propertyName = memberPropertyDefinitionSimple.getName();
- final PropertySimple newMemberPropertySimple = new PropertySimple(propertyName, null);
-
- FormItem simpleField = buildSimpleField(memberPropertyDefinitionSimple, newMemberPropertySimple);
- simpleField.setTitle(memberPropertyDefinitionSimple.getDisplayName());
- simpleField.setShowTitle(true);
- simpleField.setAlign(Alignment.CENTER);
- simpleField.setDisabled(false);
- simpleField.setRequired(true);
- simpleField.setEndRow(true);
-
- SpacerItem spacer = new SpacerItem();
- spacer.setHeight(9);
-
- form.setItems(simpleField, spacer);
- vLayout.addMember(form);
-
- final IButton okButton = new LocatableIButton(extendLocatorId("OK"), MSG.common_button_ok());
- okButton.disable();
- okButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
- public void onClick(ClickEvent clickEvent) {
- propertyList.add(newMemberPropertySimple);
- // Rebuild the select item options.
- LinkedHashMap<String, String> memberValueToIndexMap = buildValueMap(propertyList);
- membersItem.setValueMap(memberValueToIndexMap);
+ if(propertyList.getList().size() >= propertyDefinitionList.getMax()){
+ SC.say(MSG.view_configEdit_maxBoundsExceeded(String.valueOf(propertyDefinitionList.getMax())));
+ }else {
+ final LocatableWindow popup = createPopup(MSG.view_configEdit_addItem(), 300, 145);
- firePropertyChangedEvent(propertyList, propertyDefinitionList, true);
- CoreGUI.getMessageCenter().notify(
- new Message(MSG.view_configEdit_msg_4(), EnumSet.of(Message.Option.Transient)));
+ VLayout vLayout = new VLayout();
+ vLayout.setMargin(10);
- popup.destroy();
- }
- });
+ HTMLFlow description = new HTMLFlow(propertyDefinitionList.getDescription());
+ vLayout.addMember(description);
- form.addItemChangedHandler(new ItemChangedHandler() {
- public void onItemChanged(ItemChangedEvent itemChangedEvent) {
- Object newValue = itemChangedEvent.getNewValue();
- newMemberPropertySimple.setValue(newValue);
+ final DynamicForm form = new DynamicForm();
- // Only enable the OK button, allowing the user to add the property to the map, if the
- // property is valid.
- boolean isValid = form.validate();
- okButton.setDisabled(!isValid);
- }
- });
+ PropertyDefinitionSimple memberPropertyDefinitionSimple = (PropertyDefinitionSimple) propertyDefinitionList
+ .getMemberDefinition();
+ final String propertyName = memberPropertyDefinitionSimple.getName();
+ final PropertySimple newMemberPropertySimple = new PropertySimple(propertyName, null);
- final IButton cancelButton = new LocatableIButton(extendLocatorId("Cancel"), MSG
- .common_button_cancel());
- cancelButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
- public void onClick(ClickEvent clickEvent) {
- popup.destroy();
- }
- });
+ FormItem simpleField = buildSimpleField(memberPropertyDefinitionSimple, newMemberPropertySimple);
+ simpleField.setTitle(memberPropertyDefinitionSimple.getDisplayName());
+ simpleField.setShowTitle(true);
+ simpleField.setAlign(Alignment.CENTER);
+ simpleField.setDisabled(false);
+ simpleField.setRequired(true);
+ simpleField.setEndRow(true);
+
+ SpacerItem spacer = new SpacerItem();
+ spacer.setHeight(9);
+
+ form.setItems(simpleField, spacer);
+ vLayout.addMember(form);
+
+ final IButton okButton = new LocatableIButton(extendLocatorId("OK"), MSG.common_button_ok());
+ okButton.disable();
+ okButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
+ public void onClick(ClickEvent clickEvent) {
+ propertyList.add(newMemberPropertySimple);
+
+ // Rebuild the select item options.
+ LinkedHashMap<String, String> memberValueToIndexMap = buildValueMap(propertyList);
+ membersItem.setValueMap(memberValueToIndexMap);
+
+ firePropertyChangedEvent(propertyList, propertyDefinitionList, true);
+ CoreGUI.getMessageCenter().notify(
+ new Message(MSG.view_configEdit_msg_4(), EnumSet.of(Message.Option.Transient)));
+
+ popup.destroy();
+ }
+ });
- HLayout buttons = new HLayout();
- buttons.setAlign(Alignment.CENTER);
- buttons.setTop(10);
- buttons.setMembersMargin(10);
- buttons.setMembers(okButton, cancelButton);
- vLayout.addMember(buttons);
+ form.addItemChangedHandler(new ItemChangedHandler() {
+ public void onItemChanged(ItemChangedEvent itemChangedEvent) {
+ Object newValue = itemChangedEvent.getNewValue();
+ newMemberPropertySimple.setValue(newValue);
- popup.addItem(vLayout);
- popup.show();
+ // Only enable the OK button, allowing the user to add the property to the map, if the
+ // property is valid.
+ boolean isValid = form.validate();
+ okButton.setDisabled(!isValid);
+ }
+ });
+
+ final IButton cancelButton = new LocatableIButton(extendLocatorId("Cancel"), MSG
+ .common_button_cancel());
+ cancelButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
+ public void onClick(ClickEvent clickEvent) {
+ popup.destroy();
+ }
+ });
- simpleField.focusInItem();
+ HLayout buttons = new HLayout();
+ buttons.setAlign(Alignment.CENTER);
+ buttons.setTop(10);
+ buttons.setMembersMargin(10);
+ buttons.setMembers(okButton, cancelButton);
+ vLayout.addMember(buttons);
+
+ popup.addItem(vLayout);
+ popup.show();
+
+ simpleField.focusInItem();
}
+ }
});
+
footer.addMember(newButton);
}
@@ -1675,15 +1676,8 @@ public class ConfigurationEditor extends LocatableVLayout {
final PropertyMap workingMap = (newRow) ? new PropertyMap(memberMapDefinition.getName()) : memberMap
.deepCopy(true);
- final LocatableWindow popup = new LocatableWindow(extendLocatorId("MapEditor"));
- String title = (mapReadOnly) ? MSG.view_configEdit_viewRow() : MSG.view_configEdit_editRow();
- popup.setTitle(title);
- popup.setWidth(800);
- popup.setHeight(600);
- popup.setIsModal(true);
- popup.setShowModalMask(true);
- popup.setShowCloseButton(false);
- popup.centerInPage();
+ final String title = (mapReadOnly) ? MSG.view_configEdit_viewRow() : MSG.view_configEdit_editRow();
+ final LocatableWindow popup = createPopup(title, 800, 600);
final LocatableVLayout layout = new LocatableVLayout(popup.extendLocatorId("Layout"));
layout.setHeight100();
@@ -1756,6 +1750,18 @@ public class ConfigurationEditor extends LocatableVLayout {
popup.show();
}
+ private LocatableWindow createPopup(String title, int width, int height) {
+ final LocatableWindow popup = new LocatableWindow(extendLocatorId("MapEditor"));
+ popup.setTitle(title);
+ popup.setWidth(width);
+ popup.setHeight(height);
+ popup.setIsModal(true);
+ popup.setShowModalMask(true);
+ popup.setShowCloseButton(false);
+ popup.centerInPage();
+ return popup;
+ }
+
private void mergePropertyMap(PropertyMap sourceMap, PropertyMap targetMap,
List<PropertyDefinition> memberDefinitions) {
for (PropertyDefinition subDef : memberDefinitions) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationFactory.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationFactory.java
index 2142764..c4cc0f7 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationFactory.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationFactory.java
@@ -138,6 +138,8 @@ public abstract class TestConfigurationFactory {
"a list of Integer simples", true, new PropertyDefinitionSimple("integer", "an integer", false,
PropertySimpleType.INTEGER));
listOfSimplesPropDef.setDisplayName(listOfSimplesPropDef.getName());
+ listOfSimplesPropDef.setMax(listOfSimplesPropDef.getMax());
+ listOfSimplesPropDef.setMin(listOfSimplesPropDef.getMin());
addPropertyDefinition(configDef, listOfSimplesPropDef, orderIndex++);
PropertyDefinitionMap mapInListPropDef =
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index e8d267b..56766cd 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -1176,6 +1176,8 @@ view_configEdit_error_3 = Cannot add property named [{0}]. The property name is
view_configEdit_files = Files
view_configEdit_hideAll = Hide All
view_configEdit_jumpToSection = Jump to Section
+view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
view_configEdit_msg_1 = Added property [{0}] to the set.
view_configEdit_msg_2 = Removed properties from the set.
view_configEdit_msg_3 = [{0} {1}] deleted from list.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index f02b83b..f7d4ef7 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -1195,6 +1195,8 @@ view_configEdit_error_3 = Nelze pÅidat vlastnost nazvanou [{0}]. Jméno té vla
view_configEdit_files = Soubory
view_configEdit_hideAll = SkrÜt vše
view_configEdit_jumpToSection = PÅejÃt na sekci
+##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
view_configEdit_msg_1 = PÅidána vlastnost [{0}]
view_configEdit_msg_2 = Vlastnost odebrána z mnoşiny.
view_configEdit_msg_3 = [{0} {1}] smazáno ze seznamu.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 4de4df2..a40cb2f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -1060,6 +1060,8 @@ view_configEdit_confirm_2 = Sind Sie sicher dass sie diese Zeile löschen wollen
view_configEdit_files = Dateien
view_configEdit_hideAll = Alle verbergen
view_configEdit_jumpToSection = Zum Abschnitt springen
+##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
view_configEdit_msg_1 = Eigentschaft [{0}] zur Menge hinzugefÃŒgt
##view_configEdit_msg_2 = Removed properties from the set.
view_configEdit_msg_3 = [{0} {1}] aus der Liste gelöscht.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index ea692e6..e135c0d 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -1172,6 +1172,8 @@ view_configEdit_error_3 = [{0}] ãšããååã®ããããã£ãè¿œå ã§ã
view_configEdit_files = ãã¡ã€ã«
view_configEdit_hideAll = ãã¹ãŠé ã
view_configEdit_jumpToSection = ã»ã¯ã·ã§ã³ãžã®ãžã£ã³ã
+##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
view_configEdit_msg_1 = ãããã㣠[{0}] ãã»ããã«è¿œå ããŸãã
view_configEdit_msg_2 = ã»ããããããããã£ãåãé€ããŸãã
view_configEdit_msg_3 = [{0} {1}] ããªã¹ãããåé€ãããŸãã
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 26f3ab8..843d5d2 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -1182,6 +1182,8 @@ view_configEdit_error_3 = N\u00E3o f\u00F3 poss\u00EDvel adicionar a propriedade
view_configEdit_files = Arquivos
view_configEdit_hideAll = Ocultar todos
view_configEdit_jumpToSection = Ir direto para a Sele\u00E7\u00E3o
+##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
view_configEdit_msg_1 = Propriedade [{0}] adicionada ao conjunto.
view_configEdit_msg_2 = Propriedades removidas do conjunto.
view_configEdit_msg_3 = [{0} {1}] removido da lista.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 394ecc9..512e087 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -1165,6 +1165,8 @@
#view_configEdit_files = Files
#view_configEdit_hideAll = Hide All
#view_configEdit_jumpToSection = Jump to Section
+##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
#view_configEdit_msg_1 = Added property [{0}] to the set.
#view_configEdit_msg_2 = Removed properties from the set.
#view_configEdit_msg_3 = [{0} {1}] deleted from list.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index dff469a..269ed1c 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -1166,6 +1166,8 @@ view_configEdit_error_3 = \u65e0\u6cd5\u6dfb\u52a0\u540d\u4e3a[{0}]\u7684\u5c5e\
view_configEdit_files = \u6587\u4ef6
view_configEdit_hideAll = \u9690\u85cf\u6240\u6709
view_configEdit_jumpToSection = \u8df3\u81f3\u6a21\u5757
+##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
view_configEdit_msg_1 = \u589e\u52a0\u5c5e\u6027 [{0}]\u5230\u96c6\u5408.
view_configEdit_msg_2 = \u79fb\u9664\u96c6\u5408\u5185\u6240\u6709\u7684\u5c5e\u6027.
view_configEdit_msg_3 = \u4ece\u5217\u8868\u4e2d\u5220\u9664[{0} {1}]\u6210\u529f.
commit 4c3b4fdd3ad080d772b2932b526e08366694dc0f
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu Jul 12 21:06:36 2012 +0200
Allow to pass the number of data points to the backend.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
index 163d48d..cb7cc5c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
@@ -166,13 +166,16 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
}
public Response getMetricDataForGroupAndDefinition(int groupId, int definitionId, long startTime, long endTime,
- boolean hideEmpty, Request request, HttpHeaders headers) {
+ int dataPoints,boolean hideEmpty, Request request, HttpHeaders headers) {
if (startTime==0) {
endTime = System.currentTimeMillis();
startTime = endTime - EIGHT_HOURS;
}
+ if (dataPoints<1)
+ throw new IllegalArgumentException("datapoints must be >=0");
+
MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
boolean isHtml = mediaType.equals(MediaType.TEXT_HTML_TYPE);
@@ -187,7 +190,7 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
res.setGroup(true);
List<List<MeasurementDataNumericHighLowComposite>> listList = dataManager.findDataForCompatibleGroup(caller,
- groupId,definitionId,startTime,endTime,60); // TODO number of points
+ groupId,definitionId,startTime,endTime,dataPoints);
if (listList.isEmpty()) {
throw new StuffNotFoundException("Data for group with id " + groupId + " and definition " + definitionId);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
index 4ea9343..4ae33f4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
@@ -120,6 +120,7 @@ public interface MetricHandlerLocal {
@ApiParam("Id of the metric definition to retrieve") @PathParam("definitionId") int definitionId,
@ApiParam(value = "Start time since epoch.", defaultValue="End time - 8h") @QueryParam("startTime") long startTime,
@ApiParam(value = "End time since epoch.", defaultValue = "Now") @QueryParam("endTime") long endTime,
+ @ApiParam("Number of buckets - currently fixed at 60") @QueryParam("dataPoints") @DefaultValue("60") int dataPoints,
@ApiParam(value = "Hide rows that are NaN only", defaultValue = "false") @QueryParam("hideEmpty") boolean hideEmpty,
@Context Request request,
@Context HttpHeaders headers);
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest.java
index 9b1d0bf..ec0fcd4 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest.java
@@ -1,3 +1,22 @@
+/*
+ * 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;
@@ -32,8 +51,9 @@ public class PluginManagerBeanTest extends MetadataBeanTest {
private PluginDeploymentScanner pluginScanner;
@AfterClass
- public void afterClass() {
+ public void afterClass() throws Exception {
this.pluginScanner = null;
+ super.afterClass();
}
@Override
commit 9af5936fe96183531a393f68dd638ef79cc895cd
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Jul 12 19:26:51 2012 +0200
make sure CLI scripts on the server redirect standard and error output to
the tracked writer.
diff --git a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
index 98246a0..0bca2fa 100644
--- a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
+++ b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
@@ -274,6 +274,8 @@ public class CliSender extends AlertSender<CliComponent> {
bindings.put("alert", alert);
ScriptEngine engine = takeEngine(bindings);
+ engine.getContext().setWriter(output);
+ engine.getContext().setErrorWriter(output);
return engine;
}
commit 12762b55b0add61b33ff861047acf2e7eac1cff5
Merge: 7095212 a49e075
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Jul 12 18:00:02 2012 +0200
Merge lkrejci/modular-scripting into master
commit 709521269eea8fa16f7c672e34ad90c0b748c0ee
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Jul 12 16:39:49 2012 +0200
Fixing the last javascript specific thing in the CLI - no more assumptions
about the format of the error message.
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index cfe1686..c7f6bbf 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@ -58,6 +58,7 @@ import org.rhq.enterprise.client.utility.CodeCompletionCompletorWrapper;
import org.rhq.enterprise.client.utility.DummyCodeCompletion;
import org.rhq.enterprise.clientapi.RemoteClient;
import org.rhq.scripting.CodeCompletion;
+import org.rhq.scripting.ScriptEngineInitializer;
/**
* @author Greg Hinkle
@@ -108,6 +109,7 @@ public class ClientMain {
private Recorder recorder = new NoOpRecorder();
private ScriptEngine engine;
+ private ScriptEngineInitializer scriptEngineInitializer;
private class StartupConfiguration {
public boolean askForPassword;
@@ -675,6 +677,12 @@ public class ClientMain {
try {
engine = ScriptEngineFactory.getScriptEngine(getLanguage(),
new PackageFinder(Arrays.asList(getLibDir())), null);
+
+ if (engine == null) {
+ throw new IllegalStateException("The scripting language '" + getLanguage()
+ + "' could not be loaded.");
+ }
+ scriptEngineInitializer = ScriptEngineFactory.getInitializer(getLanguage());
} catch (ScriptException e) {
e.printStackTrace();
} catch (IOException e) {
@@ -685,6 +693,10 @@ public class ClientMain {
return engine;
}
+ public String getUsefulErrorMessage(ScriptException e) {
+ return scriptEngineInitializer.extractUserFriendlyErrorMessage(e);
+ }
+
public Map<String, ClientCommand> getCommands() {
return commands;
}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
index a511310..42137af 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
@@ -151,9 +151,7 @@ public class ScriptCommand implements ClientCommand {
}
} catch (ScriptException e) {
- String message = e.getCause() != null ? e.getCause().getMessage() : e.getMessage();
- message = message.replace("sun.org.mozilla.javascript.internal.EcmaError: ", "");
- message = message.replace("(<Unknown source>#1) in <Unknown source> at line number 1", "");
+ String message = client.getUsefulErrorMessage(e);
client.getPrintWriter().println(message);
client.getPrintWriter().println(script);
commit 0520b77135d2be31dea003cb1b99bf75aac49a9b
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Jul 12 16:35:16 2012 +0200
Finishing up the python support for CLI.
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
index c91b706..e65f793 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
@@ -34,5 +34,11 @@ import java.net.URI;
*/
public interface ScriptSourceProvider {
+ /**
+ * Returns the reader of the source of the script specified by given location.
+ *
+ * @param location the location of the script
+ * @return the reader of the script source or null if it could not be found
+ */
Reader getScriptSource(URI location);
}
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index 6009b1b..06bed89 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -23,7 +23,6 @@
<artifactId>rhino</artifactId>
<version>1.7R4</version>
</dependency>
-
</dependencies>
<build>
diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
index 4b48e52..b657dd2 100644
--- a/modules/enterprise/scripting/python/pom.xml
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -27,10 +27,39 @@
<build>
<plugins>
<plugin>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
- </configuration>
+ <groupId>org.sonatype.plugins</groupId>
+ <artifactId>jarjar-maven-plugin</artifactId>
+ <version>1.5</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>jarjar</goal>
+ </goals>
+ <configuration>
+ <includes>
+ <include>org.python:jython-standalone</include>
+ </includes>
+ <rules>
+ <keep>
+ <pattern>*.**</pattern>
+ </keep>
+ </rules>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+ <argLine>-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>
</plugin>
</plugins>
</build>
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineFactory.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineFactory.java
new file mode 100644
index 0000000..2d1ef65
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineFactory.java
@@ -0,0 +1,41 @@
+/*
+ * 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.scripting.python;
+
+import javax.script.ScriptEngine;
+
+import org.python.jsr223.PyScriptEngineFactory;
+
+/**
+ * @author Lukas Krejci
+ *
+ */
+public class PythonScriptEngineFactory extends PyScriptEngineFactory {
+
+ @Override
+ public Object getParameter(String key) {
+ if (ScriptEngine.NAME.equals(key)) {
+ return "python";
+ } else {
+ return super.getParameter(key);
+ }
+ }
+}
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
index 07ed8eb..e868204 100644
--- a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
@@ -23,12 +23,19 @@ import java.lang.reflect.Method;
import java.security.PermissionCollection;
import java.util.Collections;
import java.util.HashSet;
+import java.util.Properties;
import java.util.Set;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.python.core.Py;
+import org.python.core.PySystemState;
+import org.python.util.PythonInterpreter;
+
import org.rhq.scripting.ScriptEngineInitializer;
import org.rhq.scripting.ScriptSourceProvider;
import org.rhq.scripting.util.SandboxedScriptEngine;
@@ -40,6 +47,16 @@ import org.rhq.scripting.util.SandboxedScriptEngine;
*/
public class PythonScriptEngineInitializer implements ScriptEngineInitializer {
+ private static final Log LOG = LogFactory.getLog(PythonScriptEngineInitializer.class);
+
+ static {
+ Properties props = new Properties();
+ props.put("python.packages.paths", "java.class.path,sun.boot.class.path");
+ props.put("python.packages.directories", "java.ext.dirs");
+ props.put("python.cachedir.skip", false);
+ PythonInterpreter.initialize(System.getProperties(), props, null);
+ }
+
private ScriptEngineManager engineManager = new ScriptEngineManager();
@Override
@@ -47,17 +64,29 @@ public class PythonScriptEngineInitializer implements ScriptEngineInitializer {
ScriptEngine eng = engineManager.getEngineByName("python");
+ //XXX this might not work perfectly in jython
+ //but we can't make it work perfectly either, so let's just
+ //keep our fingers crossed..
+ //http://www.jython.org/jythonbook/en/1.0/ModulesPackages.html#from-import-statements
for (String pkg : packages) {
- eng.eval("from " + pkg + " import *\n");
+ try {
+ eng.eval("from " + pkg + " import *\n");
+ } catch (ScriptException e) {
+ //well, let's just keep things going, this is not fatal...
+ LOG.info("Python script engine could not pre-import members of package '" + pkg + "'.");
+ }
}
//fingers crossed we can secure jython like this
- return new SandboxedScriptEngine(eng, permissions);
+ return permissions == null ? eng : new SandboxedScriptEngine(eng, permissions);
}
@Override
public void installScriptSourceProvider(ScriptEngine scriptEngine, ScriptSourceProvider provider) {
- //TODO add support for script source providers... possibly using http://www.python.org/dev/peps/pep-0302/
+ PySystemState sys = Py.getSystemState();
+ if (sys != null) {
+ sys.path_hooks.append(new PythonSourceProvider(provider));
+ }
}
@Override
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonSourceProvider.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonSourceProvider.java
new file mode 100644
index 0000000..70688d4
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonSourceProvider.java
@@ -0,0 +1,136 @@
+/*
+ * 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.scripting.python;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.python.core.Py;
+import org.python.core.PyObject;
+import org.python.core.imp;
+
+import org.rhq.scripting.ScriptSourceProvider;
+
+/**
+ * This class translates the requests for modules in python using the import
+ * statement into calls to RHQ's script source providers.
+ * <p>
+ * For a script to be downloadable using RHQ, one must add a path prefix to
+ * <code>sys.path</code> so that RHQ is aware of the available locations it should
+ * look into.
+ * <p>
+ * For example, if you have the RHQ repository script source provider available on
+ * the classpath of the CLI, you can add the following to the <code>sys.path</code>:
+ * <pre>
+ * <code>
+ * import sys
+ * sys.path.append("__rhq__:rhq:/repositories/my_repository")
+ * </code>
+ * </pre>
+ * and then you can import a module from that repository by the ordinary import statement:
+ * <pre>
+ * <code>
+ * import my_module
+ * </code>
+ * </pre>
+ * This will translate into a download of the script from the following location:
+ * <code>rhq://repositories/my_repository/my_module.py</code>.
+ *
+ * @author Lukas Krejci
+ */
+public class PythonSourceProvider extends PyObject {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final String RHQ_PATH_EXTENSION_PREFIX = "__rhq__:";
+
+ private ScriptSourceProvider scriptSourceProvider;
+ private String currentPathPrefix;
+
+ public PyObject __call__(PyObject args[], String keywords[]) {
+ if (args[0].toString().startsWith(RHQ_PATH_EXTENSION_PREFIX)) {
+ currentPathPrefix = args[0].toString().substring(RHQ_PATH_EXTENSION_PREFIX.length());
+ return this;
+ }
+ throw Py.ImportError("unable to handle");
+ }
+
+ private static class ReaderInputStream extends InputStream {
+ private Reader rdr;
+
+ public ReaderInputStream(Reader rdr) {
+ this.rdr = rdr;
+ }
+
+ @Override
+ public int read() throws IOException {
+ return rdr.read();
+ }
+
+ }
+
+ public class Loader extends PyObject {
+
+ private static final long serialVersionUID = 1L;
+
+ private String prefix;
+
+ public Loader(String prefix) {
+ this.prefix = prefix;
+ }
+
+ public PyObject load_module(String name) {
+ try {
+ URI uri = new URI(prefix + name + ".py");
+ Reader rdr = scriptSourceProvider.getScriptSource(uri);
+ return imp.createFromSource(name, new ReaderInputStream(rdr), uri.toString());
+ } catch (URISyntaxException e) {
+ return Py.None;
+ }
+ }
+ }
+
+ public PythonSourceProvider(ScriptSourceProvider scriptSourceProvider) {
+ this.scriptSourceProvider = scriptSourceProvider;
+ }
+
+ public PyObject find_module(String name) {
+ return find_module(name, Py.None);
+ }
+
+ public PyObject find_module(String name, PyObject path) {
+ try {
+ URI uri = new URI(currentPathPrefix + name + ".py");
+
+ return scriptSourceProvider.getScriptSource(uri) == null ? Py.None : new Loader(currentPathPrefix);
+ } catch (URISyntaxException e) {
+ return Py.None;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getType().toString();
+ }
+}
diff --git a/modules/enterprise/scripting/python/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory b/modules/enterprise/scripting/python/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
new file mode 100644
index 0000000..f2c5a71
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
@@ -0,0 +1 @@
+org.rhq.scripting.python.PythonScriptEngineFactory
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
new file mode 100644
index 0000000..b1d4a65
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/test/java/org/rhq/scripting/python/PythonScriptEngineInitializerTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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.scripting.python;
+
+import java.io.FilePermission;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.security.AccessControlException;
+import java.security.Permissions;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.rhq.scripting.ScriptSourceProvider;
+
+/**
+ * @author Lukas Krejci
+ */
+@Test
+public class PythonScriptEngineInitializerTest {
+
+ public static class Tester {
+ private int cnt = 0;
+
+ public void increment() {
+ ++cnt;
+ }
+
+ public int getInvocationCoung() {
+ return cnt;
+ }
+ }
+
+ private static final String EXPECTED_OUTPUT = "kachny";
+
+ public static class SourceProvider implements ScriptSourceProvider {
+ @Override
+ public Reader getScriptSource(URI scriptUri) {
+ if (scriptUri.toString().equals("test/test_module.py")) {
+ return new StringReader("print '" + EXPECTED_OUTPUT + "'");
+ }
+ return null;
+ }
+ }
+
+ public void testEngineInitialization() throws Exception {
+ PythonScriptEngineInitializer initializer = new PythonScriptEngineInitializer();
+ ScriptEngine engine = initializer.instantiate(Collections.<String> emptySet(), null);
+
+ //just some code to test out this is python
+ engine.eval("from java.util import HashMap\nHashMap()");
+ }
+
+ public void testMethodIndirection() throws Exception {
+ PythonScriptEngineInitializer initializer = new PythonScriptEngineInitializer();
+ ScriptEngine engine = initializer.instantiate(Collections.<String> emptySet(), null);
+
+ Bindings bindings = engine.createBindings();
+ Tester tester = new Tester();
+ bindings.put("tester", tester);
+
+ engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
+
+ engine.eval("tester.increment()");
+
+ Assert.assertEquals(tester.getInvocationCoung(), 1, "Unexpected number of tester invocations.");
+
+ Map<String, Set<Method>> methods = getMethodsByName(Tester.class);
+ for (Set<Method> ms : methods.values()) {
+ Set<String> fns = initializer.generateIndirectionMethods("tester", ms);
+ for (String fn : fns) {
+ engine.eval(fn);
+ }
+ }
+
+ engine.eval("increment()");
+ Assert.assertEquals(tester.getInvocationCoung(), 2,
+ "Unexpected number of tester invocations after calling an indirected method.");
+ }
+
+ public void testSecuredEngine() throws Exception {
+ PythonScriptEngineInitializer initializer = new PythonScriptEngineInitializer();
+
+ //jython seems to need these two..
+ Permissions perms = new Permissions();
+ perms.add(new RuntimePermission("createClassLoader"));
+ perms.add(new RuntimePermission("getProtectionDomain"));
+
+ //add permission to read files so that modules can be loaded, but writing should fail
+ perms.add(new FilePermission("<<ALL FILES>>", "read"));
+
+ ScriptEngine engine = initializer.instantiate(Collections.<String> emptySet(), perms);
+
+ try {
+ engine.eval("import os\nfp = open('pom.xml', 'w')");
+ Assert.fail("Opening a file for writing should have failed with a security exception.");
+ } catch (ScriptException e) {
+ checkIsCausedByAccessControlException(e);
+ }
+ }
+
+ public void testSourceProvider() throws Exception {
+ PythonScriptEngineInitializer initializer = new PythonScriptEngineInitializer();
+
+ ScriptEngine engine = initializer.instantiate(Collections.<String> emptySet(), null);
+
+ StringWriter wrt = new StringWriter();
+
+ engine.getContext().setWriter(wrt);
+
+ initializer.installScriptSourceProvider(engine, new SourceProvider());
+
+ engine
+ .eval("import sys\nsys.path.append('__rhq__:test-unsupported/')\nsys.path.append('__rhq__:test/')\nimport test_module");
+
+ Assert.assertEquals(wrt.toString(), EXPECTED_OUTPUT + "\n", "Unexpected output from a custom module.");
+ }
+
+ private void checkIsCausedByAccessControlException(Throwable e) {
+ Throwable ex = e;
+ while (ex != null) {
+ if (ex instanceof AccessControlException) {
+ return;
+ }
+
+ ex = ex.getCause();
+ }
+
+ Assert.fail("Expected an AccessControlException but the exception doesn't seem to be caused by it.", e);
+ }
+
+ private static Map<String, Set<Method>> getMethodsByName(Class<?> cls) {
+ Map<String, Set<Method>> ret = new HashMap<String, Set<Method>>();
+
+ for (Method m : cls.getDeclaredMethods()) {
+ Set<Method> methods = ret.get(m.getName());
+ if (methods == null) {
+ methods = new HashSet<Method>();
+ ret.put(m.getName(), methods);
+ }
+
+ methods.add(m);
+ }
+
+ return ret;
+ }
+}
diff --git a/modules/enterprise/scripting/python/src/test/resources/allow-all.policy b/modules/enterprise/scripting/python/src/test/resources/allow-all.policy
new file mode 100644
index 0000000..cb9dbed
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/test/resources/allow-all.policy
@@ -0,0 +1,3 @@
+grant {
+ permission java.security.AllPermission;
+};
commit a49e0754c248ee94a1252dc7dbbbd2048133c426
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Thu Jul 12 14:50:02 2012 +0200
Monitoring -> Tables -> Get Live Value, the resulting modal window has now sorted records
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
index fe00f1a..881a3a3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
@@ -19,12 +19,20 @@
package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.widgets.events.CloseClickEvent;
import com.smartgwt.client.widgets.events.CloseClickHandler;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
+
import org.rhq.core.domain.measurement.MeasurementData;
import org.rhq.core.domain.measurement.MeasurementUnits;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
@@ -38,11 +46,6 @@ import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableListGrid;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableWindow;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
-
/**
* Views a resource's measurements in a tabular view.
*
@@ -118,6 +121,11 @@ public class MeasurementTableView extends Table<MeasurementTableDataSource> {
records.add(record);
}
}
+ Collections.sort(records, new Comparator<ListGridRecord>() {
+ public int compare(ListGridRecord o1, ListGridRecord o2) {
+ return o1.getAttribute("name").compareTo(o2.getAttribute("name"));
+ }
+ });
showLiveData(records);
}
commit 6307139046317a3b9d0037e542197182c7ba1519
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Thu Jul 12 11:17:15 2012 +0200
[BZ Bug 808175 - Monitor>Traits subtab should provide a Get Live Value button] Added support for "getting live value" for resource's traits as well as for group's traits
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Agent.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Agent.java
index 220af57..e96e1d3 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Agent.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Agent.java
@@ -62,6 +62,10 @@ import org.rhq.core.domain.cloud.Server;
@NamedQuery(name = Agent.QUERY_REMOVE_SERVER_REFERENCE, query = "UPDATE Agent a SET a.server.id = NULL WHERE a.server.id = :serverId "),
@NamedQuery(name = Agent.QUERY_COUNT_ALL, query = "SELECT count(a.id) FROM Agent a"),
@NamedQuery(name = Agent.QUERY_FIND_RESOURCE_IDS_FOR_AGENT, query = "SELECT r.id FROM Resource r WHERE r.agent.id = :agentId"),
+ @NamedQuery(name = Agent.QUERY_FIND_RESOURCE_IDS_WITH_AGENTS_BY_RESOURCE_IDS, query = "" //
+ + "SELECT new org.rhq.core.domain.resource.composite.ResourceIdWithAgentComposite(r.id, r.agent) " //
+ + " FROM Resource r " //
+ + " WHERE r.id IN (:resourceIds)"),
@NamedQuery(name = Agent.QUERY_FIND_ALL_SUSPECT_AGENTS, query = "SELECT new org.rhq.core.domain.resource.composite.AgentLastAvailabilityPingComposite "
+ " ( "
+ " a.id,a.name,a.remoteEndpoint,a.lastAvailabilityPing,a.backFilled "
@@ -150,6 +154,7 @@ public class Agent implements Serializable {
public static final String QUERY_FIND_BY_SERVER = "Agent.findByServer";
public static final String QUERY_COUNT_ALL = "Agent.countAll";
public static final String QUERY_FIND_RESOURCE_IDS_FOR_AGENT = "Agent.findResourceIdsForAgent";
+ public static final String QUERY_FIND_RESOURCE_IDS_WITH_AGENTS_BY_RESOURCE_IDS = "Agent.findResourceIdsWithAgentsByResourceIds";
public static final String QUERY_FIND_ALL_SUSPECT_AGENTS = "Agent.findAllSuspectAgents";
public static final String QUERY_FIND_BY_AFFINITY_GROUP = "Agent.findByAffinityGroup";
public static final String QUERY_FIND_WITHOUT_AFFINITY_GROUP = "Agent.findWithoutAffinityGroup";
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/composite/ResourceIdWithAgentComposite.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/composite/ResourceIdWithAgentComposite.java
new file mode 100644
index 0000000..03fbef9
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/composite/ResourceIdWithAgentComposite.java
@@ -0,0 +1,48 @@
+/*
+ * 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.core.domain.resource.composite;
+
+import java.io.Serializable;
+
+import org.rhq.core.domain.resource.Agent;
+
+/**
+ * (resourceId, agent) tuple
+ *
+ * @author Jirka Kremser
+ */
+public class ResourceIdWithAgentComposite implements Serializable {
+
+ private static final long serialVersionUID = 42L;
+ private final int resourceId;
+ private final Agent agent;
+
+ public ResourceIdWithAgentComposite(int resourceId, Agent agent) {
+ this.resourceId = resourceId;
+ this.agent = agent;
+ }
+
+ public int getResourceId() {
+ return resourceId;
+ }
+
+ public Agent getAgent() {
+ return agent;
+ }
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/collection/ArrayUtils.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/collection/ArrayUtils.java
new file mode 100644
index 0000000..12fd15e
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/collection/ArrayUtils.java
@@ -0,0 +1,75 @@
+/*
+ * 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.core.domain.util.collection;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author John Mazzitelli
+ * @author Joseph Marques
+ */
+public class ArrayUtils {
+
+ public static int[] unwrapCollection(Collection<Integer> input) {
+ if (input == null) {
+ return null;
+ }
+ Integer[] intermediate = input.toArray(new Integer[input.size()]);
+ return unwrapArray(intermediate);
+ }
+
+ public static int[] unwrapArray(Integer[] input) {
+ if (input == null) {
+ return null;
+ }
+ int[] output = new int[input.length];
+ for (int i = 0; i < input.length; i++) {
+ output[i] = input[i];
+ }
+ return output;
+ }
+
+ public static Integer[] wrapInArray(int[] input) {
+ if (input == null) {
+ return null;
+ }
+ Integer[] output = new Integer[input.length];
+ for (int i = 0; i < input.length; i++) {
+ output[i] = input[i];
+ }
+ return output;
+ }
+
+ public static List<Integer> wrapInList(int[] input) {
+ if (input == null) {
+ return null;
+ }
+ Integer[] intermediate = wrapInArray(input);
+
+ // do not use Arrays.asList because returned list needs to be modifiable
+ List<Integer> results = new ArrayList<Integer>();
+ for (Integer next : intermediate) {
+ results.add(next);
+ }
+ return results;
+ }
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/MeasurementDataGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/MeasurementDataGWTService.java
index 8db6354..8640383 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/MeasurementDataGWTService.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/MeasurementDataGWTService.java
@@ -50,6 +50,8 @@ public interface MeasurementDataGWTService extends RemoteService {
throws RuntimeException;
Set<MeasurementData> findLiveData(int resourceId, int[] definitionIds) throws RuntimeException;
+
+ Set<MeasurementData> findLiveDataForGroup(int groupId, int resourceId[], int[] definitionIds) throws RuntimeException;
List<List<MeasurementDataNumericHighLowComposite>> findDataForResource(int resourceId, int[] definitionIds,
long beginTime, long endTime, int numPoints) throws RuntimeException;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java
index 325a542..e640d1d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java
@@ -52,6 +52,10 @@ import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
*/
public abstract class AbstractMeasurementDataTraitDataSource extends
RPCDataSource<MeasurementDataTrait, MeasurementDataTraitCriteria> {
+
+ public static final String FIELD_METRIC_SCHED_ID = "id";
+ public static final String FIELD_METRIC_NAME = "name";
+
private MeasurementDataGWTServiceAsync measurementService = GWTServiceLookup.getMeasurementDataService();
protected AbstractMeasurementDataTraitDataSource() {
@@ -70,9 +74,13 @@ public abstract class AbstractMeasurementDataTraitDataSource extends
primaryKeyField.setHidden(true);
fields.add(primaryKeyField);
- DataSourceIntegerField idField = new DataSourceIntegerField("id", MSG.dataSource_traits_field_definitionID());
+ DataSourceIntegerField idField = new DataSourceIntegerField(FIELD_METRIC_SCHED_ID, MSG.dataSource_traits_field_definitionID());
idField.setHidden(true);
fields.add(idField);
+
+ DataSourceIntegerField nameField = new DataSourceIntegerField(FIELD_METRIC_NAME, MSG.common_title_name());
+ nameField.setHidden(true);
+ fields.add(nameField);
return fields;
}
@@ -173,11 +181,13 @@ public abstract class AbstractMeasurementDataTraitDataSource extends
ListGridRecord record = new ListGridRecord();
record.setAttribute("primaryKey", from.getScheduleId() + ":" + from.getTimestamp());
- record.setAttribute("id", from.getSchedule().getDefinition().getId()); // used for detail view
+ record.setAttribute(FIELD_METRIC_SCHED_ID, from.getSchedule().getDefinition().getId()); // used for detail view
record.setAttribute(MeasurementDataTraitCriteria.SORT_FIELD_TIMESTAMP, new Date(from.getTimestamp()));
record.setAttribute(MeasurementDataTraitCriteria.SORT_FIELD_DISPLAY_NAME, from.getSchedule().getDefinition()
.getDisplayName());
record.setAttribute(MeasurementDataTraitCriteria.SORT_FIELD_VALUE, from.getValue());
+ record.setAttribute(FIELD_METRIC_NAME, from.getSchedule().getDefinition().getName());
+ record.setAttribute(MeasurementDataTraitCriteria.FILTER_FIELD_RESOURCE_ID, from.getSchedule().getResource().getId());
return record;
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListView.java
index 2f842a8..6a9d35b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListView.java
@@ -19,16 +19,23 @@
package org.rhq.enterprise.gui.coregui.client.inventory.common;
import java.util.ArrayList;
+import java.util.List;
import com.smartgwt.client.data.Criteria;
import com.smartgwt.client.data.SortSpecifier;
import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.types.SortDirection;
+import com.smartgwt.client.widgets.events.CloseClickEvent;
+import com.smartgwt.client.widgets.events.CloseClickHandler;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
import org.rhq.core.domain.criteria.MeasurementDataTraitCriteria;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
import org.rhq.enterprise.gui.coregui.client.components.table.TableSection;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableListGrid;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableWindow;
/**
* A view that displays a non-paginated table of {@link org.rhq.core.domain.measurement.MeasurementDataTrait trait}s,
@@ -36,7 +43,7 @@ import org.rhq.enterprise.gui.coregui.client.components.table.TableSection;
*
* @author Ian Springer
*/
-public abstract class AbstractMeasurementDataTraitListView extends TableSection {
+public abstract class AbstractMeasurementDataTraitListView extends TableSection<AbstractMeasurementDataTraitDataSource> {
private static final String TITLE = MSG.view_metric_traits();
private static final String[] EXCLUDED_FIELD_NAMES = new String[0];
@@ -70,11 +77,45 @@ public abstract class AbstractMeasurementDataTraitListView extends TableSection
// Set widths and cell formatters on the fields.
ListGridField displayNameField = listGrid.getField(MeasurementDataTraitCriteria.SORT_FIELD_DISPLAY_NAME);
displayNameField.setWidth("20%");
+
+ addTableAction(extendLocatorId("liveValue"), MSG.view_measureTable_getLive(), getLiveValueAction());
}
+
+ protected abstract TableAction getLiveValueAction();
+
+ protected abstract LocatableListGrid decorateLiveDataGrid(List<ListGridRecord> records);
@Override
protected String getDetailsLinkColumnName() {
return MeasurementDataTraitCriteria.SORT_FIELD_DISPLAY_NAME;
}
+
+ public void showLiveData(List<ListGridRecord> records) {
+ final LocatableWindow liveDataWindow = new LocatableWindow(extendLocatorId("liveDataWindow"));
+ liveDataWindow.setTitle(MSG.view_measureTable_live_title());
+ liveDataWindow.setShowModalMask(true);
+ liveDataWindow.setShowMinimizeButton(false);
+ liveDataWindow.setShowMaximizeButton(true);
+ liveDataWindow.setShowCloseButton(true);
+ liveDataWindow.setShowResizer(true);
+ liveDataWindow.setCanDragResize(true);
+ liveDataWindow.setDismissOnEscape(true);
+ liveDataWindow.setIsModal(true);
+ liveDataWindow.setWidth(700);
+ liveDataWindow.setHeight(425);
+ liveDataWindow.setAutoCenter(true);
+ liveDataWindow.centerInPage();
+ liveDataWindow.addCloseClickHandler(new CloseClickHandler() {
+ @Override
+ public void onCloseClick(CloseClickEvent event) {
+ liveDataWindow.destroy();
+ refreshTableInfo();
+ }
+ });
+
+ LocatableListGrid liveDataGrid = decorateLiveDataGrid(records);
+ liveDataWindow.addItem(liveDataGrid);
+ liveDataWindow.show();
+ }
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/traits/TraitsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/traits/TraitsView.java
index ed91c6a..f7eb900 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/traits/TraitsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/traits/TraitsView.java
@@ -18,7 +18,18 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.traits;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.Criteria;
+import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.grid.CellFormatter;
import com.smartgwt.client.widgets.grid.HoverCustomizer;
@@ -27,9 +38,16 @@ import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import org.rhq.core.domain.criteria.MeasurementDataTraitCriteria;
+import org.rhq.core.domain.measurement.MeasurementData;
+import org.rhq.core.domain.util.collection.ArrayUtils;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.LinkManager;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMeasurementDataTraitDataSource;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMeasurementDataTraitListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableListGrid;
import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
/**
@@ -71,7 +89,6 @@ public class TraitsView extends AbstractMeasurementDataTraitListView {
//resourceNameField.setCanGroupBy(true);
AncestryUtil.setupAncestryListGridField(listGrid);
- super.configureTable();
}
@Override
@@ -87,4 +104,92 @@ public class TraitsView extends AbstractMeasurementDataTraitListView {
return criteria;
}
+
+ @Override
+ protected TableAction getLiveValueAction() {
+ return new TableAction() {
+ @Override
+ public boolean isEnabled(ListGridRecord[] selection) {
+ return selection != null && selection.length > 0;
+ }
+
+ @Override
+ public void executeAction(ListGridRecord[] selection, Object actionValue) {
+ if (selection == null || selection.length == 0) {
+ return;
+ }
+ final Map<String, ListGridRecord> selectedRecords = new HashMap<String, ListGridRecord>();
+ int[] definitionIds = new int[selection.length];
+ int i = 0;
+ Set<Integer> resourceIds = new HashSet<Integer>();
+ for (ListGridRecord record : selection) {
+ Integer defId = record
+ .getAttributeAsInt(AbstractMeasurementDataTraitDataSource.FIELD_METRIC_SCHED_ID);
+ definitionIds[i++] = defId.intValue();
+ int resourceId = record.getAttributeAsInt(MeasurementDataTraitCriteria.FILTER_FIELD_RESOURCE_ID);
+ resourceIds.add(resourceId);
+
+ selectedRecords.put(
+ resourceId + ":"
+ + record.getAttribute(AbstractMeasurementDataTraitDataSource.FIELD_METRIC_NAME), record);
+ }
+
+ // actually go out and ask the agents for the data
+ GWTServiceLookup.getMeasurementDataService(60000).findLiveDataForGroup(groupId,
+ ArrayUtils.unwrapCollection(resourceIds), definitionIds, new AsyncCallback<Set<MeasurementData>>() {
+ @Override
+ public void onSuccess(Set<MeasurementData> result) {
+ if (result == null) {
+ result = new HashSet<MeasurementData>(0);
+ }
+ ArrayList<ListGridRecord> records = new ArrayList<ListGridRecord>(result.size());
+ for (MeasurementData data : result) {
+ ListGridRecord record = selectedRecords.get(data.getName());
+ record.setAttribute("value", data.getValue());
+ records.add(record);
+ }
+ Collections.sort(records, new Comparator<ListGridRecord>() {
+ public int compare(ListGridRecord o1, ListGridRecord o2) {
+ return o1.getAttribute("name").compareTo(o2.getAttribute("name"));
+ }
+ });
+ showLiveData(records);
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError(MSG.view_measureTable_getLive_failure(), caught);
+ }
+ });
+ }
+ };
+ }
+
+ @Override
+ protected LocatableListGrid decorateLiveDataGrid(List<ListGridRecord> records) {
+ LocatableListGrid liveDataGrid = new LocatableListGrid(extendLocatorId("liveDataListGrid"));
+ liveDataGrid.setShowAllRecords(true);
+ liveDataGrid.setData(records.toArray(new ListGridRecord[records.size()]));
+ liveDataGrid.setSelectionType(SelectionStyle.NONE);
+ ListGridField name = new ListGridField(MeasurementDataTraitCriteria.SORT_FIELD_DISPLAY_NAME,
+ MSG.dataSource_traits_field_trait());
+ ListGridField value = new ListGridField("value", MSG.common_title_value());
+ ListGridField resourceNameField = new ListGridField(MeasurementDataTraitCriteria.SORT_FIELD_RESOURCE_NAME,
+ MSG.common_title_resource());
+ resourceNameField.setCellFormatter(new CellFormatter() {
+ public String format(Object o, ListGridRecord listGridRecord, int i, int i1) {
+ String url = LinkManager.getResourceLink(listGridRecord.getAttributeAsInt(AncestryUtil.RESOURCE_ID));
+ return SeleniumUtility.getLocatableHref(url, o.toString(), null);
+ }
+ });
+ resourceNameField.setShowHover(true);
+ resourceNameField.setHoverCustomizer(new HoverCustomizer() {
+ public String hoverHTML(Object value, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return AncestryUtil.getResourceHoverHTML(listGridRecord, 0);
+ }
+ });
+ liveDataGrid.setFields(name, value, resourceNameField, AncestryUtil.setupAncestryListGridField());
+
+ return liveDataGrid;
+ }
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java
index fe7b9ec..ad422b7 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java
@@ -18,11 +18,30 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.traits;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.Criteria;
+import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
import org.rhq.core.domain.criteria.MeasurementDataTraitCriteria;
+import org.rhq.core.domain.measurement.MeasurementData;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMeasurementDataTraitDataSource;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMeasurementDataTraitListView;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableListGrid;
/**
* The Resource Monitoring>Traits subtab.
@@ -55,4 +74,71 @@ public class TraitsView extends AbstractMeasurementDataTraitListView {
return criteria;
}
+
+ @Override
+ protected TableAction getLiveValueAction() {
+ return new TableAction() {
+ @Override
+ public boolean isEnabled(ListGridRecord[] selection) {
+ return selection != null && selection.length > 0;
+ }
+
+ @Override
+ public void executeAction(ListGridRecord[] selection, Object actionValue) {
+ if (selection == null || selection.length == 0) {
+ return;
+ }
+ final Map<String, String> scheduleNames = new HashMap<String, String>();
+ int[] definitionIds = new int[selection.length];
+ int i = 0;
+ for (ListGridRecord record : selection) {
+ Integer defId = record.getAttributeAsInt(AbstractMeasurementDataTraitDataSource.FIELD_METRIC_SCHED_ID);
+ definitionIds[i++] = defId.intValue();
+
+ scheduleNames.put(record.getAttribute(AbstractMeasurementDataTraitDataSource.FIELD_METRIC_NAME), record.getAttribute(MeasurementDataTraitCriteria.SORT_FIELD_DISPLAY_NAME));
+ }
+
+ // actually go out and ask the agents for the data
+ GWTServiceLookup.getMeasurementDataService(60000).findLiveData(resourceId,
+ definitionIds, new AsyncCallback<Set<MeasurementData>>() {
+ public void onSuccess(Set<MeasurementData> result) {
+ if (result == null) {
+ result = new HashSet<MeasurementData>(0);
+ }
+ ArrayList<ListGridRecord> records = new ArrayList<ListGridRecord>(result.size());
+ for (MeasurementData data : result) {
+ ListGridRecord record = new ListGridRecord();
+ record.setAttribute("name", scheduleNames.get(data.getName()));
+ record.setAttribute("value", data.getValue());
+ records.add(record);
+ }
+ Collections.sort(records, new Comparator<ListGridRecord>() {
+ public int compare(ListGridRecord o1, ListGridRecord o2) {
+ return o1.getAttribute("name").compareTo(o2.getAttribute("name"));
+ }
+ });
+ showLiveData(records);
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError(MSG.view_measureTable_getLive_failure(), caught);
+ }
+ });
+ }
+ };
+ }
+
+ @Override
+ protected LocatableListGrid decorateLiveDataGrid(List<ListGridRecord> records) {
+ LocatableListGrid liveDataGrid = new LocatableListGrid(extendLocatorId("liveDataListGrid"));
+ liveDataGrid.setShowAllRecords(true);
+ liveDataGrid.setData(records.toArray(new ListGridRecord[records.size()]));
+ liveDataGrid.setSelectionType(SelectionStyle.NONE);
+ ListGridField name = new ListGridField("name", MSG.dataSource_traits_field_trait());
+ ListGridField value = new ListGridField("value", MSG.common_title_value());
+ liveDataGrid.setFields(name, value);
+
+ return liveDataGrid;
+ }
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/MeasurementDataGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/MeasurementDataGWTServiceImpl.java
index 071881e..eec590d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/MeasurementDataGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/MeasurementDataGWTServiceImpl.java
@@ -81,6 +81,15 @@ public class MeasurementDataGWTServiceImpl extends AbstractGWTServiceImpl implem
throw getExceptionToThrowToClient(t);
}
}
+
+ public Set<MeasurementData> findLiveDataForGroup(int groupId, int resourceId[], int[] definitionIds) throws RuntimeException {
+ try {
+ return SerialUtility.prepare(dataManager.findLiveDataForGroup(getSessionSubject(), groupId, resourceId, definitionIds),
+ "MeasurementDataService.findLiveDataForGroup");
+ } catch (Throwable t) {
+ throw getExceptionToThrowToClient(t);
+ }
+ }
public List<List<MeasurementDataNumericHighLowComposite>> findDataForResource(int resourceId, int[] definitionIds,
long beginTime, long endTime, int numPoints) throws RuntimeException {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java
index 32567f0..65ec2a7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java
@@ -73,6 +73,7 @@ import org.rhq.core.domain.measurement.ui.MetricDisplaySummary;
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.composite.ResourceIdWithAgentComposite;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.server.PersistenceUtility;
import org.rhq.core.domain.util.OrderingField;
@@ -775,6 +776,7 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal,
return results;
}
+ @Override
@SuppressWarnings("unchecked")
public Set<MeasurementData> findLiveData(Subject subject, int resourceId, int[] definitionIds) {
if (authorizationManager.canViewResource(subject, resourceId) == false) {
@@ -782,10 +784,11 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal,
+ "] does not have permission to view live measurement data for resource[id=" + resourceId + "]");
}
- Resource resource = entityManager.find(Resource.class, resourceId);
- Agent agent = resource.getAgent();
+ Query query = entityManager.createNamedQuery(Agent.QUERY_FIND_BY_RESOURCE_ID);
+ query.setParameter("resourceId", resourceId);
+ Agent agent = (Agent) query.getSingleResult();
- Query query = entityManager.createNamedQuery(MeasurementSchedule.FIND_BY_RESOURCE_IDS_AND_DEFINITION_IDS);
+ query = entityManager.createNamedQuery(MeasurementSchedule.FIND_BY_RESOURCE_IDS_AND_DEFINITION_IDS);
query.setParameter("definitionIds", ArrayUtils.wrapInList(definitionIds));
query.setParameter("resourceIds", Arrays.asList(resourceId));
List<MeasurementSchedule> schedules = query.getResultList();
@@ -796,7 +799,7 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal,
}
AgentClient ac = agentClientManager.getAgentClient(agent);
- Set<MeasurementData> values = ac.getMeasurementAgentService().getRealTimeMeasurementValue(resourceId,requests);
+ Set<MeasurementData> values = ac.getMeasurementAgentService().getRealTimeMeasurementValue(resourceId, requests);
//[BZ 760139] always return non-null value even when there are errors on the server side. Avoids cryptic
// Global UI Exceptions when attempting to serialize null responses.
if (values == null) {
@@ -807,6 +810,49 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal,
}
@Override
+ @SuppressWarnings("unchecked")
+ public Set<MeasurementData> findLiveDataForGroup(Subject subject, int groupId, int resourceIds[],
+ int[] definitionIds) {
+ if (authorizationManager.canViewGroup(subject, groupId) == false) {
+ throw new PermissionException("User [" + subject.getName()
+ + "] does not have permission to view measurement data for resourceGroup[id=" + groupId + "]");
+ }
+ Set<MeasurementData> values = new HashSet<MeasurementData>();
+
+ if (resourceIds != null) {
+ Query query = entityManager.createNamedQuery(Agent.QUERY_FIND_RESOURCE_IDS_WITH_AGENTS_BY_RESOURCE_IDS);
+ query.setParameter("resourceIds", ArrayUtils.wrapInList(resourceIds));
+ List<ResourceIdWithAgentComposite> resourceIdsWithAgents = query.getResultList();
+
+ for (ResourceIdWithAgentComposite resourceIdWithAgent : resourceIdsWithAgents) {
+ query = entityManager.createNamedQuery(MeasurementSchedule.FIND_BY_RESOURCE_IDS_AND_DEFINITION_IDS);
+ query.setParameter("definitionIds", ArrayUtils.wrapInList(definitionIds));
+ query.setParameter("resourceIds", Arrays.asList(resourceIdWithAgent.getResourceId()));
+ List<MeasurementSchedule> schedules = query.getResultList();
+
+ Map<Integer, Integer> scheduleIdToResourceIdMap = new HashMap<Integer, Integer>(schedules.size());
+ Set<MeasurementScheduleRequest> requests = new HashSet<MeasurementScheduleRequest>(schedules.size());
+ for (MeasurementSchedule schedule : schedules) {
+ requests.add(new MeasurementScheduleRequest(schedule));
+ scheduleIdToResourceIdMap.put(schedule.getId(), resourceIdWithAgent.getResourceId());
+ }
+
+ AgentClient ac = agentClientManager.getAgentClient(resourceIdWithAgent.getAgent());
+ Set<MeasurementData> newValues = ac.getMeasurementAgentService().getRealTimeMeasurementValue(
+ resourceIdWithAgent.getResourceId(), requests);
+ values.addAll(newValues);
+
+ // Add the resource id as a prefix of the name, because the name is not unique across different platforms
+ for (MeasurementData value : newValues) {
+ value.setName(String.valueOf(scheduleIdToResourceIdMap.get(value.getScheduleId())) + ":"
+ + value.getName());
+ }
+ }
+ }
+ return values;
+ }
+
+ @Override
public List<MeasurementDataNumeric> findRawData(Subject subject, int scheduleId, long startTime, long endTime) {
List<MeasurementDataNumeric> result = new ArrayList<MeasurementDataNumeric>();
@@ -817,23 +863,22 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal,
try {
connection = rhqDs.getConnection();
ps = connection.prepareStatement( // TODO supply real impl that spans multiple tables
- "SELECT time_stamp,value FROM " + table + " WHERE schedule_id= ? AND time_stamp BETWEEN ? AND ?");
- ps.setLong(1,scheduleId);
- ps.setLong(2,startTime);
- ps.setLong(3,endTime);
+ "SELECT time_stamp,value FROM " + table + " WHERE schedule_id= ? AND time_stamp BETWEEN ? AND ?");
+ ps.setLong(1, scheduleId);
+ ps.setLong(2, startTime);
+ ps.setLong(3, endTime);
rs = ps.executeQuery();
while (rs.next()) {
- MeasurementDataNumeric point = new MeasurementDataNumeric(rs.getLong(1),scheduleId,rs.getDouble(2));
+ MeasurementDataNumeric point = new MeasurementDataNumeric(rs.getLong(1), scheduleId, rs.getDouble(2));
result.add(point);
}
} catch (SQLException e) {
- e.printStackTrace(); // TODO: Customise this generated block
+ e.printStackTrace(); // TODO: Customise this generated block
} finally {
JDBCUtil.safeClose(connection, ps, rs);
}
-
return result;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
index 4ea8302..a285a7f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
@@ -164,11 +164,24 @@ public interface MeasurementDataManagerLocal {
/**
* Get live metrics for a given MeasurementSchedule
*
- * @param sched MeasurementSchedule to obtain the data for
+ * @param subject the user that is requesting the data
+ * @param resourceId the id of the resource
+ * @param definitionIds the array of ids of schedule definitions
*
* @return MeasurementData for this Schedule
*/
Set<MeasurementData> findLiveData(Subject subject, int resourceId, int[] definitionIds);
+
+ /**
+ * Get live metrics for a given MeasurementSchedule
+ *
+ * @param subject the user that is requesting the data
+ * @param resourceId the array of ids of the resources
+ * @param definitionIds the array of ids of schedule definitions
+ *
+ * @return MeasurementData for this Schedule
+ */
+ Set<MeasurementData> findLiveDataForGroup(Subject subject, int groupId, int[] resourceId, int[] definitionIds);
/**
* Returns a list of numeric data point lists for the given compatible group - one per specified measurement
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java
index 032f8f9..d3163ec 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java
@@ -71,6 +71,13 @@ public interface MeasurementDataManagerRemote {
@WebParam(name = "subject") Subject subject, //
@WebParam(name = "resourceId") int resourceId, //
@WebParam(name = "definitionIds") int[] definitionIds);
+
+ @WebMethod
+ Set<MeasurementData> findLiveDataForGroup(//
+ @WebParam(name = "subject") Subject subject, //
+ @WebParam(name = "groupId") int groupId,//
+ @WebParam(name = "resourceId") int[] resourceId, //
+ @WebParam(name = "definitionIds") int[] definitionIds);
@WebMethod
@XmlJavaTypeAdapter(MeasurementDataNumericHighLowCompositeAdapter.class)
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
index 27cdabd..1ba4d97 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
@@ -666,6 +666,10 @@ public class WebservicesManagerBean implements WebservicesRemote {
public Set<MeasurementData> findLiveData(Subject subject, int resourceId, int[] definitionIds) {
return measurementDataManager.findLiveData(subject, resourceId, definitionIds);
}
+
+ public Set<MeasurementData> findLiveDataForGroup(Subject subject, int groupId, int[] resourceId, int[] definitionIds) {
+ return measurementDataManager.findLiveDataForGroup(subject, groupId, resourceId, definitionIds);
+ }
public List<MeasurementDataTrait> findTraits(Subject subject, int resourceId, int definitionId) {
return measurementDataManager.findTraits(subject, resourceId, definitionId);
commit db5166849d9de681ec1ea65826799f445c272ef0
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu Jul 12 10:19:07 2012 +0200
No-op plugin that is meant as base for jar-less plugins that should not be discovered on the agent side, but which are served through the server side REST-api.
diff --git a/modules/plugins/noop/pom.xml b/modules/plugins/noop/pom.xml
new file mode 100644
index 0000000..cc31433
--- /dev/null
+++ b/modules/plugins/noop/pom.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<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>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-plugins-parent</artifactId>
+ <version>4.5.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-no-op-plugin</artifactId>
+ <packaging>jar</packaging>
+
+ <name>RHQ No-op Plugin</name>
+ <description>An abstract plugin for plugins defining resource types without java-agent support.</description>
+
+ <profiles>
+
+ <profile>
+ <id>dev</id>
+
+ <properties>
+ <rhq.rootDir>../../..</rhq.rootDir>
+ <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+ <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/rhq-downloads/rhq-plugins
+ </rhq.deploymentDir>
+ </properties>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+
+ <execution>
+ <id>deploy</id>
+ <phase>compile</phase>
+ <configuration>
+ <target>
+ <mkdir dir="${rhq.deploymentDir}"/>
+ <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar"/>
+ <echo>*** Updating ${deployment.file}...</echo>
+ <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}"/>
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>deploy-jar-meta-inf</id>
+ <phase>package</phase>
+ <configuration>
+ <target>
+ <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar"/>
+ <echo>*** Updating META-INF dir in ${deployment.file}...</echo>
+ <unjar src="${project.build.directory}/${project.build.finalName}.jar"
+ dest="${project.build.outputDirectory}">
+ <patternset>
+ <include name="META-INF/**"/>
+ </patternset>
+ </unjar>
+ <jar destfile="${deployment.file}" manifest="${project.build.outputDirectory}/META-INF/MANIFEST.MF"
+ update="true">
+ </jar>
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>undeploy</id>
+ <phase>clean</phase>
+ <configuration>
+ <target>
+ <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar"/>
+ <echo>*** Deleting ${deployment.file}...</echo>
+ <delete file="${deployment.file}"/>
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
\ No newline at end of file
diff --git a/modules/plugins/noop/src/main/java/org/rhq/plugins/noop/NoopComponent.java b/modules/plugins/noop/src/main/java/org/rhq/plugins/noop/NoopComponent.java
new file mode 100644
index 0000000..184397d
--- /dev/null
+++ b/modules/plugins/noop/src/main/java/org/rhq/plugins/noop/NoopComponent.java
@@ -0,0 +1,67 @@
+/*
+ * 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.plugins.noop;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+
+/**
+ * Class that servers as discovery and component class
+ * The discovery will on purpose never discover a resource
+ * @author Heiko W. Rupp
+ */
+public class NoopComponent implements ResourceComponent, ResourceDiscoveryComponent {
+ @Override
+ public void start(ResourceContext context) throws Exception {
+ // nothing to do
+ }
+
+ @Override
+ public void stop() {
+ // nothing to do
+ }
+
+ @Override
+ public AvailabilityType getAvailability() {
+ return null;
+ }
+
+ /**
+ * Discovery method, that on purpose always returns an empty set of discovered resources.
+ * This plugin is meant as base for plugins that
+ * @param context the discovery context that provides the information to the component that helps it perform its
+ * discovery
+ *
+ * @return An empty set
+ * @throws Exception in the case something is sooo wrong ..
+ */
+ @Override
+ public Set<DiscoveredResourceDetails> discoverResources(
+ ResourceDiscoveryContext context) throws Exception {
+ return Collections.emptySet();
+ }
+}
diff --git a/modules/plugins/noop/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/noop/src/main/resources/META-INF/rhq-plugin.xml
new file mode 100644
index 0000000..721f737
--- /dev/null
+++ b/modules/plugins/noop/src/main/resources/META-INF/rhq-plugin.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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.
+ -->
+
+<plugin name="No-op"
+ displayName="Abstract NO-OP plugin"
+ description="Abstract plugin supporting concrete plugins that don't want java-agent support"
+ package="org.rhq.plugins.noop"
+ xmlns="urn:xmlns:rhq-plugin">
+</plugin>
\ No newline at end of file
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index d101f55..350c11e 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -53,14 +53,14 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
-
+
<dependency>
<groupId>${rhq.groupId}</groupId>
<artifactId>test-utils</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
-
+
<!--
TODO: This is a fix for the Javac bug requiring annotations to be available when compiling dependent classes.
It is fixed in JDK 6.
@@ -93,7 +93,8 @@
<!-- core plugins -->
<module>platform</module>
<module>jmx</module>
- <module>rhq-agent</module>
+ <module>rhq-agent</module>
+ <module>noop</module>
</modules>
<profiles>
commit 1656f7c935fe1b9aedd3807d12b3ac635f3ab530
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu Jul 12 10:17:13 2012 +0200
BZ 74168 - allow to deploy descriptor-only "agent" plugins.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginScanner.java
index c787943..cbed5c8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginScanner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginScanner.java
@@ -24,6 +24,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
+import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.sql.Connection;
@@ -34,6 +35,8 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
import javax.sql.DataSource;
import javax.transaction.TransactionManager;
@@ -94,8 +97,14 @@ public class AgentPluginScanner {
void registerAgentPlugins() throws Exception {
try {
for (DeploymentInfo di : this.scanned) {
- log.debug("Hot deploying agent plugin [" + di.url + "]...");
- this.agentPluginDeployer.pluginDetected(di);
+ if (di.url.getFile().endsWith("-rhq-plugin.xml")) {
+ // Create a plugin jar and deploy next time
+ createPluginJarFromDescriptorFile(di.url.getFile());
+ }
+ else {
+ log.debug("Hot deploying agent plugin [" + di.url + "]...");
+ this.agentPluginDeployer.pluginDetected(di);
+ }
}
// Register all the new plugins.
@@ -107,6 +116,53 @@ public class AgentPluginScanner {
}
}
+ /**
+ * We take a plugin descriptor and wrap it into a jar file. The original file is
+ * deleted if the wrapping succeeds.
+ * @param fileName Full path of the file to wrap.
+ */
+ private void createPluginJarFromDescriptorFile(String fileName) throws Exception {
+ if (!fileName.endsWith("-rhq-plugin.xml")) {
+ log.warn("The passed file does not end in -rhq-plugin.xml, will not process it");
+ return;
+ }
+
+ log.info("Found a plugin-descriptor at [" + fileName + "], creating a jar from it to be deployed at the next scan");
+ File descriptor = new File(fileName);
+ String name = descriptor.getName();
+ int pos = name.lastIndexOf(".xml");
+ name = name.substring(0,pos) + ".jar"; // TODO special name for those plugins?
+ String parent = descriptor.getParent();
+ JarOutputStream jos = null;
+ FileInputStream fis = null;
+ boolean success = false;
+ try {
+ jos = new JarOutputStream(new FileOutputStream(new File(parent,name)));
+ JarEntry jarEntry = new JarEntry("META-INF");
+ jos.putNextEntry(jarEntry);
+ jarEntry = new JarEntry("META-INF/rhq-plugin.xml");
+ jos.putNextEntry(jarEntry);
+ fis = new FileInputStream(descriptor);
+ int i;
+ while ((i= fis.read())>0) {
+ jos.write(i);
+ }
+ jos.flush();
+ success = true;
+ } catch (IOException e) {
+ log.error("Failed creating the plugin jar from the descriptor: " + e.getMessage());
+ throw e;
+ }
+ finally {
+ JDBCUtil.safeClose(jos);
+ JDBCUtil.safeClose(fis);
+ }
+ if (success) {
+ boolean deleted = descriptor.delete();
+ log.info("Deleted the now obsolete plugin descriptor: " + deleted);
+ }
+ }
+
void agentPluginScan() throws Exception {
// this method just scans the filesystem and database for agent plugin changes but makes
// no attempt to register them or do anything with the agent plugin deployer.
@@ -136,7 +192,7 @@ public class AgentPluginScanner {
/**
* Scans the plugin directory and updates our cache of known plugin files.
* This will purge any old plugins that are deemed obsolete.
- *
+ *
* @return a list of files that appear to be new or updated and should be deployed
*/
List<File> agentPluginScanFilesystem() {
@@ -145,7 +201,7 @@ public class AgentPluginScanner {
// get the current list of plugins deployed on the filesystem
File[] pluginJars = this.agentPluginDeployer.getPluginDir().listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
- return name.endsWith(".jar");
+ return name.endsWith(".jar") || name.endsWith("-rhq-plugin.xml");
}
});
@@ -384,10 +440,10 @@ public class AgentPluginScanner {
log.debug(message);
}
} else {
- //inform on the info level so that it's clear from the logs that the new file
+ //inform on the info level so that it's clear from the logs that the new file
//is going to be used.
log.info(message);
- }
+ }
}
} else {
log.info("Found agent plugin in the DB that we do not yet have: " + name);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScanner.java
index 05865c9..2093041 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScanner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScanner.java
@@ -200,12 +200,12 @@ public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
if (listFiles == null || listFiles.length == 0) {
return; // nothing to do
}
-
for (File file : listFiles) {
File destinationDirectory;
- if (file.getName().endsWith(".jar")) {
+ boolean isJarLess = file.getName().endsWith("-rhq-plugin.xml");
+ if (file.getName().endsWith(".jar") || isJarLess ) {
try {
- if (null == AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(file.toURI().toURL())) {
+ if (!isJarLess && null == AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(file.toURI().toURL())) {
throw new NullPointerException("no xml descriptor found in jar");
}
destinationDirectory = getAgentPluginDir();
@@ -244,10 +244,18 @@ public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
log.error("Failed to set mtime to [" + new Date(file.lastModified()) + "] on file ["
+ realPluginFile + "].");
}
- log.info("Found plugin jar at [" + file.getAbsolutePath() + "] and placed it at ["
+ String tmp;
+ if (!isJarLess)
+ tmp = "jar";
+ else
+ tmp = "descriptor";
+ log.info("Found plugin " + tmp + " at [" + file.getAbsolutePath() + "] and placed it at ["
+ realPluginFile.getAbsolutePath() + "]");
}
}
+ else {
+ log.info("Found a plugin at [" + file.getAbsolutePath() + "], which is the same as the existing one. It will be ignored");
+ }
boolean deleted = file.delete();
if (!deleted) {
log.info("The plugin jar found at[" + file.getAbsolutePath()
commit 7c360f94c89a59f008065b737f6c10a01826fb61
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed Jul 11 08:54:21 2012 -0700
Trivial: fix incorrect imports on ConfigurationEditor
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
index 4e188dd..48df2d6 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
@@ -52,8 +52,26 @@ import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.ValuesManager;
import com.smartgwt.client.widgets.form.events.ItemChangedEvent;
import com.smartgwt.client.widgets.form.events.ItemChangedHandler;
-import com.smartgwt.client.widgets.form.fields.*;
-import com.smartgwt.client.widgets.form.fields.events.*;
+import com.smartgwt.client.widgets.form.fields.ButtonItem;
+import com.smartgwt.client.widgets.form.fields.CanvasItem;
+import com.smartgwt.client.widgets.form.fields.CheckboxItem;
+import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
+import com.smartgwt.client.widgets.form.fields.FloatItem;
+import com.smartgwt.client.widgets.form.fields.FormItem;
+import com.smartgwt.client.widgets.form.fields.PasswordItem;
+import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
+import com.smartgwt.client.widgets.form.fields.SelectItem;
+import com.smartgwt.client.widgets.form.fields.SpacerItem;
+import com.smartgwt.client.widgets.form.fields.SpinnerItem;
+import com.smartgwt.client.widgets.form.fields.StaticTextItem;
+import com.smartgwt.client.widgets.form.fields.TextAreaItem;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
+import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
+import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
+import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
+import com.smartgwt.client.widgets.form.fields.events.FocusEvent;
+import com.smartgwt.client.widgets.form.fields.events.FocusHandler;
import com.smartgwt.client.widgets.form.validator.CustomValidator;
import com.smartgwt.client.widgets.form.validator.FloatRangeValidator;
import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator;
@@ -118,7 +136,6 @@ import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableSectionStack
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableToolStrip;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableWindow;
-import sun.net.www.content.image.png;
/**
* A SmartGWT widget for editing an RHQ {@link Configuration} that conforms to a {@link ConfigurationDefinition}.
commit c0721b423ae75cc18d6969d56a128be882b8edc0
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jul 10 08:56:48 2012 -0700
Add Swagger documentation annotations to CSV Export Reports.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java
index d106ed6..373643b 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java
@@ -17,7 +17,7 @@ public interface AlertDefinitionLocal {
@GZIP
@GET
@Produces({"text/csv"})
- @ApiOperation(value = "Export the AlertDefinitions in the system")
+ @ApiOperation(value = "Export the AlertDefinitions as CSV")
StreamingOutput alertDefinitions(@Context HttpServletRequest request);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java
index 00079e7..31c3df8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java
@@ -9,6 +9,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
import org.jboss.resteasy.annotations.GZIP;
@Path("/configurationHistory")
@@ -19,5 +20,6 @@ public interface ConfigurationHistoryLocal {
@GZIP
@GET
@Produces({"text/csv"})
+ @ApiOperation(value = "Export the Configuration History data as CSV")
StreamingOutput configurationHistory(@Context HttpServletRequest request);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java
index f3da333..fed7590 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java
@@ -28,6 +28,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
import org.jboss.resteasy.annotations.GZIP;
@Path("/driftCompliance")
@@ -38,6 +39,7 @@ public interface DriftComplianceLocal {
@GZIP
@GET
@Produces({"text/csv", "application/xml"})
+ @ApiOperation(value = "Export the drift compliance data")
StreamingOutput generateReport(
@Context HttpServletRequest request,
@QueryParam("resourceTypeId") String resourceTypeId,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java
index 43f2ee1..6b046dc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java
@@ -28,11 +28,13 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
import org.jboss.resteasy.annotations.GZIP;
@Path("/inventorySummary")
@Local
@Api(basePath="http://localhost:7080/coregui/reports", value = "The inventory summary report")
+
public interface InventorySummaryLocal {
/**
@@ -49,6 +51,7 @@ public interface InventorySummaryLocal {
@GZIP
@GET
@Produces({"text/csv"})
+ @ApiOperation(value = "Export the Inventory Summary data as CSV")
StreamingOutput generateReport(
@Context HttpServletRequest request,
@QueryParam("resourceTypeId") String resourceTypeId,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java
index 7ee299a..1567fb5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java
@@ -30,6 +30,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
import org.jboss.resteasy.annotations.GZIP;
@Path("/platformUtilization")
@@ -40,6 +41,7 @@ public interface PlatformUtilizationLocal {
@GZIP
@GET
@Produces({"text/csv"})
+ @ApiOperation(value = "Export the Platform utilization data as CSV")
StreamingOutput generateReport(@Context HttpServletRequest request);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java
index 606be2b..979cb29 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java
@@ -11,6 +11,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
import org.jboss.resteasy.annotations.GZIP;
@Path("/recentAlerts")
@@ -21,6 +22,7 @@ public interface RecentAlertLocal {
@GZIP
@GET
@Produces({"text/csv"})
+ @ApiOperation(value = "Export the Recent Alert data as CSV")
StreamingOutput recentAlerts(
@QueryParam("alertPriority") @DefaultValue("high,medium,low") String alertPriority,
@QueryParam("startTime") Long startTime,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentDriftLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentDriftLocal.java
index fe2fd8b..8bea6c7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentDriftLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentDriftLocal.java
@@ -10,14 +10,18 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
+import org.jboss.resteasy.annotations.GZIP;
@Path("/recentDrift")
@Local
@Api(basePath="http://localhost:7080/coregui/reports", value = "The recent drift report")
public interface RecentDriftLocal {
+ @GZIP
@GET
@Produces({"text/csv"})
+ @ApiOperation(value = "Export the Recent drift data as CSV")
StreamingOutput recentDrift(
@QueryParam("categories") String categories,
@QueryParam("snapshot") Integer snapshot,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java
index 187ad1d..191623a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java
@@ -11,6 +11,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
import org.jboss.resteasy.annotations.GZIP;
@Path("/recentOperations")
@@ -21,6 +22,7 @@ public interface RecentOperationsLocal {
@GZIP
@GET
@Produces({"text/csv"})
+ @ApiOperation(value = "Export the Recent Operations Data as CSV")
StreamingOutput recentOperations(
@QueryParam("status") @DefaultValue("inprogress,success,failure,canceled") String operationRequestStatus,
@QueryParam("startTime") Long startTime,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java
index 217920f..019a715 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java
@@ -9,6 +9,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
import org.jboss.resteasy.annotations.GZIP;
@Path("/suspectMetrics")
@@ -19,6 +20,7 @@ public interface SuspectMetricLocal {
@GZIP
@GET
@Produces("text/csv")
+ @ApiOperation(value = "Export the Suspect Metrics data as CSV")
StreamingOutput suspectMetrics(@Context HttpServletRequest request);
}
commit db20267b46527836cbe22b9a2138a4b70ee26885
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Jul 11 13:53:56 2012 +0200
Make AlertManagerBeanTest I18N aware.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java
index 7700e1a..ade9639 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java
@@ -68,7 +68,7 @@ public interface AlertI18NResourceKeys {
@I18NMessages({ @I18NMessage("Avail stays NOT UP") })
String ALERT_AVAILABILITY_DURATION_NOT_UP_SHORT = "alert.condition.availability.duration.notup.short";
- // Foo Prop > 10.0% of Baseline Mean Value
+ // Foo Prop > 10.0% of Baseline Mean Value
@I18NMessages({ @I18NMessage("{0} {1} {2} of Baseline Mean Value") /*, @I18NMessage(locale = "de", value = "") */})
String ALERT_BASELINE_MEAN = "alert.condition.baseline.mean";
@@ -137,7 +137,8 @@ public interface AlertI18NResourceKeys {
@I18NMessages({ @I18NMessage("{0} Val Chg"), @I18NMessage(locale = "de", value = "{0} Wertï¿œnd.") })
String ALERT_METRIC_CHANGED_SHORT = "alert.condition.metric.changed.short";
- @I18NMessages({ @I18NMessage("Operation [{0}] has status=[{1}]") /*, @I18NMessage(locale = "de", value = "") */})
+ @I18NMessages({ @I18NMessage("Operation [{0}] has status=[{1}]") ,
+ @I18NMessage(locale = "de", value = "Operation [{0}] hat den Status [{1}]") })
String ALERT_OPERATION = "alert.condition.op";
@I18NMessages({ @I18NMessage("Op [{0}]={1}") /*, @I18NMessage(locale = "de", value = "") */})
@@ -188,11 +189,11 @@ public interface AlertI18NResourceKeys {
// Foo Value is Between 1.0B and 2.0B, Inclusive
@I18NMessages({ @I18NMessage("{0} Value is Between {1} and {2}, Inclusive"),
- @I18NMessage(locale = "de", value = "{0} Der Wert zwischen {1} und {2}, pauschal") })
+ @I18NMessage(locale = "de", value = "{0} Der Wert ist zwischen {1} und {2}, inklusiv") })
String ALERT_RANGE_INSIDE_INCL = "alert.condition.range.in.incl";
@I18NMessages({ @I18NMessage("{0} Between {1} - {2}, incl"),
- @I18NMessage(locale = "de", value = "{0} zwischen {1} und {2}, paus") })
+ @I18NMessage(locale = "de", value = "{0} zwischen {1} und {2}, inkl") })
String ALERT_RANGE_INSIDE_INCL_SHORT = "alert.condition.range.in.incl.short";
@I18NMessages({ @I18NMessage("{0} Value is Between {1} and {2}, Exclusive"),
@@ -228,4 +229,8 @@ public interface AlertI18NResourceKeys {
@I18NMessages({ @I18NMessage("\\ - Cond {0}: {1}\\n\\\n" + "\\ - Time: {2}\\n\\\n" + "\\ - Det: {3}\\n\\\n"),
@I18NMessage(locale = "de", value = " - Bed {0}: {1}\\n\\\n - Zeit: {2}\\n\\\n" + "\\ - Det: {3}\\n\\\n") })
String ALERT_EMAIL_CONDITION_LOG_FORMAT_SHORT = "alert.email.condition.log.format.short";
+
+ // Needed for the AlertManagerBeanTest
+ @I18NMessages({ @I18NMessage("Cond(?:ition)?"), @I18NMessage(locale = "de", value = "Bed(?:ingung)?")})
+ String ALERT_CONDITION_PATTERN = "alert.condition.pattern";
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java
index b6fcf14..131db7d 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java
@@ -19,40 +19,44 @@ 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);
- assert "Availability goes UP".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_UP);
pretty = getShortPrettyAlertConditionString(condition);
- assert "Avail goes UP".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_UP_SHORT);
condition = createCondition(AlertConditionCategory.AVAILABILITY, AlertConditionOperator.AVAIL_GOES_DOWN.name(),
null, null, null, null);
pretty = getPrettyAlertConditionString(condition);
- assert "Availability goes DOWN".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_DOWN);
pretty = getShortPrettyAlertConditionString(condition);
- assert "Avail goes DOWN".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_DOWN_SHORT);
condition = createCondition(AlertConditionCategory.AVAILABILITY,
AlertConditionOperator.AVAIL_GOES_DISABLED.name(), null, null, null, null);
pretty = getPrettyAlertConditionString(condition);
- assert "Availability goes DISABLED".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_DISABLED);
pretty = getShortPrettyAlertConditionString(condition);
- assert "Avail goes DISABLED".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_DISABLED_SHORT);
condition = createCondition(AlertConditionCategory.AVAILABILITY,
AlertConditionOperator.AVAIL_GOES_UNKNOWN.name(), null, null, null, null);
pretty = getPrettyAlertConditionString(condition);
- assert "Availability goes UNKNOWN".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_UNKNOWN);
pretty = getShortPrettyAlertConditionString(condition);
- assert "Avail goes UNKNOWN".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_UNKNOWN_SHORT);
}
@@ -77,9 +81,10 @@ public class AlertManagerBeanTest {
AlertCondition condition = createCondition(AlertConditionCategory.THRESHOLD, md.getDisplayName(), ">", 12.5d,
null, md);
pretty = getPrettyAlertConditionString(condition);
- assert "Foo Prop > 12.5B".equals(pretty) : pretty;
+ String ref = String.format("Foo Prop > %2.1fB",12.5d);
+ assert ref.equals(pretty) : pretty;
pretty = getShortPrettyAlertConditionString(condition);
- assert "Foo Prop > 12.5B".equals(pretty) : pretty;
+ assert ref.equals(pretty) : pretty;
}
public void testPrettyPrintTHRESHOLD_Calltime() {
@@ -88,17 +93,19 @@ public class AlertManagerBeanTest {
AlertCondition condition = createCondition(AlertConditionCategory.THRESHOLD, regex, ">", 12.5d, "MAX", md);
pretty = getPrettyAlertConditionString(condition);
- assert "Calltime Metric CT Prop MAX > 12.5B with calltime destination matching \"some.*(reg)?ex$\""
- .equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_THRESHOLD_WITH_EXPR, "CT Prop", "MAX", ">",
+ TWELVE_DOT_5_B, regex);
pretty = getShortPrettyAlertConditionString(condition);
- assert "CT Prop MAX > 12.5B matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+ 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);
- assert "Calltime Metric CT Prop MAX > 12.5B".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_THRESHOLD,"CT Prop","MAX",">", TWELVE_DOT_5_B);
pretty = getShortPrettyAlertConditionString(condition);
- assert "CT Prop MAX > 12.5B".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_THRESHOLD_SHORT, "CT Prop", "MAX", ">",
+ TWELVE_DOT_5_B);
}
public void testPrettyPrintBASELINE() {
@@ -106,21 +113,21 @@ public class AlertManagerBeanTest {
AlertCondition condition = createCondition(AlertConditionCategory.BASELINE, md.getDisplayName(), ">", 0.10d,
"mean", md);
pretty = getPrettyAlertConditionString(condition);
- assert "Foo Prop > 10.0% of Baseline Mean Value".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_BASELINE_MEAN,"Foo Prop",">", TEN_PERCENT);
pretty = getShortPrettyAlertConditionString(condition);
- assert "Foo Prop > 10.0% bl mean".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_BASELINE_MEAN_SHORT,"Foo Prop",">", TEN_PERCENT);
condition = createCondition(AlertConditionCategory.BASELINE, md.getDisplayName(), ">", 0.10d, "min", md);
pretty = getPrettyAlertConditionString(condition);
- assert "Foo Prop > 10.0% of Baseline Minimum Value".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_BASELINE_MIN,"Foo Prop",">", TEN_PERCENT);
pretty = getShortPrettyAlertConditionString(condition);
- assert "Foo Prop > 10.0% bl min".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_BASELINE_MIN_SHORT,"Foo Prop",">", TEN_PERCENT);
condition = createCondition(AlertConditionCategory.BASELINE, md.getDisplayName(), ">", 0.10d, "max", md);
pretty = getPrettyAlertConditionString(condition);
- assert "Foo Prop > 10.0% of Baseline Maximum Value".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_BASELINE_MAX,"Foo Prop",">", TEN_PERCENT);
pretty = getShortPrettyAlertConditionString(condition);
- assert "Foo Prop > 10.0% bl max".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_BASELINE_MAX_SHORT,"Foo Prop",">", TEN_PERCENT);
}
public void testPrettyPrintCHANGE() {
@@ -128,9 +135,9 @@ public class AlertManagerBeanTest {
AlertCondition condition = createCondition(AlertConditionCategory.CHANGE, md.getDisplayName(), null, null,
null, md);
pretty = getPrettyAlertConditionString(condition);
- assert "Foo Prop Value Changed".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_METRIC_CHANGED, "Foo Prop");
pretty = getShortPrettyAlertConditionString(condition);
- assert "Foo Prop Val Chg".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_METRIC_CHANGED_SHORT, "Foo Prop");
}
public void testPrettyPrintCHANGE_Calltime() {
@@ -139,85 +146,100 @@ public class AlertManagerBeanTest {
AlertCondition condition = createCondition(AlertConditionCategory.CHANGE, regex, "LO", 0.10d, "MIN", md);
pretty = getPrettyAlertConditionString(condition);
- assert "Calltime Metric CT Prop MIN shrinks by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
- .equals(pretty) : pretty;
+ 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 "CT Prop MIN shrinks by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+ 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);
- assert "Calltime Metric CT Prop MIN changes by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
- .equals(pretty) : pretty;
+ msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_CHANGES);
+ assert String.format(ref,msg,10.0f).equals(pretty) ;
pretty = getShortPrettyAlertConditionString(condition);
- assert "CT Prop MIN changes by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+ 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 "Calltime Metric CT Prop MIN grows by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
- .equals(pretty) : pretty;
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
pretty = getShortPrettyAlertConditionString(condition);
- assert "CT Prop MIN grows by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+ 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 "Calltime Metric CT Prop MAX shrinks by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
- .equals(pretty) : pretty;
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
pretty = getShortPrettyAlertConditionString(condition);
- assert "CT Prop MAX shrinks by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+ 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 "Calltime Metric CT Prop MAX changes by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
- .equals(pretty) : pretty;
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
pretty = getShortPrettyAlertConditionString(condition);
- assert "CT Prop MAX changes by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+ 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 "Calltime Metric CT Prop MAX grows by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
- .equals(pretty) : pretty;
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
pretty = getShortPrettyAlertConditionString(condition);
- assert "CT Prop MAX grows by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+ 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 "Calltime Metric CT Prop AVG shrinks by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
- .equals(pretty) : pretty;
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
pretty = getShortPrettyAlertConditionString(condition);
- assert "CT Prop AVG shrinks by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+ 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 "Calltime Metric CT Prop AVG changes by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
- .equals(pretty) : pretty;
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
pretty = getShortPrettyAlertConditionString(condition);
- assert "CT Prop AVG changes by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+ 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 "Calltime Metric CT Prop AVG grows by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
- .equals(pretty) : pretty;
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
pretty = getShortPrettyAlertConditionString(condition);
- assert "CT Prop AVG grows by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+ 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 "Calltime Metric CT Prop AVG shrinks by at least 10.0%".equals(pretty) : pretty;
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
pretty = getShortPrettyAlertConditionString(condition);
- assert "CT Prop AVG shrinks by 10.0%".equals(pretty) : pretty;
+ 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 "Calltime Metric CT Prop AVG changes by at least 10.0%".equals(pretty) : pretty;
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
pretty = getShortPrettyAlertConditionString(condition);
- assert "CT Prop AVG changes by 10.0%".equals(pretty) : pretty;
+ 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 "Calltime Metric CT Prop AVG grows by at least 10.0%".equals(pretty) : pretty;
+ assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
pretty = getShortPrettyAlertConditionString(condition);
- assert "CT Prop AVG grows by 10.0%".equals(pretty) : pretty;
+ assert String.format(refs,msg,10.0f).equals(pretty) : pretty + " \n<=> " +String.format(refs,msg,10.0f);
}
public void testPrettyPrintTRAIT() {
@@ -225,25 +247,25 @@ public class AlertManagerBeanTest {
AlertCondition condition = createCondition(AlertConditionCategory.TRAIT, md.getDisplayName(), null, null, null,
md);
pretty = getPrettyAlertConditionString(condition);
- assert "Blah Trait Value Changed".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_METRIC_CHANGED,"Blah Trait");
pretty = getShortPrettyAlertConditionString(condition);
- assert "Blah Trait Val Chg".equals(pretty) : pretty;
+ 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);
- assert "Operation [opNameHere] has status=[FAILURE]".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_OPERATION,"opNameHere","FAILURE");
pretty = getShortPrettyAlertConditionString(condition);
- assert "Op [opNameHere]=FAILURE".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_OPERATION_SHORT,"opNameHere","FAILURE");
condition = createCondition(AlertConditionCategory.CONTROL, "opNameHere", null, null,
OperationRequestStatus.SUCCESS.name(), null);
pretty = getPrettyAlertConditionString(condition);
- assert "Operation [opNameHere] has status=[SUCCESS]".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_OPERATION,"opNameHere","SUCCESS");
pretty = getShortPrettyAlertConditionString(condition);
- assert "Op [opNameHere]=SUCCESS".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_OPERATION_SHORT,"opNameHere","SUCCESS");
}
public void testPrettyPrintEVENT() {
@@ -303,27 +325,27 @@ public class AlertManagerBeanTest {
AlertCondition condition = createCondition(AlertConditionCategory.RANGE, md.getDisplayName(), "<=", 1.0,
"22.2", md);
pretty = getPrettyAlertConditionString(condition);
- assert "Foo Prop Value is Between 1.0B and 22.2B, Inclusive".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_RANGE_INSIDE_INCL,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
pretty = getShortPrettyAlertConditionString(condition);
- assert "Foo Prop Between 1.0B - 22.2B, incl".equals(pretty) : pretty;
+ 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);
- assert "Foo Prop Value is Outside 1.0B and 22.2B, Inclusive".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_RANGE_OUTSIDE_INCL,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
pretty = getShortPrettyAlertConditionString(condition);
- assert "Foo Prop Outside 1.0B - 22.2B, incl".equals(pretty) : pretty;
+ 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);
- assert "Foo Prop Value is Between 1.0B and 22.2B, Exclusive".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_RANGE_INSIDE_EXCL,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
pretty = getShortPrettyAlertConditionString(condition);
- assert "Foo Prop Between 1.0B - 22.2B, excl".equals(pretty) : pretty;
+ 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);
- assert "Foo Prop Value is Outside 1.0B and 22.2B, Exclusive".equals(pretty) : pretty;
+ check(AlertI18NResourceKeys.ALERT_RANGE_OUTSIDE_EXCL,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
pretty = getShortPrettyAlertConditionString(condition);
- assert "Foo Prop Outside 1.0B - 22.2B, excl".equals(pretty) : pretty;
+ 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) {
@@ -392,10 +414,23 @@ public class AlertManagerBeanTest {
}
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(?:ition)? 1: (.*)\n"); // short form has " - Cond 1: ...", long form has " - Condition 1: ..."
+ 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 + "<<";
+ }
}
commit 4bfd07c96ff3eeca302cb28871d6e7979e9035ec
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Jul 10 18:27:22 2012 +0200
Don't pass the query param in the path.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
index a1645d3..e6f9335 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
@@ -252,7 +252,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
def.getUnits().getName(),def.getDisplayType().toString());
if (def.getDataType()== DataType.MEASUREMENT) {
UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
- uriBuilder.path("/metric/data/group/{groupId}/{definitionId}?hideEmpty=true");
+ uriBuilder.path("/metric/data/group/{groupId}/{definitionId}");
URI uri = uriBuilder.build(id,def.getId());
Link link = new Link("metric",uri.toString());
schedule.addLink(link);
commit 1e102dc66868f2a07d572e56a560e8c60ac93933
Merge: cdd639d fce34e6
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Jul 10 15:16:16 2012 +0200
Merge remote-tracking branch 'origin/master' into lkrejci/modular-scripting
commit fce34e60ab6708ed7fc1d59f76fd78970e950aea
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Jul 10 15:10:16 2012 +0200
BZ 838686 - Provide the server status (OperationMode) to unprivileged users.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java
index a6fce0c..176b72e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java
@@ -23,25 +23,14 @@ import java.util.Map;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
-import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
-import org.rhq.core.domain.alert.Alert;
-import org.rhq.core.domain.alert.AlertDefinition;
-import org.rhq.core.domain.criteria.AlertCriteria;
-import org.rhq.core.domain.criteria.AlertDefinitionCriteria;
-import org.rhq.core.domain.criteria.Criteria;
-import org.rhq.core.domain.criteria.ResourceCriteria;
-import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.resource.ResourceCategory;
-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.MeasurementScheduleManagerLocal;
-import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.core.domain.cloud.Server;
+import org.rhq.enterprise.server.cloud.instance.ServerManagerLocal;
import org.rhq.enterprise.server.rest.domain.Status;
+import org.rhq.enterprise.server.rest.domain.StringValue;
import org.rhq.enterprise.server.system.SystemInfoManagerLocal;
/**
@@ -55,11 +44,13 @@ public class StatusHandlerBean extends AbstractRestBean implements StatusHandler
@EJB
SystemInfoManagerLocal infoMgr;
+ @EJB
+ ServerManagerLocal serverManager;
@Override
public Response getStatus(HttpHeaders httpHeaders) {
- Map<String,String> statusMap = infoMgr.getSystemInformation (caller);
+ Map<String,String> statusMap = infoMgr.getSystemInformation(caller);
Status status = new Status();
status.setValues(statusMap);
@@ -74,4 +65,11 @@ public class StatusHandlerBean extends AbstractRestBean implements StatusHandler
return builder.build();
}
+
+ @Override
+ public StringValue serverState() {
+ Server server = serverManager.getServer();
+ StringValue sv = new StringValue(server.getOperationMode().name());
+ return sv;
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java
index c03244d..f149d8c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java
@@ -31,6 +31,8 @@ import com.wordnik.swagger.annotations.ApiOperation;
import org.jboss.resteasy.annotations.GZIP;
+import org.rhq.enterprise.server.rest.domain.StringValue;
+
/**
* Return some status information about the system
* @author Heiko W. Rupp
@@ -42,9 +44,15 @@ import org.jboss.resteasy.annotations.GZIP;
public interface StatusHandlerLocal {
@GZIP
- @ApiOperation(value="Retrieve the current configured state of the server along with some runtime information",
+ @ApiOperation(value="Retrieve the current configured state of the server along with some runtime information." +
+ "Caller must have MANAGE_SETTINGS to access this endpoint.",
responseClass = "Map 'values' with map of key-value pairs describing the status")
@GET
@Path("/")
Response getStatus(@Context HttpHeaders httpHeaders);
+
+ @GET
+ @Path("/server")
+ @ApiOperation(value = "Get the operation mode of this server")
+ StringValue serverState();
}
commit cdd639d3a1324412aded642a31d8eb4d88c73115
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Jul 10 13:54:35 2012 +0200
Bumping Rhino to 1.7R4.
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index 11f3784..6009b1b 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -21,7 +21,7 @@
<dependency>
<groupId>org.mozilla</groupId>
<artifactId>rhino</artifactId>
- <version>1.7R3</version>
+ <version>1.7R4</version>
</dependency>
</dependencies>
commit 5d58a155a00362b6a5eb4e44ab69471ef577258b
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Jul 10 13:54:23 2012 +0200
Do not compile the scripts to new classes to save the permgen space.
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
index 0456e94..e8069a6 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
@@ -193,12 +193,19 @@ public class RhinoScriptEngine extends AbstractScriptEngine
}
}
+ protected Context makeContext() {
+ Context cx = super.makeContext();
+ cx.setOptimizationLevel(-1);
+ return cx;
+ }
+
private Object superDoTopCall(final Callable callable,
final Context cx, final Scriptable scope,
final Scriptable thisObj, final Object[] args) {
return super.doTopCall(callable, cx, scope, thisObj, args);
- }
+ }
+
});
}
commit 4344f843a8bdd16454def73be245ada673d259b9
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Jul 10 13:53:34 2012 +0200
Setting the require function to NOT be sandboxed (which doesn't make much
difference) and make the require function use the correct scope so that it
can resolve all the variables defined by the script engine.
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
index a2dca22..0456e94 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
@@ -266,7 +266,8 @@ public class RhinoScriptEngine extends AbstractScriptEngine
requireBuilder = new RequireBuilder();
setModuleSourceProvider(moduleSourceProvider);
-
+ requireBuilder.setSandboxed(false);
+
new LazilyLoadedCtor(topLevel, "JSAdapter",
"org.rhq.scripting.javascript.engine.JSAdapter",
false);
@@ -484,7 +485,7 @@ public class RhinoScriptEngine extends AbstractScriptEngine
Context cx = enterContext();
try {
cx.evaluateString(newScope, printSource, "print", 1, null);
- requireBuilder.createRequire(cx, topLevel).install(newScope);
+ requireBuilder.createRequire(cx, newScope).install(newScope);
} finally {
Context.exit();
}
commit 35bad6163b91cc55d2bee67be67f10a6aabdd4bb
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Jul 10 13:51:40 2012 +0200
Adding a script source provider able to handle the "file://" scheme.
This is for the scripts to be able to access the file system using absolute
paths.
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/FileSystemScriptSourceProvider.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/FileSystemScriptSourceProvider.java
new file mode 100644
index 0000000..531222b
--- /dev/null
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/FileSystemScriptSourceProvider.java
@@ -0,0 +1,72 @@
+/*
+ * 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.client.script;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.Reader;
+import java.net.URI;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.scripting.ScriptSourceProvider;
+
+/**
+ * @author Lukas Krejci
+ */
+public class FileSystemScriptSourceProvider implements ScriptSourceProvider {
+
+ private static final Log LOG = LogFactory.getLog(FileSystemScriptSourceProvider.class);
+ private static final String SCHEME = "file";
+
+ @Override
+ public Reader getScriptSource(URI location) {
+ String scheme = location.getScheme();
+
+ //return early if we can't handle this URI
+ if (scheme != null && !SCHEME.equals(scheme)) {
+ return null;
+ }
+
+ String path = location.getSchemeSpecificPart();
+
+ if (scheme != null) {
+ // leave out the leading '//';
+ path = path.substring(2);
+ }
+
+ File f = new File(path);
+
+ try {
+ if (f.exists() && f.isFile() && f.canRead()) {
+ return new FileReader(f);
+ }
+ } catch (FileNotFoundException e) {
+ LOG.debug("File '" + f.getAbsolutePath() + "' seems to have disappeared while we were trying to open it.",
+ e);
+ }
+
+ return null;
+ }
+
+}
diff --git a/modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider b/modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
index 9722a1c..a935c58 100644
--- a/modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
+++ b/modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
@@ -1 +1,2 @@
org.rhq.enterprise.client.script.SamplesScriptSourceProvider
+org.rhq.enterprise.client.script.FileSystemScriptSourceProvider
commit 5f651047a7d1a147de9ec3f3cabcdba195b42483
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Jul 10 13:50:30 2012 +0200
Fixed the method resolution in the abstract rhq facade proxy.
The old impl assumed the simplified class implements the original interface
which is no longer true. I therefore added some auxiliary annotations on
the simplified class and methods to aid in recovering the original method
even though the simplified interface no longer implements the original
interface.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
index bd37131..5a6d1c5 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
@@ -22,7 +22,6 @@ import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import org.rhq.bindings.util.InterfaceSimplifier;
-import org.rhq.core.domain.auth.Subject;
/**
* An abstract {@link InvocationHandler} to help the script users create proxies to actually call the
@@ -50,38 +49,21 @@ public abstract class AbstractRhqFacadeProxy<T extends RhqFacade> implements Inv
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- Class<?>[] interfaces = method.getDeclaringClass().getInterfaces();
- Class<?> originalClass;
- if (interfaces != null && interfaces.length > 0) {
- originalClass = interfaces[0];
- } else {
- originalClass = method.getDeclaringClass();
- }
-
- try {
- // See if this method really exists or if its a simplified set of parameters
- originalClass.getMethod(method.getName(), method.getParameterTypes());
- } catch (NoSuchMethodException e) {
- // If this was not in the original interface it must've been added in the Simplifier... add back the subject argument
- Class<?>[] origParams = method.getParameterTypes();
- Class<?>[] params = new Class<?>[origParams.length + 1];
- params[0] = Subject.class;
- System.arraycopy(method.getParameterTypes(), 0, params, 1, origParams.length);
-
- try {
- method = originalClass.getMethod(method.getName(), params);
- } catch (NoSuchMethodException e2) {
- throw new IllegalArgumentException("Method " + method + " doesn't seem to be present on the interface "
- + originalClass + " neither in its original or simplified form.");
- }
+ Method origMethod = InterfaceSimplifier.getOriginalMethod(method);
+
+ if (origMethod != null) {
+ if (InterfaceSimplifier.isSimplified(method)) {
+ // If this was not in the original interface it must've been added in the Simplifier... add back the subject argument
+ int numArgs = (null == args) ? 0 : args.length;
+ Object[] newArgs = new Object[numArgs + 1];
+ if (numArgs > 0) {
+ System.arraycopy(args, 0, newArgs, 1, numArgs);
+ }
+ newArgs[0] = getRhqFacade().getSubject();
- int numArgs = (null == args) ? 0 : args.length;
- Object[] newArgs = new Object[numArgs + 1];
- if (numArgs > 0) {
- System.arraycopy(args, 0, newArgs, 1, numArgs);
+ args = newArgs;
}
- newArgs[0] = getRhqFacade().getSubject();
- args = newArgs;
+ method = origMethod;
}
return doInvoke(proxy, method, args);
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
index dc07d4e..8ce7bc6 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
@@ -18,6 +18,7 @@
*/
package org.rhq.bindings.util;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
@@ -69,6 +70,77 @@ public class InterfaceSimplifier {
}
+ /**
+ * Returns the method on the original interface that the simplified interface with given method was generated from
+ * using the {@link #simplify(Class)} method (i.e. this method is kind of reverse to the {@link #simplify(Class)}
+ * method).
+ * <p>
+ * The returned method may or may not have different signature from the supplied method - that depends on whether
+ * the {@link #simplify(Class)} simplified the method or not.
+ *
+ * @param method the potentially simplified method
+ * @return null if the method doesn't come from a simplified class, otherwise a method on the original interface
+ * that the supplied method was generated from.
+ */
+ public static Method getOriginalMethod(Method method) {
+ SimplifiedClass simplifiedClass = method.getDeclaringClass().getAnnotation(SimplifiedClass.class);
+ if (simplifiedClass == null) {
+ return null;
+ } else {
+ SimplifiedMethod simplifiedMethod = method.getAnnotation(SimplifiedMethod.class);
+ Class<?> origClass = simplifiedClass.originalClass();
+
+ if (simplifiedMethod == null) {
+ try {
+ return origClass.getMethod(method.getName(), method.getParameterTypes());
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException("Inconsisten interface simplification. The non-simplified method "
+ + method + " should have had a counterpart with the exact signature on the interface "
+ + origClass + " but it could not be found.", e);
+ }
+ } else {
+
+ Class<?>[] paramTypes = new Class<?>[method.getParameterTypes().length + 1];
+ paramTypes[0] = Subject.class;
+ System.arraycopy(method.getParameterTypes(), 0, paramTypes, 1, paramTypes.length - 1);
+
+ try {
+ return origClass.getMethod(method.getName(), paramTypes);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException("Inconsistent interface simplification. The simplified method "
+ + method + " should have had a counterpart on the interface " + origClass
+ + " but it couldn't be found.", e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Determines whether given class is simplified or not. This method will return true for any class returned from
+ * {@link #simplify(Class)}.
+ *
+ * @param cls the class
+ * @return true if the class object was created by the {@link #simplify(Class)} method, false otherwise.
+ */
+ public static boolean isSimplified(Class<?> cls) {
+ return cls.getAnnotation(SimplifiedClass.class) != null;
+ }
+
+ /**
+ * Determines whether the method (declared on the simplified interface, i.e.
+ * <code>isSimplified(method.getDeclaringClass()</code> returns true) has been "tampered with" by the simplifier or
+ * has been left intact.
+ * <p>
+ * If you want to get the original method that the supplied method corresponds to, use
+ * the {@link #getOriginalMethod(Method)} method.
+ *
+ * @param method the potentially simplified method present on a simplified class
+ * @return true if the method's signature has been modified by the simplifier, false otherwise.
+ */
+ public static boolean isSimplified(Method method) {
+ return method.getAnnotation(SimplifiedMethod.class) != null;
+ }
+
public static Class<?> simplify(Class<?> intf) {
try {
ClassPool classPool = ClassPool.getDefault();
@@ -107,9 +179,10 @@ public class InterfaceSimplifier {
AnnotationsAttribute annotations = (AnnotationsAttribute) originalClassFile
.getAttribute(AnnotationsAttribute.visibleTag);
AnnotationsAttribute newAnnotations = copyAnnotations(annotations, constPool);
- if (newAnnotations != null) {
- newClassFile.addAttribute(newAnnotations);
- }
+
+ //add our @Simplified annotation to the new class
+ newAnnotations = addSimplifiedClassAnnotation(originalClass.getName(), newAnnotations, constPool);
+ newClassFile.addAttribute(newAnnotations);
//copy the generic signature of the class
SignatureAttribute signature = (SignatureAttribute) originalClassFile.getAttribute(SignatureAttribute.tag);
@@ -160,6 +233,9 @@ public class InterfaceSimplifier {
annotations = copyAnnotations(annotations, constPool);
if (simplify) {
+ //add the @SimplifiedMethod to the method annotations
+ annotations = addSimplifiedMethodAnnotation(annotations, constPool);
+
if (signature != null) {
//fun, we need to modify the signature, too, because we have left out the parameter
MethodSignature sig = MethodSignature.parse(signature.getSignature());
@@ -475,4 +551,31 @@ public class InterfaceSimplifier {
return bld.toString();
}
}
+
+ private static AnnotationsAttribute addSimplifiedClassAnnotation(String originalClassName,
+ AnnotationsAttribute annotations, ConstPool constPool) {
+
+ if (annotations == null) {
+ annotations = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
+ }
+
+ Annotation simplified = new Annotation(SimplifiedClass.class.getName(), constPool);
+ simplified.addMemberValue("originalClass", new ClassMemberValue(originalClassName, constPool));
+
+ annotations.addAnnotation(simplified);
+
+ return annotations;
+ }
+
+ private static AnnotationsAttribute addSimplifiedMethodAnnotation(AnnotationsAttribute annotations,
+ ConstPool constPool) {
+
+ if (annotations == null) {
+ annotations = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
+ }
+
+ annotations.addAnnotation(new Annotation(SimplifiedMethod.class.getName(), constPool));
+
+ return annotations;
+ }
}
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedClass.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedClass.java
new file mode 100644
index 0000000..50edede
--- /dev/null
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedClass.java
@@ -0,0 +1,38 @@
+/*
+ * 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.bindings.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to keep track of the original class on the simplified classes.
+ * Used by the {@link InterfaceSimplifier}.
+ *
+ * @author Lukas Krejci
+ */
+(a)Retention(RetentionPolicy.RUNTIME)
+(a)Target(ElementType.TYPE)
+public @interface SimplifiedClass {
+ Class<?> originalClass();
+}
\ No newline at end of file
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedMethod.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedMethod.java
new file mode 100644
index 0000000..290b807
--- /dev/null
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedMethod.java
@@ -0,0 +1,41 @@
+/*
+ * 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.bindings.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates a method on a simplified class as being simplified.
+ * This is to distinguish the simplified methods on a simplified class
+ * from the non-simplified methods on that class.
+ * <p>
+ * Used by the {@link InterfaceSimplifier}.
+ *
+ * @author Lukas Krejci
+ */
+(a)Retention(RetentionPolicy.RUNTIME)
+(a)Target(ElementType.METHOD)
+public @interface SimplifiedMethod {
+
+}
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/client/AbstractRhqFacadeProxyTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/client/AbstractRhqFacadeProxyTest.java
new file mode 100644
index 0000000..d1042df
--- /dev/null
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/client/AbstractRhqFacadeProxyTest.java
@@ -0,0 +1,185 @@
+/*
+ * 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.bindings.client;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.rhq.bindings.util.InterfaceSimplifier;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.enterprise.server.resource.ResourceManagerRemote;
+
+/**
+ * @author Lukas Krejci
+ */
+@Test
+public class AbstractRhqFacadeProxyTest {
+
+ public interface TestInterface {
+ void method();
+ }
+
+ public static class TestFacade implements RhqFacade {
+
+ private Subject subject;
+
+ @Override
+ public Subject getSubject() {
+ return subject;
+ }
+
+ public void setSubject(Subject subject) {
+ this.subject = subject;
+ }
+
+ @Override
+ public Subject login(String user, String password) throws Exception {
+ return subject;
+ }
+
+ @Override
+ public void logout() {
+ subject = null;
+ }
+
+ @Override
+ public boolean isLoggedIn() {
+ return subject != null;
+ }
+
+ @Override
+ public Map<RhqManager, Object> getScriptingAPI() {
+ EnumMap<RhqManager, Object> ret = new EnumMap<RhqManager, Object>(RhqManager.class);
+
+ for (RhqManager m : RhqManager.values()) {
+ Class<?> iface = InterfaceSimplifier.simplify(m.remote());
+ Object proxy = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class<?>[] { iface },
+ new TestProxy(this, m));
+ ret.put(m, proxy);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public <T> T getProxy(Class<T> remoteApiIface) {
+ RhqManager m = RhqManager.forInterface(remoteApiIface);
+ if (m == null) {
+ throw new IllegalArgumentException();
+ }
+
+ return remoteApiIface.cast(Proxy.newProxyInstance(this.getClass().getClassLoader(),
+ new Class<?>[] { remoteApiIface }, new TestProxy(this, m)));
+ }
+
+ }
+
+ public static class InvocationRecord {
+ public Method method;
+ public Object[] args;
+ }
+
+ public static class TestProxy extends AbstractRhqFacadeProxy<TestFacade> {
+
+ private static List<InvocationRecord> pastInvocations = new ArrayList<InvocationRecord>();
+
+ /**
+ * @param facade
+ * @param manager
+ */
+ public TestProxy(TestFacade facade, RhqManager manager) {
+ super(facade, manager);
+ }
+
+ @Override
+ protected Object doInvoke(Object proxy, Method originalMethod, Object[] args) throws Throwable {
+ InvocationRecord inv = new InvocationRecord();
+ inv.method = originalMethod;
+ inv.args = args;
+
+ pastInvocations.add(inv);
+
+ return null;
+ }
+
+ public static List<InvocationRecord> getPastInvocations() {
+ return pastInvocations;
+ }
+
+ public static void clearPastInvocations() {
+ pastInvocations.clear();
+ }
+ }
+
+ public void testInvocationOfSimplifiedMethods() throws Exception {
+ TestProxy.clearPastInvocations();
+
+ TestFacade facade = new TestFacade();
+ Subject subject = new Subject();
+
+ facade.setSubject(subject);
+
+ Object resourceManager = facade.getScriptingAPI().get(RhqManager.ResourceManager);
+
+ Method getResource = resourceManager.getClass().getMethod("getResource", int.class);
+
+ getResource.invoke(resourceManager, 1);
+
+ Assert.assertEquals(TestProxy.getPastInvocations().size(), 1, "Unexpected number of proxy invocations");
+
+ InvocationRecord inv = TestProxy.getPastInvocations().get(0);
+
+ Assert.assertEquals(inv.method, ResourceManagerRemote.class.getMethod("getResource", Subject.class, int.class),
+ "Unexpected method invoked.");
+
+ Assert.assertEquals(subject, inv.args[0], "Unexpected subject passed to the invocation.");
+ Assert.assertEquals(inv.args[1], new Integer(1), "Unexpected resource id passed to the invocation.");
+ }
+
+ public void testProxyRobustAgainstNonSimplifiedMethods() throws Exception {
+ TestProxy.clearPastInvocations();
+
+ Class<?> iface = InterfaceSimplifier.simplify(TestInterface.class);
+
+ Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] { iface },
+ new TestProxy(null, null));
+
+ Method charAt = proxy.getClass().getMethod("method");
+
+ charAt.invoke(proxy);
+
+ Assert.assertEquals(TestProxy.getPastInvocations().size(), 1, "Unexpected number of proxy invocations");
+
+ InvocationRecord inv = TestProxy.getPastInvocations().get(0);
+
+ Assert.assertEquals(inv.method, TestInterface.class.getMethod("method"),
+ "Unexpected method invoked.");
+
+ Assert.assertNull(inv.args, "Unexpected number of arguments passed to the invocation.");
+ }
+}
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java
index 4312153..8c581ce 100644
--- a/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java
@@ -243,7 +243,9 @@ public class InterfaceSimplifierTest {
Class<?> iface = InterfaceSimplifier.simplify(Annotations.class);
Annotation[] annotations = iface.getAnnotations();
- Assert.assertEquals(annotations.length, 1, "UNexpected number of annotations on the 'Annotations' class.");
+ //we add the @SimplifiedClass annotation
+ Assert.assertEquals(annotations.length, Annotations.class.getAnnotations().length + 1,
+ "Unexpected number of annotations on the 'Annotations' class.");
Annotation annotation = annotations[0];
Assert.assertEquals(annotation.annotationType(), MyAnnotation.class,
"Unexpected annotation type on the class 'Annotations");
@@ -284,8 +286,9 @@ public class InterfaceSimplifierTest {
method = iface.getMethod("methodSimplified", int.class);
annotations = method.getAnnotations();
+ //we add the @SimplifiedMethod on the method
Assert
- .assertEquals(annotations.length, 1, "Unexpected number of annotations on the 'methodSimplified' method.");
+ .assertEquals(annotations.length, 2, "Unexpected number of annotations on the 'methodSimplified' method.");
annotation = annotations[0];
Assert.assertEquals(annotation.annotationType(), MyAnnotation.class,
@@ -314,4 +317,35 @@ public class InterfaceSimplifierTest {
.assertEquals(((MyAnnotation) annotation).parameter(), "d",
"Unexpected value of the 'parameter' of the annotation on the parameter p of 'Annotations.methodSimplified(int)'.");
}
+
+ public void testOriginalMethodRetrieval() throws Exception {
+ Class<?> iface = InterfaceSimplifier.simplify(Generics.class);
+
+ Method simplifiedMethod = iface.getMethod("typeParametersSimplified", Type.class, int.class);
+ Method origMethod = InterfaceSimplifier.getOriginalMethod(simplifiedMethod);
+
+ Assert.assertTrue(InterfaceSimplifier.isSimplified(iface),
+ "Unable to determine that the simplified interface was simplified.");
+ Assert.assertTrue(InterfaceSimplifier.isSimplified(simplifiedMethod));
+ Assert.assertFalse(InterfaceSimplifier.isSimplified(String.class), "String class is NOT simplified.");
+ Assert.assertFalse(InterfaceSimplifier.isSimplified(Object.class.getMethod("toString")),
+ "Object.toString() is NOT simplified.");
+
+ Assert.assertEquals(origMethod.getDeclaringClass(), Generics.class,
+ "Unexpected declaring class of the original method.");
+ Assert.assertEquals(origMethod.getParameterTypes().length, simplifiedMethod.getParameterTypes().length + 1,
+ "Unexpected number of params on the original method.");
+ Assert.assertEquals(origMethod.getParameterTypes()[0], Subject.class,
+ "Unexpected first param of the original method.");
+
+ Method nonSimplifiedMethod = iface.getMethod("typeParameters", Type.class, int.class);
+ origMethod = InterfaceSimplifier.getOriginalMethod(nonSimplifiedMethod);
+
+ Assert.assertFalse(InterfaceSimplifier.isSimplified(nonSimplifiedMethod));
+
+ Assert.assertEquals(origMethod.getDeclaringClass(), Generics.class,
+ "Unexpected declaring class of the original method.");
+ Assert.assertEquals(origMethod.getParameterTypes(), nonSimplifiedMethod.getParameterTypes(),
+ "Unexpected params on the original method.");
+ }
}
commit 12b6a37abf5be2f7dc0541563e70a8fe94590a08
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Jul 10 12:33:58 2012 +0200
Support metrics for compatible groups.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 79012a1..615ba6c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -55,7 +55,10 @@ import org.jboss.cache.TreeCacheMBean;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.resource.group.GroupCategory;
+import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.ResourceWithType;
@@ -78,6 +81,8 @@ public class AbstractRestBean {
TreeCacheMBean treeCache;
@EJB
ResourceManagerLocal resMgr;
+ @EJB
+ ResourceGroupManagerLocal resourceGroupManager;
/**
* Renders the passed object with the help of a freemarker template into a string. Freemarket templates
@@ -397,4 +402,26 @@ public class AbstractRestBean {
*/
return res;
}
+
+ /**
+ * Fetch the group with the passed id
+ *
+ * @param groupId id of the resource group
+ * @param requireCompatible Does the group have to be a compatible group?
+ * @return the group object if found
+ * @throws org.rhq.enterprise.server.rest.StuffNotFoundException if the group is not found (or not accessible by the caller)
+ * @throws IllegalArgumentException if a compatible group is required, but the found one is not a compatible one
+ */
+ protected ResourceGroup fetchGroup(int groupId, boolean requireCompatible) {
+ ResourceGroup resourceGroup;
+ resourceGroup = resourceGroupManager.getResourceGroup(caller, groupId);
+ if (resourceGroup == null)
+ throw new StuffNotFoundException("Group with id " + groupId);
+ if (requireCompatible) {
+ if (resourceGroup.getGroupCategory() != GroupCategory.COMPATIBLE) {
+ throw new IllegalArgumentException("Group with id " + groupId + " is no compatible group");
+ }
+ }
+ return resourceGroup;
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
index 5fa0089..a1645d3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
@@ -22,6 +22,8 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.criteria.ResourceGroupCriteria;
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.GroupDefinition;
@@ -32,7 +34,6 @@ import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
import org.rhq.enterprise.server.resource.ResourceTypeNotFoundException;
import org.rhq.enterprise.server.resource.group.ResourceGroupDeleteException;
-import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.resource.group.definition.GroupDefinitionManagerLocal;
import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionAlreadyExistsException;
import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionCreateException;
@@ -41,6 +42,7 @@ import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefini
import org.rhq.enterprise.server.rest.domain.GroupDefinitionRest;
import org.rhq.enterprise.server.rest.domain.GroupRest;
import org.rhq.enterprise.server.rest.domain.Link;
+import org.rhq.enterprise.server.rest.domain.MetricSchedule;
import org.rhq.enterprise.server.rest.domain.ResourceWithType;
/**
@@ -54,9 +56,6 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
private final Log log = LogFactory.getLog(GroupHandlerBean.class);
@EJB
- ResourceGroupManagerLocal resourceGroupManager;
-
- @EJB
ResourceManagerLocal resourceManager;
@EJB
@@ -94,7 +93,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
public Response getGroup(int id, @Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo) {
- ResourceGroup group = fetchGroup(id);
+ ResourceGroup group = fetchGroup(id, false);
GroupRest groupRest = fillGroup(group, uriInfo);
@@ -149,7 +148,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
@Context HttpHeaders headers,
@Context UriInfo uriInfo) {
- ResourceGroup resourceGroup = fetchGroup(id);
+ ResourceGroup resourceGroup = fetchGroup(id, false);
resourceGroup.setName(in.getName());
Response.ResponseBuilder builder;
@@ -182,7 +181,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
public Response getResources(int id, @Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo) {
- ResourceGroup resourceGroup = fetchGroup(id);
+ ResourceGroup resourceGroup = fetchGroup(id, false);
Set<Resource> resources = resourceGroup.getExplicitResources();
List<ResourceWithType> rwtList = new ArrayList<ResourceWithType>(resources.size());
@@ -208,7 +207,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
public Response addResource(int id, int resourceId,
@Context Request request, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
- ResourceGroup resourceGroup = fetchGroup(id);
+ ResourceGroup resourceGroup = fetchGroup(id, false);
Resource res = resourceManager.getResource(caller,resourceId);
if (res==null)
throw new StuffNotFoundException("Resource with id " + resourceId);
@@ -230,7 +229,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
public Response removeResource(int id, int resourceId,
@Context Request request, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
- ResourceGroup resourceGroup = fetchGroup(id);
+ ResourceGroup resourceGroup = fetchGroup(id, false);
Resource res = resourceManager.getResource(caller,resourceId);
if (res==null)
throw new StuffNotFoundException("Resource with id " + resourceId);
@@ -241,21 +240,38 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
}
- /**
- * Fetch the group with the passed id
- * @param groupId id of the resource group
- * @return the group object if found
- * @throws StuffNotFoundException if the group is not found (or not accessible by the caller)
- */
- private ResourceGroup fetchGroup(int groupId) {
- ResourceGroup resourceGroup;
- resourceGroup = resourceGroupManager.getResourceGroup(caller, groupId);
- if (resourceGroup==null)
- throw new StuffNotFoundException("Group with id " + groupId);
- return resourceGroup;
- }
+ @Override
+ public Response getMetricDefinitionsForGroup(int id, Request request, HttpHeaders headers,
+ UriInfo uriInfo) {
+ ResourceGroup group = fetchGroup(id, true);
+
+ Set<MeasurementDefinition> definitions = group.getResourceType().getMetricDefinitions();
+ List<MetricSchedule> schedules = new ArrayList<MetricSchedule>(definitions.size());
+ for (MeasurementDefinition def : definitions) {
+ MetricSchedule schedule = new MetricSchedule(def.getId(),def.getName(),def.getDisplayName(),false,def.getDefaultInterval(),
+ def.getUnits().getName(),def.getDisplayType().toString());
+ if (def.getDataType()== DataType.MEASUREMENT) {
+ UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/metric/data/group/{groupId}/{definitionId}?hideEmpty=true");
+ URI uri = uriBuilder.build(id,def.getId());
+ Link link = new Link("metric",uri.toString());
+ schedule.addLink(link);
+ }
+ schedules.add(schedule);
+ }
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+ Response.ResponseBuilder builder;
+ if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+ builder = Response.ok(renderTemplate("listMetricDefinitions",schedules));
+ }
+ else {
+ GenericEntity<List<MetricSchedule>> ret = new GenericEntity<List<MetricSchedule>>(schedules) {};
+ builder = Response.ok(ret);
+ }
+ return builder.build();
+ }
private GroupRest fillGroup(ResourceGroup group, UriInfo uriInfo) {
@@ -270,10 +286,15 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
uriBuilder.path("/group/{id}");
URI uri = uriBuilder.build(group.getId());
-
Link link = new Link("edit",uri.toASCIIString());
gr.getLinks().add(link);
+ uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/group/{id}/metricDefinitions");
+ uri = uriBuilder.build(group.getId());
+ link = new Link("metricDefinitions",uri.toASCIIString());
+ gr.getLinks().add(link);
+
return gr;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java
index ac77cce..39e0c2a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java
@@ -57,6 +57,14 @@ public interface GroupHandlerLocal {
@Context UriInfo uriInfo);
+ @GET
+ @GZIP
+ @Path("{id}/metricDefinitions")
+ @ApiOperation(value = "Get the metric definitions for the compatible group with the passed id")
+ public Response getMetricDefinitionsForGroup(@ApiParam(value = "Id of the group") @PathParam("id") int id,
+ @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
+
@POST
@Path("/")
@ApiOperation(value = "Create a new group")
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
index 7c664b7..163d48d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
@@ -71,10 +71,13 @@ 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.composite.MeasurementDataNumericHighLowComposite;
+import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.util.jdbc.JDBCUtil;
import org.rhq.enterprise.server.RHQConstants;
+import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerLocal;
import org.rhq.enterprise.server.measurement.util.MeasurementDataManagerUtility;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.rest.domain.Baseline;
import org.rhq.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.MetricAggregate;
@@ -99,7 +102,11 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
@EJB
MeasurementScheduleManagerLocal scheduleManager;
@EJB
+ MeasurementDefinitionManagerLocal definitionManager;
+ @EJB
ResourceManagerLocal resMgr;
+ @EJB
+ ResourceGroupManagerLocal groupMgr;
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
EntityManager em;
@@ -158,6 +165,56 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
return builder.build();
}
+ public Response getMetricDataForGroupAndDefinition(int groupId, int definitionId, long startTime, long endTime,
+ boolean hideEmpty, Request request, HttpHeaders headers) {
+
+ if (startTime==0) {
+ endTime = System.currentTimeMillis();
+ startTime = endTime - EIGHT_HOURS;
+ }
+
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+ boolean isHtml = mediaType.equals(MediaType.TEXT_HTML_TYPE);
+
+ fetchGroup(groupId,true); // Make sure the group exists and is compatible
+ MeasurementDefinition definition = definitionManager.getMeasurementDefinition(caller,definitionId);
+ if (definition==null) {
+ throw new StuffNotFoundException("There is no definition with id " + definitionId);
+ }
+
+ MeasurementAggregate aggr = dataManager.getAggregate(caller, groupId, definitionId, startTime, endTime);
+ MetricAggregate res = new MetricAggregate(definitionId, aggr.getMin(),aggr.getAvg(),aggr.getMax());
+ res.setGroup(true);
+
+ List<List<MeasurementDataNumericHighLowComposite>> listList = dataManager.findDataForCompatibleGroup(caller,
+ groupId,definitionId,startTime,endTime,60); // TODO number of points
+
+ if (listList.isEmpty()) {
+ throw new StuffNotFoundException("Data for group with id " + groupId + " and definition " + definitionId);
+ }
+ List<MeasurementDataNumericHighLowComposite> list = listList.get(0);
+ if (!listList.isEmpty()) {
+ fill(res, list,definitionId,hideEmpty,isHtml);
+ }
+
+ CacheControl cc = new CacheControl();
+ int maxAge = (int) (definition.getDefaultInterval() / 1000L)/2; // millis ; half of schedule interval
+ cc.setMaxAge(maxAge); // these are seconds
+ cc.setPrivate(false);
+ cc.setNoCache(false);
+
+ Response.ResponseBuilder builder;
+ if (isHtml) {
+ String htmlString = renderTemplate("metricData", res);
+ builder = Response.ok(htmlString,mediaType);
+ }
+ else
+ builder= Response.ok(res,mediaType);
+ builder.cacheControl(cc);
+
+ return builder.build();
+ }
+
/**
* Get the schedule for the passed schedule id
*
@@ -419,6 +476,30 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
}
@Override
+ public List<MetricAggregate> getAggregatesForGroup(int groupId, long startTime, long endTime) {
+ long now = System.currentTimeMillis();
+ if (endTime==0)
+ endTime = now;
+ if (startTime==0) {
+ startTime = endTime - EIGHT_HOURS;
+ }
+ ResourceGroup group = fetchGroup(groupId, true);
+
+ Set<MeasurementDefinition> definitions = group.getResourceType().getMetricDefinitions();
+
+ List<MetricAggregate> ret = new ArrayList<MetricAggregate>(definitions.size());
+ for (MeasurementDefinition def : definitions) {
+ if (def.getDataType()==DataType.MEASUREMENT) {
+ MeasurementAggregate aggregate = dataManager.getAggregate(caller, groupId, def.getId(), startTime, endTime);
+ MetricAggregate res = new MetricAggregate(def.getId(), aggregate.getMin(),aggregate.getAvg(),aggregate.getMax());
+ res.setGroup(true);
+ ret.add(res);
+ }
+ }
+ return ret;
+ }
+
+ @Override
public Response updateSchedule(int scheduleId, MetricSchedule in,HttpHeaders httpHeaders) {
if (in==null)
throw new StuffNotFoundException("Input is null"); // TODO other type of exception
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
index 8ec3d82..4ea9343 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
@@ -77,7 +77,7 @@ public interface MetricHandlerLocal {
@ApiParam(value="Start time since epoch.", defaultValue = "End time - 8h") @QueryParam("startTime") long startTime,
@ApiParam(value="End time since epoch.", defaultValue = "Now") @QueryParam("endTime") long endTime,
@ApiParam("Number of buckets - currently fixed at 60") @QueryParam("dataPoints") @DefaultValue("60") int dataPoints,
- @QueryParam("hideEmpty") boolean hideEmpty,
+ @ApiParam(value = "Hide rows that are NaN only", defaultValue = "false") @QueryParam("hideEmpty") boolean hideEmpty,
@Context Request request,
@Context HttpHeaders headers);
@@ -98,10 +98,33 @@ public interface MetricHandlerLocal {
@ApiOperation("Retrieve a list of high/low/average/data aggregate for the resource")
@ApiError(code = 404, reason = NO_RESOURCE_FOR_ID)
List<MetricAggregate> getAggregatesForResource(
- @ApiParam("Resource to query") @PathParam("resourceId") int resourceId,
+ @ApiParam("Id of the resource to query") @PathParam("resourceId") int resourceId,
+ @ApiParam(value = "Start time since epoch.", defaultValue="End time - 8h") @QueryParam("startTime") long startTime,
+ @ApiParam(value = "End time since epoch.", defaultValue = "Now") @QueryParam("endTime") long endTime);
+
+ @GET
+ @Path("data/group/{groupId}")
+ @ApiOperation("Retrieve a list of high/low/average/data aggregate for the group")
+ List<MetricAggregate> getAggregatesForGroup(
+ @ApiParam("Id of the group to query") @PathParam("groupId") int groupId,
@ApiParam(value = "Start time since epoch.", defaultValue="End time - 8h") @QueryParam("startTime") long startTime,
@ApiParam(value = "End time since epoch.", defaultValue = "Now") @QueryParam("endTime") long endTime);
+ @GZIP
+ @GET
+ @Path("data/group/{groupId}/{definitionId}")
+ @ApiOperation(value = "Get the bucketized metric values for the metric definition of the group ")
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
+ Response getMetricDataForGroupAndDefinition(
+ @ApiParam("Id of the group to query") @PathParam("groupId") int groupId,
+ @ApiParam("Id of the metric definition to retrieve") @PathParam("definitionId") int definitionId,
+ @ApiParam(value = "Start time since epoch.", defaultValue="End time - 8h") @QueryParam("startTime") long startTime,
+ @ApiParam(value = "End time since epoch.", defaultValue = "Now") @QueryParam("endTime") long endTime,
+ @ApiParam(value = "Hide rows that are NaN only", defaultValue = "false") @QueryParam("hideEmpty") boolean hideEmpty,
+ @Context Request request,
+ @Context HttpHeaders headers);
+
+
/**
* Get information about the schedule
* @param scheduleId id of the schedule
@@ -169,7 +192,7 @@ public interface MetricHandlerLocal {
* @param point Datapoint of class NumericDataPoint
* @param headers Injected HTTP headers
* @param uriInfo Injected info about the uri
- * @return
+ * @return Created response
*/
@PUT
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricAggregate.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricAggregate.java
index 4f17e61..46605cf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricAggregate.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricAggregate.java
@@ -25,7 +25,7 @@ import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
- * Raw data that could be used to draw a chart
+ * Metric data that could be used to draw a chart
* @author Heiko W. Rupp
*/
@XmlRootElement
@@ -39,6 +39,7 @@ public class MetricAggregate {
List<DataPoint> dataPoints;
long minTimeStamp;
long maxTimeStamp;
+ boolean isGroup = false;
public MetricAggregate() {
dataPoints = new ArrayList<DataPoint>();
@@ -127,6 +128,14 @@ public class MetricAggregate {
this.maxTimeStamp = maxTimeStamp;
}
+ public boolean isGroup() {
+ return isGroup;
+ }
+
+ public void setGroup(boolean group) {
+ isGroup = group;
+ }
+
public static class DataPoint {
long timeStamp;
Double value;
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl
index 03a69bb..c88c072 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl
@@ -31,7 +31,7 @@
<td>Name</td><td>${var.name}</td>
</tr>
<tr>
- <td>Id</td><td>${var.id}</td>
+ <td>Id</td><td>${var.id?c}</td>
</tr>
<tr>
<td>Category</td><td>${var.category}</td>
@@ -57,4 +57,10 @@
</tr>
</table>
<a href="/rest/1/group/${var.id?c}/resources.html">Resources</a><br/>
+ <#if (var.category?contains("compatible"))>
+ <a href="/rest/1/group/${var.id?c}/metricDefinitions.html">Metric Definitions</a><br/>
+ </#if>
+ <#if (var.dynaGroupDefinitionId >0)>
+ <a href="/rest/1/group/definition/${var.dynaGroupDefinitionId?c}.html">DynaGroup definition</a>
+ </#if>
</html>
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/listMetricDefinitions.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/listMetricDefinitions.ftl
new file mode 100644
index 0000000..5c87d5f
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/listMetricDefinitions.ftl
@@ -0,0 +1,38 @@
+<#ftl >
+<#--
+/*
+ * 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.
+ */
+-->
+<#-- @ftlvariable name="var" type="java.util.List<org.rhq.enterprise.server.rest.domain.MetricSchedule>" -->
+<html>
+<#if (var?size>0) >
+<ul>
+ <#-- the next looks odd, but the incoming var is a list -->
+
+ <#list var as var>
+ <li>
+ <#include "metricDefinition.ftl"/>
+ </li>
+ </#list>
+
+</ul>
+<#else>
+ <strong>No Schedules have been set up</strong>
+</#if>
+<html>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/metricData.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/metricData.ftl
index fdf2f88..61c9280 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/metricData.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/metricData.ftl
@@ -33,7 +33,13 @@
</thead>
<tr>
<#assign sched=var.scheduleId/>
- <td>ScheduleId</td><td><a href="/rest/1/metric/schedule/${sched?c}.html">${sched?c}</a></td> </tr>
+ <#if var.isGroup()>
+ <td>DefinitionId</td><td>${sched?c}</a></td>
+ <#else>
+ <td>ScheduleId</td><td><a href="/rest/1/metric/schedule/${sched?c}.html">${sched?c}</a></td>
+ </#if>
+ </tr>
+
<tr>
<td>Min</td><td>
<#if var.min?has_content>
@@ -64,7 +70,9 @@
</td>
</tr>
<tr>
- <td><a align="top" href="javascript:rhq.whisker(${sched?c},'one',400,200)">DataPoints</a></td><td>
+ <#if !var.isGroup()>
+ <td><a align="top" href="javascript:rhq.whisker(${sched?c},'one',400,200)">DataPoints</a></td><td>
+ </#if>
<table>
<thead>
<tr>
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/metricDefinition.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/metricDefinition.ftl
new file mode 100644
index 0000000..df277e1
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/metricDefinition.ftl
@@ -0,0 +1,52 @@
+<#ftl >
+<#--
+/*
+ * 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.
+ */
+-->
+<#-- @ftlvariable name="var" type="org.rhq.enterprise.server.rest.domain.MetricSchedule" -->
+<html>
+ <table border=1>
+ <tr>
+ <th>Name</th><th>Value</th>
+ </tr>
+ <tr>
+ <td>Id</td><td>${var.scheduleId}</td>
+ </tr>
+ <tr>
+ <td>Internal Name</td><td>${var.scheduleName}</td>
+ </tr>
+ <tr>
+ <td>Name</td><td>${var.displayName}</td>
+ </tr>
+ <tr>
+ <td>Default collection interval (ms)</td><td>${var.collectionInterval}</td>
+ </tr>
+ <tr>
+ <td>Units</td><td>${var.unit}</td>
+ </tr>
+ <tr>
+ <td>Links</td>
+ <td>
+ <#list var.links as link>
+ <li><a href="${link.href}.html">${link.rel}</a> </li>
+ </#list>
+ </td>
+ </tr>
+ </table>
+</html>
\ No newline at end of file
commit 5d33eb1fcb0114ebce98c834bc7e54e89f03eb8c
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Jul 9 08:17:09 2012 -0700
Add GZIP compression to REST reports.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java
index f42c190..d106ed6 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java
@@ -7,12 +7,14 @@ import javax.ws.rs.core.*;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
+import org.jboss.resteasy.annotations.GZIP;
@Path("/alertDefinitions")
@Local
@Api(basePath="http://localhost:7080/coregui/reports", value = "The Alert definitions report")
public interface AlertDefinitionLocal {
+ @GZIP
@GET
@Produces({"text/csv"})
@ApiOperation(value = "Export the AlertDefinitions in the system")
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java
index 1eb4d38..00079e7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java
@@ -9,12 +9,14 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import org.jboss.resteasy.annotations.GZIP;
@Path("/configurationHistory")
@Local
@Api(basePath="http://localhost:7080/coregui/reports", value = "The configuration history report")
public interface ConfigurationHistoryLocal {
+ @GZIP
@GET
@Produces({"text/csv"})
StreamingOutput configurationHistory(@Context HttpServletRequest request);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java
index f9dbed3..f3da333 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java
@@ -28,12 +28,14 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import org.jboss.resteasy.annotations.GZIP;
@Path("/driftCompliance")
@Local
@Api(basePath="http://localhost:7080/coregui/reports", value = "The drift compliance report")
public interface DriftComplianceLocal {
+ @GZIP
@GET
@Produces({"text/csv", "application/xml"})
StreamingOutput generateReport(
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java
index 4f09b7e..43f2ee1 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java
@@ -28,6 +28,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import org.jboss.resteasy.annotations.GZIP;
@Path("/inventorySummary")
@Local
@@ -45,6 +46,7 @@ public interface InventorySummaryLocal {
* specified to generate the details version of the report.
* @return An output stream that contains the CSV report.
*/
+ @GZIP
@GET
@Produces({"text/csv"})
StreamingOutput generateReport(
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java
index cfda23a..7ee299a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java
@@ -30,12 +30,14 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import org.jboss.resteasy.annotations.GZIP;
@Path("/platformUtilization")
@Local
@Api(basePath="http://localhost:7080/coregui/reports", value = "The platform utilization report")
public interface PlatformUtilizationLocal {
+ @GZIP
@GET
@Produces({"text/csv"})
StreamingOutput generateReport(@Context HttpServletRequest request);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java
index 6efe5b2..606be2b 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java
@@ -11,12 +11,14 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import org.jboss.resteasy.annotations.GZIP;
@Path("/recentAlerts")
@Local
@Api(basePath="http://localhost:7080/coregui/reports", value = "The recent alerts report")
public interface RecentAlertLocal {
+ @GZIP
@GET
@Produces({"text/csv"})
StreamingOutput recentAlerts(
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java
index ec161b0..187ad1d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java
@@ -11,12 +11,14 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import org.jboss.resteasy.annotations.GZIP;
@Path("/recentOperations")
@Local
@Api(basePath="http://localhost:7080/coregui/reports", value = "The recent operations report")
public interface RecentOperationsLocal {
+ @GZIP
@GET
@Produces({"text/csv"})
StreamingOutput recentOperations(
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java
index 78ab8a1..217920f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java
@@ -9,12 +9,14 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import com.wordnik.swagger.annotations.Api;
+import org.jboss.resteasy.annotations.GZIP;
@Path("/suspectMetrics")
@Local
@Api(basePath="http://localhost:7080/coregui/reports", value = "The suspect metrics report")
public interface SuspectMetricLocal {
+ @GZIP
@GET
@Produces("text/csv")
StreamingOutput suspectMetrics(@Context HttpServletRequest request);
commit 34c1b99a067c54c875b83a646c8cf309b32d0d34
Merge: 9287b7e e704b68
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Jul 9 14:53:41 2012 +0200
Merge remote-tracking branch 'origin/master' into lkrejci/modular-scripting
commit 9287b7e475adc4a182270624913b7cc926ff0664
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Jul 9 14:50:00 2012 +0200
Improvements to javascript code completion - we now are able to complete
the properties/functions of native javascript objects. This makes
code completion on required modules return the defined functions.
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 f90969a..d4d68bc 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
@@ -20,6 +20,7 @@
package org.rhq.scripting.javascript;
import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
@@ -28,6 +29,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -40,6 +42,8 @@ import javax.script.ScriptContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.ScriptableObject;
import org.rhq.scripting.CodeCompletion;
import org.rhq.scripting.MetadataProvider;
@@ -231,8 +235,10 @@ public class JavascriptCompletor implements CodeCompletion {
}
if (matches.size() == 1 && matches.containsKey(call[0])) {
- if (matches.get(call[0]).get(0) instanceof Method) {
- list.add("(" + (((Method) matches.get(call[0]).get(0)).getParameterTypes().length == 0 ? ")" : ""));
+ Object obj = matches.get(call[0]).get(0);
+ if (isMethod(obj)) {
+ boolean close = obj instanceof Method && ((Method) obj).getParameterTypes().length == 0;
+ list.add("(" + (close ? ")" : ""));
}
return call[0].length() + 1;
}
@@ -446,53 +452,80 @@ public class JavascriptCompletor implements CodeCompletion {
}
try {
- if (baseObjectClass.equals(Void.TYPE))
+ if (baseObjectClass.equals(Void.TYPE)) {
return found;
-
- BeanInfo info = null;
- if (baseObjectClass.isInterface() || baseObjectClass.equals(Object.class)) {
- info = Introspector.getBeanInfo(baseObjectClass);
+ } else if (ScriptableObject.class.isAssignableFrom(baseObjectClass)) {
+ return findJavascriptContextMatches((ScriptableObject) baseObject, start);
} else {
- info = Introspector.getBeanInfo(baseObjectClass, Object.class);
+ return findJavaBeanContextMatches(baseObject, baseObjectClass, start);
}
- Set<Method> methodsCovered = new HashSet<Method>();
+ } catch (Exception e) {
+ LOG.info("Failure during code completion", e);
+ e.printStackTrace(output);
+ }
- PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
- for (PropertyDescriptor desc : descriptors) {
- if (desc.getName().startsWith(start) && (!IGNORED_METHODS.contains(desc.getName()))) {
+ return found;
+ }
- List<Object> list = found.get(desc.getName());
- if (list == null) {
- list = new ArrayList<Object>();
- found.put(desc.getName(), list);
- }
- list.add(desc);
+ private Map<String, List<Object>> findJavascriptContextMatches(ScriptableObject object, String start) {
+ HashMap<String, List<Object>> ret = new HashMap<String, List<Object>>();
+ for (Object o : object.getIds()) {
+ String key = o.toString();
- methodsCovered.add(desc.getReadMethod());
- methodsCovered.add(desc.getWriteMethod());
- }
+ if (start == null || start.isEmpty() || key.startsWith(start)) {
+ Object target = object.get(key);
+ ret.put(key, new ArrayList<Object>(Arrays.asList(target)));
}
+ }
- MethodDescriptor[] methods = info.getMethodDescriptors();
- for (MethodDescriptor desc : methods) {
- if (desc.getName().startsWith(start) && !methodsCovered.contains(desc.getMethod())
- && !desc.getName().startsWith("_d") && !IGNORED_METHODS.contains(desc.getName())) {
+ return ret;
+ }
- Method m = desc.getMethod();
+ private Map<String, List<Object>> findJavaBeanContextMatches(Object baseObject, Class<?> baseObjectClass,
+ String start) throws IntrospectionException {
- List<Object> list = found.get(desc.getName());
- if (list == null) {
- list = new ArrayList<Object>();
- found.put(desc.getName(), list);
- }
- list.add(m);
+ Map<String, List<Object>> found = new HashMap<String, List<Object>>();
+
+ BeanInfo info = null;
+ if (baseObjectClass.isInterface() || baseObjectClass.equals(Object.class)) {
+ info = Introspector.getBeanInfo(baseObjectClass);
+ } else {
+ info = Introspector.getBeanInfo(baseObjectClass, Object.class);
+ }
+
+ Set<Method> methodsCovered = new HashSet<Method>();
+
+ PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
+ for (PropertyDescriptor desc : descriptors) {
+ if (desc.getName().startsWith(start) && (!IGNORED_METHODS.contains(desc.getName()))) {
+
+ List<Object> list = found.get(desc.getName());
+ if (list == null) {
+ list = new ArrayList<Object>();
+ found.put(desc.getName(), list);
}
+ list.add(desc);
+
+ methodsCovered.add(desc.getReadMethod());
+ methodsCovered.add(desc.getWriteMethod());
}
+ }
- } catch (Exception e) {
- LOG.info("Failure during code completion", e);
- e.printStackTrace(output);
+ MethodDescriptor[] methods = info.getMethodDescriptors();
+ for (MethodDescriptor desc : methods) {
+ if (desc.getName().startsWith(start) && !methodsCovered.contains(desc.getMethod())
+ && !desc.getName().startsWith("_d") && !IGNORED_METHODS.contains(desc.getName())) {
+
+ Method m = desc.getMethod();
+
+ List<Object> list = found.get(desc.getName());
+ if (list == null) {
+ list = new ArrayList<Object>();
+ found.put(desc.getName(), list);
+ }
+ list.add(m);
+ }
}
return found;
@@ -546,4 +579,8 @@ public class JavascriptCompletor implements CodeCompletion {
m.setAccessible(access);
}
}
+
+ private static boolean isMethod(Object object) {
+ return object != null && object instanceof Method || object instanceof Function;
+ }
}
commit eb1ade1290dedc3c83ef12f8cdf6531df5433278
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Jul 9 14:42:46 2012 +0200
Make the summary print all the "summary" properties of the object, including the inherited ones from the super classes.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SummaryFilter.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SummaryFilter.java
index 871484f..7015068 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SummaryFilter.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SummaryFilter.java
@@ -22,13 +22,11 @@
*/
package org.rhq.bindings.util;
-import org.rhq.core.domain.util.Summary;
-
import java.beans.BeanInfo;
+import java.beans.IndexedPropertyDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
-import java.beans.IndexedPropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
@@ -36,13 +34,15 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
+import org.rhq.core.domain.util.Summary;
+
public class SummaryFilter {
public PropertyDescriptor[] getPropertyDescriptors(Object object, boolean exportMode) throws IntrospectionException {
- BeanInfo info = Introspector.getBeanInfo(object.getClass(), object.getClass().getSuperclass());
+ BeanInfo info = Introspector.getBeanInfo(object.getClass(), Object.class);
final Map<PropertyDescriptor, Integer> indexes = new HashMap<PropertyDescriptor, Integer>();
commit e704b68d713a9bc956e826880d6fb0a93be322c9
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Jul 9 12:11:27 2012 +0200
BZ 837903 - remove thread ids from configuration and add an operation to retrieve them.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ThreadingComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ThreadingComponent.java
new file mode 100644
index 0000000..9080262
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ThreadingComponent.java
@@ -0,0 +1,61 @@
+/*
+ * 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.modules.plugins.jbossas7;
+
+import java.util.List;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.pluginapi.operation.OperationResult;
+import org.rhq.modules.plugins.jbossas7.json.Operation;
+import org.rhq.modules.plugins.jbossas7.json.ReadAttribute;
+import org.rhq.modules.plugins.jbossas7.json.Result;
+
+/**
+ * Component class for Threading within the runtime
+ * @author Heiko W. Rupp
+ */
+public class ThreadingComponent extends BaseComponent<ThreadingComponent> {
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public OperationResult invokeOperation(String name,
+ Configuration parameters) throws Exception {
+
+ if (name.equals("get-all-thread-ids")) {
+ Operation op = new ReadAttribute(getAddress(), "all-thread-ids");
+ Result res = getASConnection().execute(op);
+ OperationResult operationResult;
+ if (res.isSuccess()) {
+ List<Long> ids = (List<Long>) res.getResult();
+ operationResult = new OperationResult(ids.toString());
+ } else {
+ operationResult = new OperationResult();
+ String errorMessage = "Got no result back";
+ if (!res.isSuccess()) {
+ errorMessage += ": " + res.getFailureDescription();
+ }
+ operationResult.setErrorMessage(errorMessage);
+ }
+ return operationResult;
+ }
+
+ return super.invokeOperation(name, parameters);
+ }
+}
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 e096c0e..77bacfb 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
@@ -7028,7 +7028,7 @@
<service name="Threading"
discovery="SubsystemDiscovery"
- class="BaseComponent">
+ class="ThreadingComponent">
<plugin-configuration>
<c:simple-property name="path" readOnly="true" default="type=threading"/>
@@ -7124,6 +7124,16 @@
</results>
</operation>
+ <operation name="get-all-thread-ids"
+ description="Get all live thread IDs. If a security manager is installed and the caller does not have ManagementPermission('monitor'), the result will be undefined."
+ displayName="Get All thread ids">
+
+ <results>
+ <c:simple-property name="operationResult"
+ description="List of thread ids"/>
+ </results>
+ </operation>
+
<metric property="thread-count" description="The current number of live threads including both daemon and non-daemon threads."/>
<metric property="peak-thread-count" description="The peak live thread count since the Java virtual machine started or peak was reset."/>
<metric property="total-started-thread-count" description="The total number of threads created and also started since the Java virtual machine started."/>
@@ -7133,9 +7143,6 @@
<resource-configuration>
<c:simple-property name="thread-contention-monitoring-enabled" required="false" type="boolean" readOnly="false" description="Whether thread contention monitoring is enabled."/>
<c:simple-property name="thread-cpu-time-enabled" required="false" type="boolean" readOnly="false" description="Whether thread CPU time measurement is enabled."/>
- <c:list-property name="all-thread-ids" description="All live thread IDs. If a security manager is installed and the caller does not have ManagementPermission('monitor'), the result will be undefined." readOnly="true">
- <c:simple-property name="all-thread-ids" readOnly="true"/>
- </c:list-property>
<c:simple-property name="thread-contention-monitoring-supported" required="false" type="boolean" readOnly="true" description="Whether the Java virtual machine supports thread contention monitoring."/>
<c:simple-property name="thread-cpu-time-supported" required="false" type="boolean" readOnly="true" description="Whether the Java virtual machine implementation supports CPU time measurement for any thread."/>
<c:simple-property name="current-thread-cpu-time-supported" required="false" type="boolean" readOnly="true" description="Whether the Java virtual machine supports CPU time measurement for the current thread."/>
commit dba33e0ce637e3e16217027ed25c3c28a5b5ef34
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Sun Jul 8 11:25:55 2012 +0200
Don't fail if a resource has been deleted, but is still listed in favorites.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
index c4bf673..11ac93f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
@@ -41,6 +41,7 @@ import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.resource.Resource;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceNotFoundException;
import org.rhq.enterprise.server.rest.domain.ResourceWithType;
import org.rhq.enterprise.server.rest.domain.UserRest;
@@ -83,10 +84,18 @@ public class UserHandlerBean extends AbstractRestBean implements UserHandlerLoca
MediaType mediaType = httpHeaders.getAcceptableMediaTypes().get(0);
for (Integer id : favIds) {
- Resource res = resourceManager.getResource(caller,id);
+ try {
+ Resource res = resourceManager.getResource(caller,id);
- ResourceWithType rwt = fillRWT(res,uriInfo);
- ret.add(rwt);
+ ResourceWithType rwt = fillRWT(res,uriInfo);
+ ret.add(rwt);
+ }
+ catch (Exception e) {
+ if (e.getCause()!=null && e.getCause() instanceof ResourceNotFoundException)
+ log.debug("Favorite resource with id "+ id + " not found - not returning to the user");
+ else
+ log.warn("Retrieving resource with id " + id + " failed: " + e.getLocalizedMessage());
+ }
}
Response.ResponseBuilder builder;
if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
commit 7329628734f5afc504c90c6b97e5315d8736c6a8
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Sat Jul 7 22:27:02 2012 +0200
Allow more endpoints to return gzip'ed data
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
index 4912ca1..c032481 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
@@ -39,6 +39,7 @@ import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
+import org.jboss.resteasy.annotations.GZIP;
import org.jboss.resteasy.annotations.cache.Cache;
import org.rhq.enterprise.server.rest.domain.AlertRest;
@@ -54,6 +55,7 @@ import org.rhq.enterprise.server.rest.domain.AlertDefinitionRest;
@Api(value = "Deal with Alerts",description = "This api deals with alerts that have fired. It does not offer to create/update AlertDefinitions (yet)")
public interface AlertHandlerLocal {
+ @GZIP
@GET
@Path("/")
@ApiOperation(value = "List all alerts", multiValueResponse = true, responseClass = "List<AlertRest")
@@ -116,6 +118,7 @@ public interface AlertHandlerLocal {
AlertDefinitionRest getDefinitionForAlert(@ApiParam("Id of the alert to show the definition") @PathParam("id") int alertId);
+ @GZIP
@GET
@Path("/definition")
@ApiOperation("List all Alert Definition")
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java
index 87026cd..ac77cce 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java
@@ -24,6 +24,7 @@ import com.wordnik.swagger.annotations.ApiErrors;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
+import org.jboss.resteasy.annotations.GZIP;
import org.jboss.resteasy.annotations.cache.Cache;
import org.rhq.enterprise.server.rest.domain.GroupDefinitionRest;
@@ -39,6 +40,7 @@ import org.rhq.enterprise.server.rest.domain.GroupRest;
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML, "application/yaml"})
public interface GroupHandlerLocal {
+ @GZIP
@GET
@Path("/")
@ApiOperation(value = "List all groups", multiValueResponse = true)
@@ -82,6 +84,7 @@ public interface GroupHandlerLocal {
@Context UriInfo uriInfo);
+ @GZIP
@GET
@Path("{id}/resources")
@Cache(isPrivate = true,maxAge = 60)
@@ -114,12 +117,14 @@ public interface GroupHandlerLocal {
@Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo);
+ @GZIP
@GET
@Path("/definitions")
@ApiOperation(value="List all existing GroupDefinitions",multiValueResponse = true)
public Response getGroupDefinitions(@Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo);
+ @GZIP
@GET
@Path("/definition/{id}")
@Cache(isPrivate = true,maxAge = 60)
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java
index 8cce452..dcf5943 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java
@@ -38,6 +38,7 @@ import javax.ws.rs.core.UriInfo;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
+import org.jboss.resteasy.annotations.GZIP;
import org.jboss.resteasy.annotations.cache.Cache;
import org.rhq.enterprise.server.rest.domain.OperationRest;
@@ -63,6 +64,7 @@ public interface OperationsHandlerLocal {
@Context Request request,
@Context HttpHeaders httpHeaders);
+ @GZIP
@GET
@Path("definitions")
@Cache(maxAge = 1200)
@@ -102,6 +104,7 @@ public interface OperationsHandlerLocal {
public Response cancelOperation(
@ApiParam("Id of the operation to remove") @PathParam("id") int operationId);
+ @GZIP
@GET
@Path("history/{id}")
@ApiOperation("Return the outcome of the scheduled operation")
@@ -112,9 +115,10 @@ public interface OperationsHandlerLocal {
@Context Request request,
@Context HttpHeaders httpHeaders);
+ @GZIP
@GET
@Path("history")
- @ApiOperation("Return the outcome of the scheduled operations")
+ @ApiOperation("Return the outcome of the executed operations for a resource")
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
public Response listHistory(
@ApiParam("Id of a resource to limit to") @QueryParam("resourceId") int resourceId,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java
index cceb213..c03244d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java
@@ -29,6 +29,8 @@ import javax.ws.rs.core.Response;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
+import org.jboss.resteasy.annotations.GZIP;
+
/**
* Return some status information about the system
* @author Heiko W. Rupp
@@ -39,6 +41,7 @@ import com.wordnik.swagger.annotations.ApiOperation;
@Produces({"application/json","application/xml","text/html"})
public interface StatusHandlerLocal {
+ @GZIP
@ApiOperation(value="Retrieve the current configured state of the server along with some runtime information",
responseClass = "Map 'values' with map of key-value pairs describing the status")
@GET
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java
index 9893e8e..cdc3b5f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java
@@ -35,6 +35,7 @@ import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
+import org.jboss.resteasy.annotations.GZIP;
import org.jboss.resteasy.annotations.cache.Cache;
@@ -48,6 +49,7 @@ import org.jboss.resteasy.annotations.cache.Cache;
@Api(value="Api that deals with user related stuff")
public interface UserHandlerLocal {
+ @GZIP
@GET
@Path("favorites/resource")
@ApiOperation(value = "Return a list of favorite resources of the caller", multiValueResponse = true, responseClass = "ResourceWithType")
commit 6a23948ca9b2c87c3414ac78b4d20ee1a55b7fe5
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri Jul 6 10:06:15 2012 +0200
Don't shut down the PC between tests and don't assume we have a MySQL server running.
diff --git a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
index 1e5b9e8..511d686 100644
--- a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
+++ b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
@@ -1,3 +1,22 @@
+/*
+ * 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.plugins.mysql;
import static org.testng.AssertJUnit.assertEquals;
@@ -329,7 +348,6 @@ public abstract class ComponentTest {
protected void after() throws Exception {
for (ResourceComponent c : components.keySet())
c.stop();
- PluginContainer.getInstance().shutdown();
}
/**
diff --git a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java
index 3f35c65..498fe22 100644
--- a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java
+++ b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java
@@ -1,3 +1,22 @@
+/*
+ * 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.plugins.mysql;
import org.rhq.core.domain.configuration.Configuration;
@@ -34,8 +53,9 @@ public class PluginTest extends ComponentTest {
public void test() throws Exception {
manuallyAdd("MySql Server");
- ResourceComponent resource = getComponent("MySql Server");
- assertUp(resource);
+ ResourceComponent resourceComponent = getComponent("MySql Server");
+// assertUp(resource); // TODO this requires a running mysql server
+ assert resourceComponent != null;
}
}
commit 771656ba9c19fad7e2a61e518bcb2ab9bd470977
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu Jul 5 16:37:29 2012 -0700
Move the save button to bottom of screen on configuration tab for groups. This was just done for non-groups.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
index 454cbf7..f6d6657 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
@@ -56,6 +56,8 @@ import org.rhq.enterprise.gui.coregui.client.util.message.MessageCenter;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableIButton;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
+import static java.util.EnumSet.*;
+
/**
* A view for editing a group's configuration.
*
@@ -70,6 +72,7 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
private ConfigurationDefinition configurationDefinition;
private List<GroupMemberConfiguration> memberConfigurations;
+ private ToolStrip buttonbar;
private ConfigurationEditor editor;
private IButton saveButton;
@@ -86,31 +89,35 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
protected void onDraw() {
super.onDraw();
- ToolStrip toolStrip = new ToolStrip();
- toolStrip.setWidth100();
- toolStrip.setExtraSpace(10);
- toolStrip.setMembersMargin(5);
- toolStrip.setLayoutMargin(5);
+ refresh();
+
+ if (!this.resourcePermission.isConfigureWrite()) {
+ Message message = new Message(MSG.view_group_resConfig_edit_noperm(), Message.Severity.Info, of(
+ Message.Option.Transient, Message.Option.Sticky));
+ CoreGUI.getMessageCenter().notify(message);
+ }
+ }
+
+ private ToolStrip createButtonBar() {
+ this.buttonbar = new ToolStrip();
+ buttonbar.setWidth100();
+ buttonbar.setExtraSpace(10);
+ buttonbar.setMembersMargin(5);
+ buttonbar.setLayoutMargin(5);
this.saveButton = new LocatableIButton(this.extendLocatorId("Save"), MSG.common_button_save());
- this.saveButton.setTooltip(MSG.view_group_resConfig_edit_saveTooltip());
this.saveButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent clickEvent) {
save();
}
});
- toolStrip.addMember(saveButton);
-
- addMember(toolStrip);
- refresh();
-
- if (!this.resourcePermission.isConfigureWrite()) {
- Message message = new Message(MSG.view_group_resConfig_edit_noperm(), Message.Severity.Info, EnumSet.of(
- Message.Option.Transient, Message.Option.Sticky));
- CoreGUI.getMessageCenter().notify(message);
- }
+ buttonbar.addMember(saveButton);
+ // The button bar will remain hidden until the configuration has been successfully loaded.
+ buttonbar.setVisible(false);
+ return buttonbar;
}
+
@Override
public void refresh() {
if (this.refreshing) {
@@ -122,6 +129,8 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
if (editor != null) {
editor.destroy();
removeMember(editor);
+ buttonbar.destroy();
+ removeMember(buttonbar);
}
// TODO (ips): If editor != null, use editor.reload() instead.
@@ -145,7 +154,7 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
if (this.configurationDefinition == null) {
final ResourceType type = this.group.getResourceType();
ResourceTypeRepository.Cache.getInstance().getResourceTypes(new Integer[] { type.getId() },
- EnumSet.of(ResourceTypeRepository.MetadataType.resourceConfigurationDefinition),
+ of(ResourceTypeRepository.MetadataType.resourceConfigurationDefinition),
new ResourceTypeRepository.TypesLoadedCallback() {
public void onTypesLoaded(Map<Integer, ResourceType> types) {
configurationDefinition = types.get(type.getId()).getResourceConfigurationDefinition();
@@ -188,6 +197,7 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
"The server did not return the configuration for one or more member resources.");
}
memberConfigurations.add(memberConfiguration);
+ addMember(createButtonBar());
}
initEditor();
}
commit 26959a31d8c37bcb86dc6a845b5707a277bff3cb
Author: Elias Ross <genman(a)noderunner.net>
Date: Thu Jul 5 21:41:32 2012 +0200
BZ 796983 - Improve discovery and use of column formatted metrics of database plugin
diff --git a/modules/plugins/database/pom.xml b/modules/plugins/database/pom.xml
index d4da519..24d0e1c 100644
--- a/modules/plugins/database/pom.xml
+++ b/modules/plugins/database/pom.xml
@@ -16,7 +16,12 @@
<description>An abstract plugin for managing databases via JDBC</description>
<dependencies>
-
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
</dependencies>
<profiles>
diff --git a/modules/plugins/database/src/main/java/org/rhq/plugins/database/AbstractDatabaseComponent.java b/modules/plugins/database/src/main/java/org/rhq/plugins/database/AbstractDatabaseComponent.java
index 1170668..5976695 100644
--- a/modules/plugins/database/src/main/java/org/rhq/plugins/database/AbstractDatabaseComponent.java
+++ b/modules/plugins/database/src/main/java/org/rhq/plugins/database/AbstractDatabaseComponent.java
@@ -24,6 +24,7 @@ import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.core.pluginapi.inventory.ResourceContext;
/**
+ * Base class for database components.
* @author Greg Hinkle
*/
public abstract class AbstractDatabaseComponent<T extends DatabaseComponent<?>> implements DatabaseComponent {
@@ -46,4 +47,9 @@ public abstract class AbstractDatabaseComponent<T extends DatabaseComponent<?>>
public void removeConnection() {
this.resourceContext.getParentResourceComponent().removeConnection();
}
+
+ @Override
+ public String toString() {
+ return getClass().getName() + " key=" + resourceContext.getResourceKey();
+ }
}
\ No newline at end of file
diff --git a/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableComponent.java b/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableComponent.java
index e78d5c1..f2e8fa7 100644
--- a/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableComponent.java
+++ b/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableComponent.java
@@ -57,14 +57,20 @@ public class CustomTableComponent implements DatabaseComponent<DatabaseComponent
}
public String getTable() {
- return this.context.getPluginConfiguration().getSimpleValue("table", null);
+ return this.context.getPluginConfiguration().getSimpleValue("table", "");
}
public AvailabilityType getAvailability() {
+ if (getTable().isEmpty()) {
+ // not set
+ return AvailabilityType.UP;
+ }
Statement statement = null;
try {
statement = getConnection().createStatement();
- statement.executeQuery("SELECT COUNT(*) FROM " + getTable());
+ statement.setMaxRows(1);
+ statement.setFetchSize(1);
+ statement.executeQuery("SELECT * FROM " + getTable()).close();
return AvailabilityType.UP;
} catch (SQLException e) {
return AvailabilityType.DOWN;
@@ -75,8 +81,8 @@ public class CustomTableComponent implements DatabaseComponent<DatabaseComponent
public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
- Configuration conf = this.context.getPluginConfiguration();
- String query = conf.getSimpleValue("metricQuery", null);
+ Configuration config = this.context.getPluginConfiguration();
+ String query = config.getSimpleValue("metricQuery", null);
if (query == null) {
if (log.isTraceEnabled()) {
@@ -93,9 +99,18 @@ public class CustomTableComponent implements DatabaseComponent<DatabaseComponent
return;
}
- query = CustomTableRowDiscoveryComponent.formatMessage(query, conf.getSimpleValue("key", null));
-
- Map<String, Double> values = DatabaseQueryUtility.getNumericQueryValueMap(this, query);
+ query = CustomTableRowDiscoveryComponent.formatMessage(query, config.getSimpleValue("key", null));
+ String column = config.getSimpleValue("column", "");
+ Map<String, Double> values;
+ if (Boolean.parseBoolean(column)) {
+ // data in column format
+ values = DatabaseQueryUtility.getNumericQueryValues(this, query);
+ } else {
+ // data in row format
+ values = DatabaseQueryUtility.getNumericQueryValueMap(this, query);
+ }
+ if (log.isDebugEnabled())
+ log.debug("returned values " + values);
// this is a for loop because the name of each column can be the name of the metric
for (MeasurementScheduleRequest request : metrics) {
@@ -126,4 +141,4 @@ public class CustomTableComponent implements DatabaseComponent<DatabaseComponent
public void removeConnection() {
this.context.getParentResourceComponent().removeConnection();
}
-}
\ No newline at end of file
+}
diff --git a/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableDiscoveryComponent.java b/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableDiscoveryComponent.java
index f76a659..aeab429 100644
--- a/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableDiscoveryComponent.java
+++ b/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableDiscoveryComponent.java
@@ -24,7 +24,10 @@ import java.sql.Statement;
import java.util.Collections;
import java.util.Set;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.core.pluginapi.inventory.ManualAddFacet;
@@ -33,45 +36,61 @@ import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
import org.rhq.core.util.jdbc.JDBCUtil;
/**
- * Discovery for a generic component that can read data out of a table for monitoring purposes. Neccessary configuration
- * properties table - the name of the table to search for during inventory metricQuery - the query run to load metric
- * data name - the name of the resource description - the description of the resource
+ * Discovery for a generic component that can read data out of a table for
+ * monitoring purposes. Necessary configuration properties
+ * <li> table - the name of the table to search for during inventory. Note: If absent only
+ * supports manual adding.
+ * <li> metricQuery - the query run to load metric data
+ * <li> name - the name of the resource
+ * <li> description - the description of the resource
*
* @author Greg Hinkle
*/
public class CustomTableDiscoveryComponent implements ManualAddFacet<DatabaseComponent<?>>,
ResourceDiscoveryComponent<DatabaseComponent<?>> {
+
+ protected Log log = LogFactory.getLog(getClass());
+
public Set<DiscoveredResourceDetails> discoverResources(
ResourceDiscoveryContext<DatabaseComponent<?>> resourceDiscoveryContext)
throws InvalidPluginConfigurationException, Exception {
+
+ Configuration config = resourceDiscoveryContext.getDefaultPluginConfiguration();
+ String table = config.getSimpleValue("table", "");
+ ResourceType rt = resourceDiscoveryContext.getResourceType();
+ String resourceName = config.getSimpleValue("name", rt.getName());
+ String resourceDescription = config.getSimpleValue("description", rt.getDescription());
+
+ if (table.isEmpty()) {
+ log.debug("'table' value not set, cannot discover " + resourceName);
+ return Collections.emptySet();
+ }
+
Statement statement = null;
try {
Connection conn = resourceDiscoveryContext.getParentResourceComponent().getConnection();
-
- Configuration config = resourceDiscoveryContext.getDefaultPluginConfiguration();
- String table = config.getSimpleValue("table", null);
- String resourceName = config.getSimpleValue("name", table);
- String resourceDescription = config.getSimpleValue("description", null);
+ if (conn == null)
+ throw new InvalidPluginConfigurationException("cannot obtain connection from parent");
statement = conn.createStatement();
- statement.executeQuery("SELECT COUNT(*) FROM " + table);
-
+ statement.setMaxRows(1);
+ statement.setFetchSize(1);
+ // This is more efficient than 'count(*)'
+ // unless the JDBC driver fails to support setMaxRows or doesn't stream results
+ statement.executeQuery("SELECT * FROM " + table).close();
DiscoveredResourceDetails details = new DiscoveredResourceDetails(
resourceDiscoveryContext.getResourceType(), table + resourceName, resourceName, null,
resourceDescription, config, null);
+ log.debug("discovered " + details);
return Collections.singleton(details);
} catch (SQLException e) {
+ log.debug("discovery failed " + e + " for " + table);
// table not found, don't inventory
} finally {
JDBCUtil.safeClose(statement);
}
- if (!resourceDiscoveryContext.getPluginConfigurations().isEmpty()) {
- return Collections.singleton(discoverResource(resourceDiscoveryContext.getPluginConfigurations().get(0),
- resourceDiscoveryContext));
- }
-
return Collections.emptySet();
}
@@ -79,14 +98,15 @@ public class CustomTableDiscoveryComponent implements ManualAddFacet<DatabaseCom
ResourceDiscoveryContext<DatabaseComponent<?>> discoveryContext) throws InvalidPluginConfigurationException {
Configuration config = pluginConfiguration;
-
String table = config.getSimpleValue("table", null);
String resourceName = config.getSimpleValue("name", table);
- String resourceDescription = config.getSimpleValue("description", null);
+ String resourceDescription = config.getSimpleValue("description",
+ discoveryContext.getResourceType().getDescription());
+ String resourceVersion = config.getSimpleValue("version", null);
DiscoveredResourceDetails details = new DiscoveredResourceDetails(discoveryContext.getResourceType(), table
- + resourceName, resourceName, null, resourceDescription, config, null);
+ + resourceName, resourceName, resourceVersion, resourceDescription, config, null);
return details;
}
-}
\ No newline at end of file
+}
diff --git a/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableRowDiscoveryComponent.java b/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableRowDiscoveryComponent.java
index 56d9ddd..50da33b 100644
--- a/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableRowDiscoveryComponent.java
+++ b/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableRowDiscoveryComponent.java
@@ -38,9 +38,12 @@ import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
import org.rhq.core.util.jdbc.JDBCUtil;
/**
- * Discovery for a generic component that can read data out of a table for monitoring purposes. Neccessary configuration
- * properties table - the name of the table to search for during inventory metricQuery - the query run to load metric
- * data name - the name of the resource description - the description of the resource
+ * Discovery for a generic component that can read data out of a table for
+ * monitoring purposes. Necessary configuration properties:
+ * <li> table - the name of the table to search for during inventory
+ * <li> keyColumn - the key of the table used to load metric data
+ * <li> name - the name of the resource
+ * <li> description - the description of the resource
*
* @author Greg Hinkle
*/
@@ -112,4 +115,4 @@ public class CustomTableRowDiscoveryComponent implements ResourceDiscoveryCompon
message = message.replaceAll("\\{key\\}", key);
return message;
}
-}
\ No newline at end of file
+}
diff --git a/modules/plugins/database/src/main/java/org/rhq/plugins/database/DatabaseQueryUtility.java b/modules/plugins/database/src/main/java/org/rhq/plugins/database/DatabaseQueryUtility.java
index 5bab090..95e981d 100644
--- a/modules/plugins/database/src/main/java/org/rhq/plugins/database/DatabaseQueryUtility.java
+++ b/modules/plugins/database/src/main/java/org/rhq/plugins/database/DatabaseQueryUtility.java
@@ -24,8 +24,10 @@ import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
@@ -34,11 +36,25 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.core.util.exception.ThrowableUtil;
/**
+ * Various database (JDBC) query functions.
+ *
* @author Greg Hinkle
*/
public class DatabaseQueryUtility {
+
private static final Log LOG = LogFactory.getLog(DatabaseQueryUtility.class);
+ private DatabaseQueryUtility() {}
+
+ /**
+ * Executes a database update.
+ *
+ * @param databaseComponent
+ * @param query
+ * @param parameters
+ * @return
+ * @throws SQLException
+ */
public static int executeUpdate(DatabaseComponent databaseComponent, String query, Object... parameters)
throws SQLException {
PreparedStatement statement = null;
@@ -55,6 +71,10 @@ public class DatabaseQueryUtility {
}
}
+ /**
+ * Returns the result of a query as a single Double value.
+ * Returns {@link Double#NaN} if the query fails.
+ */
public static Double getSingleNumericQueryValue(DatabaseComponent databaseComponent, String query,
Object... parameters) {
PreparedStatement statement = null;
@@ -77,13 +97,15 @@ public class DatabaseQueryUtility {
}
/**
- * Used to read a single row of columns into a map
+ * Executes a query, returning the results as a map where the keys
+ * are the column names and values are the value of that column.
+ * Note depending on the database, the column names may be uppercase (Oracle) or lowercase.
*
* @param databaseComponent
- * @param query
- * @param parameters
+ * @param query SQL query string
+ * @param parameters optional bind parameters
*
- * @return
+ * @return a map of query results
*/
public static Map<String, Double> getNumericQueryValues(DatabaseComponent databaseComponent, String query,
Object... parameters) {
@@ -122,8 +144,48 @@ public class DatabaseQueryUtility {
}
/**
- * Used to access a set of rows as key, value pairs where the key is the first column and is a string and the second
- * is a value and is numeric
+ * Returns a list of values, one per row, containing a map of column names to values of that row.
+ * Note depending on the database, the column names may be uppercase (Oracle) or lowercase.
+ * @param databaseComponent database to query
+ * @param query SQL query
+ * @param parameters parameters to bind to the query
+ *
+ * @throws SQLException if query fails
+ */
+ public static List<Map<String, Object>> getGridValues(DatabaseComponent databaseComponent, String query,
+ Object... parameters) throws SQLException {
+ PreparedStatement statement = null;
+ ResultSet resultSet = null;
+ List<Map<String, Object>> l = new ArrayList<Map<String, Object>>();
+ try {
+ statement = databaseComponent.getConnection().prepareStatement(query);
+ bindParameters(statement, parameters);
+
+ resultSet = statement.executeQuery();
+
+ while (resultSet.next()) {
+ Map<String, Object> row = new HashMap<String, Object>();
+ l.add(row);
+
+ ResultSetMetaData md = resultSet.getMetaData();
+ String[] names = getColumns(md);
+
+ for (String name : names) {
+ Object o = resultSet.getObject(name);
+ row.put(name, o);
+ }
+ }
+
+ } finally {
+ close(statement, resultSet);
+ }
+ return l;
+
+ }
+
+ /**
+ * Returns a mapping of rows as key-value pairs where the key is the
+ * first column (a string) and the second column is a value numeric.
*
* @param databaseComponent the component to execute on
* @param query the sql query to run
@@ -166,6 +228,9 @@ public class DatabaseQueryUtility {
return Collections.emptyMap();
}
+ /**
+ * Binds arguments to a prepared statement.
+ */
private static void bindParameters(PreparedStatement statement, Object... parameters) throws SQLException {
int i = 1;
for (Object p : parameters) {
@@ -179,6 +244,9 @@ public class DatabaseQueryUtility {
}
}
+ /**
+ * Returns an array of strings as upper-case column names.
+ */
public static String[] getColumns(ResultSetMetaData rsmd) throws SQLException {
String[] names = new String[rsmd.getColumnCount()];
for (int i = 0; i < rsmd.getColumnCount(); i++) {
@@ -188,11 +256,9 @@ public class DatabaseQueryUtility {
return names;
}
- public static class StatementParameter {
- private String name;
- private String value;
- }
-
+ /**
+ * Closes statements and result sets.
+ */
public static void close(Statement statement, ResultSet resultSet) {
if (resultSet != null) {
try {
@@ -208,4 +274,4 @@ public class DatabaseQueryUtility {
}
}
}
-}
\ No newline at end of file
+}
diff --git a/modules/plugins/database/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/database/src/main/resources/META-INF/rhq-plugin.xml
index 7d92ce5..d1bcbfa 100644
--- a/modules/plugins/database/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/database/src/main/resources/META-INF/rhq-plugin.xml
@@ -7,4 +7,61 @@
pluginLifecycleListener="DatabasePluginLifecycleListener"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:xmlns:rhq-plugin">
-</plugin>
\ No newline at end of file
+
+<!-- Example use: Create a plugin to query from an Oracle database.
+
+ <depends plugin="Oracle" useClasses="true"/>
+
+ <server name="Generic Query" class="org.rhq.plugins.database.CustomTableComponent"
+ discovery="org.rhq.plugins.database.CustomTableDiscoveryComponent"
+ description="Query the database for various results"
+ supportsManualAdd="true" singleton="false"
+ createDeletePolicy="both">
+ <runs-inside>
+ ... note: this works for any database component that implements 'org.rhq.plugins.database.DatabaseComponent'
+ <parent-resource-type name="Oracle Server" plugin="Oracle"/>
+ </runs-inside>
+ <plugin-configuration>
+ <c:simple-property name="table" type="string" default="sometable"/>
+ ... table is optional; if table is not defined discovery will be skipped
+ <c:simple-property name="metricQuery" type="string" default="select a, b from sometable"/>
+ <c:simple-property name="column" type="boolean" default="true"/>
+ ... use column default='false' for data appearing like:
+ col1 col2
+ ~~~~~~~~
+ a 123
+ b 323
+
+ and query 'select col1, col2 from sometable'
+ </plugin-configuration>
+ ... columns from Oracle appear uppercase ...
+ <metric property="A" displayName="A results" displayType="summary"
+ description="Number appearing in A column"
+ units="none" dataType="measurement"/>
+ <metric property="B" displayName="B results" displayType="summary"
+ description="Number appearing in B column"
+ units="none" dataType="measurement"/>
+ </server>
+
+ ... select rows from a database and create sub-components based on that key
+
+ <service name="Oracle User"
+ discovery="org.rhq.plugins.database.CustomTableRowDiscoveryComponent"
+ class="org.rhq.plugins.oracle.OracleUserComponent">
+
+ <plugin-configuration>
+ <c:simple-property name="table" default="DBA_USERS"/>
+ <c:simple-property name="metricQuery" default="SELECT {key} FROM DBA_USERS"/>
+ <c:simple-property name="keyColumn" default="username"/>
+ <c:simple-property name="name" default="{key}"/>
+ <c:simple-property name="description" default="Oracle User"/>
+ </plugin-configuration>
+
+ <metric property="connections" displayName="Total Connections" displayType="summary"/>
+ <metric property="active" displayName="Active Connections" displayType="summary"/>
+
+ </service>
+
+-->
+
+</plugin>
diff --git a/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java b/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java
new file mode 100644
index 0000000..b9622c6
--- /dev/null
+++ b/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java
@@ -0,0 +1,545 @@
+package org.rhq.plugins.database;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertTrue;
+import static org.testng.AssertJUnit.fail;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import javax.xml.bind.JAXBElement;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
+import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
+import org.rhq.core.clientapi.descriptor.configuration.ConfigurationProperty;
+import org.rhq.core.clientapi.descriptor.plugin.MetricDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.ResourceDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.ServerDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.ServiceDescriptor;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+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.resource.ProcessScan;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pc.PluginContainer;
+import org.rhq.core.pc.PluginContainerConfiguration;
+import org.rhq.core.pc.availability.AvailabilityContextImpl;
+import org.rhq.core.pc.content.ContentContextImpl;
+import org.rhq.core.pc.event.EventContextImpl;
+import org.rhq.core.pc.event.EventManager;
+import org.rhq.core.pc.inventory.ResourceContainer;
+import org.rhq.core.pc.operation.OperationContextImpl;
+import org.rhq.core.pluginapi.availability.AvailabilityContext;
+import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
+import org.rhq.core.pluginapi.content.ContentContext;
+import org.rhq.core.pluginapi.event.EventContext;
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
+import org.rhq.core.pluginapi.inventory.ProcessScanResult;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+import org.rhq.core.pluginapi.operation.OperationContext;
+import org.rhq.core.system.ProcessInfo;
+import org.rhq.core.system.SystemInfo;
+import org.rhq.core.system.SystemInfoFactory;
+import org.rhq.core.system.pquery.ProcessInfoQuery;
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeSuite;
+
+/**
+ * Base class for RHQ Component Testing.
+ * Initializes a plugin configuration.
+ *
+ * Methods to override:
+ *
+ * {@link #setConfiguration(Configuration, ResourceType)}
+ */
+public abstract class ComponentTest {
+
+ /**
+ * Logging component.
+ */
+ protected final Log log = LogFactory.getLog(getClass());
+
+ private static File temp = new File(System.getProperty("java.io.tmpdir"));
+
+ /**
+ * Associates a resource component with a resource.
+ */
+ protected Map<ResourceComponent, Resource> components = new LinkedHashMap<ResourceComponent, Resource>();
+
+ /**
+ * Associates a name of a resource with a resource descriptor.
+ */
+ protected Map<String, ResourceDescriptor> descriptors = new LinkedHashMap<String, ResourceDescriptor>();
+
+ /**
+ * Associates a name of a resource with a type.
+ * This is useful for manually adding resources.
+ *
+ * @see #manuallyAdd(ResourceType, Configuration)
+ */
+ protected Map<String, ResourceType> resourceTypes = new LinkedHashMap<String, ResourceType>();
+
+ /**
+ * Event manager; used to obtain events.
+ */
+ private EventManager eventManager;
+
+ private PluginContainer pluginContainer = PluginContainer.getInstance();
+
+ private SystemInfo systemInfo = SystemInfoFactory.createSystemInfo();
+
+ /**
+ * Scan all processes before starting; false will disable this feature.
+ * Disabling is suggested for running tests against a remote instance.
+ */
+ private boolean processScan = true;
+
+ // TODO
+
+ private final PluginMetadataManager pmm = new PluginMetadataManager();
+ private final File temporaryDirectory = temp;
+ private final File dataDirectory = temp;
+ private final String pluginContainerName = "rhq";
+ private final OperationContext operationContext = new OperationContextImpl(0);
+ private final ContentContext contentContext = new ContentContextImpl(0);
+ private final Executor availCollectorThreadPool = Executors.newCachedThreadPool();
+ private PluginContainerDeployment pluginContainerDeployment = null;
+ private Resource platform;
+ private ResourceContainer platformContainer;
+ private List<ProcessInfo> processInfo = Collections.emptyList();
+ private PluginDescriptor pluginDescriptor;
+ private AvailabilityContext availabilityContext;
+
+
+ /**
+ * Constructs a new component test.
+ */
+ protected ComponentTest() {
+ }
+
+ /**
+ * Initializes the plugin container.
+ * This is run before {@link #before()}.
+ */
+ @BeforeSuite
+ protected void beforeSuite() {
+ // Speed up propagation of events by adjusting delay/period to 1 second
+ PluginContainerConfiguration pcc = new PluginContainerConfiguration();
+ pcc.setEventSenderInitialDelay(1);
+ pcc.setEventSenderPeriod(1);
+ pluginContainer.setConfiguration(pcc);
+ pluginContainer.initialize();
+ eventManager = pluginContainer.getEventManager();
+ platform = pluginContainer.getInventoryManager().getPlatform();
+ platformContainer = pluginContainer.getInventoryManager().getResourceContainer(platform);
+ if (platformContainer == null) {
+ platformContainer = new ResourceContainer(platform, getClass().getClassLoader());
+ }
+ }
+
+ /**
+ * Initializes all plugins defined in the system; using auto-discovery where possible.
+ * This is run once per test class.
+ */
+ @BeforeClass
+ protected void before() throws Exception {
+ if (processScan) {
+ processInfo = getProcessInfos();
+ if (processInfo == null)
+ processInfo = Collections.emptyList();
+ log.debug("Process Info " + processInfo);
+ for (ProcessInfo i : processInfo) {
+ log.debug(i.getBaseName() + " " + Arrays.toString(i.getCommandLine()));
+ }
+ }
+ Enumeration<URL> e = getClass().getClassLoader().getResources("META-INF/rhq-plugin.xml");
+ List<URL> l = Collections.list(e);
+ Collections.sort(l, new Comparator<URL>() {
+ @Override
+ public int compare(URL u1, URL u2) {
+ return u2.toString().compareTo(u1.toString());
+ }
+ });
+ for (URL url : l) {
+ log.debug("parse " + url);
+ InputStream is = url.openStream();
+ PluginDescriptor pd = AgentPluginDescriptorUtil.parsePluginDescriptor(is);
+ processPluginDescriptor(pd);
+ log.debug("pmm names " + pmm.getPluginNames());
+ buildDesc(pd.getServers());
+ buildDesc(pd.getServices());
+ is.close();
+ }
+ }
+
+ @AfterSuite
+ protected void afterSuite() {
+ pluginContainer.shutdown();
+ }
+
+ /**
+ * Process a plugin descriptor.
+ */
+ private void processPluginDescriptor(PluginDescriptor pd) throws Exception {
+ this.pluginDescriptor = pd;
+ Set<ResourceType> types = pmm.loadPlugin(pd);
+ mapResourceTypeNames(types);
+ log.info("Resource types: " + resourceTypes);
+ resources(types, platform, platformContainer.getResourceComponent(), platformContainer.getResourceContext());
+ log.info("ResourceComponent map: " + components);
+ }
+
+ private void mapResourceTypeNames(Set<ResourceType> types) {
+ for (ResourceType type : types) {
+ this.resourceTypes.put(type.getName(), type);
+ mapResourceTypeNames(type.getChildResourceTypes());
+ }
+ }
+
+ /**
+ * Manually create a component by name.
+ */
+ public ResourceComponent manuallyAdd(String name) throws Exception {
+ ResourceType resourceType = resourceTypes.get(name);
+ if (resourceType == null)
+ throw new IllegalStateException("no type " + name);
+ Configuration configuration = resourceType.getPluginConfigurationDefinition().getDefaultTemplate().createConfiguration();
+ setConfiguration(configuration, resourceType);
+ return manuallyAdd(resourceType, configuration);
+ }
+
+ /**
+ * Manually create a component by resource type.
+ */
+ public ResourceComponent manuallyAdd(ResourceType type, Configuration configuration) throws Exception {
+ return manuallyAdd(type, configuration, platformContainer.getResourceComponent());
+ }
+
+ /**
+ * Manually create a component by resource type, configuration, parent.
+ */
+ public ResourceComponent manuallyAdd(ResourceType type, Configuration configuration, ResourceComponent parent) throws Exception {
+ DiscoveredResourceDetails drd = new DiscoveredResourceDetails(type,
+ "key", "name", "ver", "desc", configuration, (ProcessInfo) null);
+ ResourceDiscoveryComponent c = null;
+ return createChild(drd, platform, configuration, parent, c);
+ }
+
+ private ResourceComponent createChild(DiscoveredResourceDetails drd,
+ Resource resource,
+ Configuration configuration,
+ ResourceComponent parentComponent,
+ ResourceDiscoveryComponent rdc) throws Exception
+ {
+ ResourceType type = pmm.getType(drd.getResourceType());
+
+ Resource cresource = new Resource();
+ cresource.setResourceType(type);
+ cresource.setPluginConfiguration(configuration);
+ cresource.setResourceKey(drd.getResourceKey());
+ cresource.setParentResource(resource);
+ cresource.setName(drd.getResourceName());
+ cresource.setVersion(drd.getResourceVersion());
+
+ String rclassname = pmm.getComponentClass(type);
+ ResourceComponent component = (ResourceComponent) Class.forName(rclassname).newInstance();
+
+ availabilityContext = new AvailabilityContextImpl(cresource,availCollectorThreadPool);
+ EventContext eventContext = new EventContextImpl(resource);
+ ResourceContext context = new ResourceContext(cresource, parentComponent,
+ null, rdc, systemInfo, temporaryDirectory, dataDirectory,
+ pluginContainerName, eventContext, operationContext, contentContext,
+ availabilityContext, pluginContainerDeployment);
+
+ component.start(context);
+ components.put(component, cresource);
+ resources(type.getChildResourceTypes(), cresource, component, context);
+ return component;
+ }
+
+ private void resources(Set<ResourceType> types, Resource parent, ResourceComponent component, ResourceContext context) throws Exception {
+ for (ResourceType type : types) {
+ String s = pmm.getDiscoveryClass(type);
+ if (s == null) {
+ throw new NullPointerException("no discovery " + type);
+ }
+ ResourceDiscoveryComponent rdc = (ResourceDiscoveryComponent) Class.forName(s).newInstance();
+ log.debug("rdc=" + rdc);
+ ResourceDiscoveryContext resourceDiscoveryContext = new ResourceDiscoveryContext(type, component,
+ context, systemInfo,
+ performProcessScans(type), new ArrayList<Configuration>(),
+ pluginContainerName, pluginContainerDeployment);
+ Set<DiscoveredResourceDetails> drds = rdc.discoverResources(resourceDiscoveryContext);
+ for (DiscoveredResourceDetails drd : drds) {
+ log.debug("discovered " + drd);
+ ResourceType resourceType = drd.getResourceType();
+ setConfiguration(drd.getPluginConfiguration(), resourceType);
+ createChild(drd, parent, drd.getPluginConfiguration(), component, rdc);
+ }
+ if (drds.isEmpty()) {
+ log.warn("not discovered " + type);
+ context.getPluginConfiguration();
+ }
+ }
+
+ }
+
+ /**
+ * Called before the configuration is processed; override to set specific plugin parameters.
+ */
+ protected void setConfiguration(Configuration configuration, ResourceType resourceType) {
+ }
+
+ /**
+ * Stops all components, stops the plugin container.
+ */
+ @AfterTest
+ protected void after() throws Exception {
+ for (ResourceComponent c : components.keySet())
+ c.stop();
+// PluginContainer.getInstance().shutdown();
+ }
+
+ /**
+ * Returns a measurement report.
+ */
+ public MeasurementReport getMeasurementReport(ResourceComponent component) throws Exception {
+ Resource resource = this.components.get(component);
+ ResourceType type = resource.getResourceType();
+ MeasurementReport report = new MeasurementReport();
+ Set<MeasurementScheduleRequest> s = new HashSet<MeasurementScheduleRequest>();
+ for (MeasurementDefinition md : type.getMetricDefinitions())
+ s.add(new MeasurementScheduleRequest(new MeasurementSchedule(md, resource)));
+ ((MeasurementFacet)component).getValues(report, s);
+ return report;
+ }
+
+ /**
+ * Returns the first resource component by resource name, then looks by matching resource type name,
+ * then asserts failure if not found.
+ */
+ public ResourceComponent getComponent(String name) {
+ for (Map.Entry<ResourceComponent, Resource> c : components.entrySet())
+ if (c.getValue().getName().equals(name))
+ return c.getKey();
+ for (Map.Entry<ResourceComponent, Resource> c : components.entrySet())
+ if (c.getValue().getResourceType().getName().equals(name))
+ return c.getKey();
+ fail("component not found " + name + " in " + components.entrySet());
+ return null;
+ }
+
+ /**
+ * Returns a resource matching this component.
+ */
+ public Resource getResource(ResourceComponent rc) {
+ Resource r = components.get(rc);
+ if (r == null)
+ throw new IllegalStateException();
+ return r;
+ }
+
+ /**
+ * Returns a resource matching this name.
+ */
+ public Resource getResource(String name) {
+ return getResource(getComponent(name));
+ }
+
+ /**
+ * Builds a new configuration for a resource type.
+ */
+ public Configuration getConfiguration(ResourceType resourceType) {
+ Configuration configuration = resourceType.getPluginConfigurationDefinition().getDefaultTemplate().createConfiguration();
+ setConfiguration(configuration, resourceType);
+ return configuration;
+ }
+
+ // ASSERT METHOD
+
+ /**
+ * From a measurement report, returns a measurement value, or asserts failure if no such value exists.
+ */
+ public static Double getValue(MeasurementReport report, String name) {
+ for (MeasurementDataNumeric m: report.getNumericData()) {
+ if (m.getName().equals(name)) {
+ return m.getValue();
+ }
+ }
+ fail("report does not incude " + name + " report " + report.getNumericData());
+ return null;
+ }
+
+ /**
+ * Asserts the resource component is available.
+ */
+ public static void assertUp(ResourceComponent component) {
+ assertEquals("up " + component, AvailabilityType.UP, component.getAvailability());
+ }
+
+ /**
+ * Asserts the resource component is unavailable.
+ */
+ public static void assertDown(ResourceComponent component) {
+ assertEquals("down " + component, AvailabilityType.DOWN, component.getAvailability());
+ }
+
+ /**
+ * Sets a configuration option.
+ */
+ public static void set(Configuration config, String name, String value) {
+ PropertySimple s = config.getSimple(name);
+ if (s == null) {
+ s = new PropertySimple(name, value);
+ config.put(s);
+ } else {
+ s.setStringValue(value);
+ }
+ }
+
+ private List<ProcessScanResult> performProcessScans(ResourceType serverType) {
+ List<ProcessScanResult> scanResults = new ArrayList<ProcessScanResult>();
+ Set<ProcessScan> processScans = serverType.getProcessScans();
+ log.debug("Executing process scans for server type " + serverType + "...");
+ ProcessInfoQuery piq = new ProcessInfoQuery(processInfo);
+ for (ProcessScan processScan : processScans) {
+ List<ProcessInfo> queryResults = piq.query(processScan.getQuery());
+ for (ProcessInfo autoDiscoveredProcess : queryResults) {
+ scanResults.add(new ProcessScanResult(processScan, autoDiscoveredProcess));
+ log.info("Process scan auto-detected new server resource: scan=[" + processScan
+ + "], discovered-process=[" + autoDiscoveredProcess + "]");
+ }
+ }
+ return scanResults;
+ }
+
+ /**
+ * AutoDiscoveryExecutor method.
+ */
+ private List<ProcessInfo> getProcessInfos() {
+ SystemInfo systemInfo = SystemInfoFactory.createSystemInfo();
+ log.debug("Retrieving process table...");
+ long startTime = System.currentTimeMillis();
+ List<ProcessInfo> processInfos = null;
+ try {
+ processInfos = systemInfo.getAllProcesses();
+ } catch (UnsupportedOperationException uoe) {
+ log.debug("Cannot perform process scan - not supported on this platform. (" + systemInfo.getClass() + ")");
+ }
+ long elapsedTime = System.currentTimeMillis() - startTime;
+ log.debug("Retrieval of process table took " + elapsedTime + " ms.");
+ return processInfos;
+ }
+
+ /**
+ * Returns the plugin descriptor.
+ */
+ public PluginDescriptor getPluginDescriptor() {
+ return pluginDescriptor;
+ }
+
+ /**
+ * Returns the plugin descriptor.
+ */
+ public ResourceDescriptor getResourceDescriptor(String name) {
+ ResourceDescriptor rd = descriptors.get(name);
+ if (rd == null)
+ throw new IllegalStateException("no descriptor " + name + " in " + descriptors.keySet());
+ return rd;
+ }
+
+ private void buildDesc(List<? extends ResourceDescriptor> l) {
+ for (ResourceDescriptor rd : l) {
+ descriptors.put(rd.getName(), rd);
+ if (rd instanceof ServerDescriptor) {
+ buildDesc(((ServerDescriptor)rd).getServers());
+ buildDesc(((ServerDescriptor)rd).getServices());
+ }
+ if (rd instanceof ServiceDescriptor) {
+ buildDesc(((ServiceDescriptor)rd).getServices());
+ buildDesc(((ServiceDescriptor)rd).getServices());
+ }
+ }
+ }
+
+ /**
+ * Asserts that all measurements in the report are present
+ * according to the resource descriptor.
+ *
+ * @see #getResourceDescriptor(String) for obtaining this.
+ * @param report
+ */
+ public static void assertAll(MeasurementReport report, ResourceDescriptor l) {
+ HashMap<String, MetricDescriptor> map = new HashMap<String, MetricDescriptor>();
+ for (MetricDescriptor md : l.getMetric()) {
+ map.put(md.getProperty(), md);
+ }
+ for (MeasurementDataNumeric n : report.getNumericData()) {
+ map.remove(n.getName());
+ }
+ for (MeasurementDataTrait n : report.getTraitData()) {
+ map.remove(n.getName());
+ }
+ assertTrue("Measurements not found " + map.keySet(), map.isEmpty());
+ }
+
+ /**
+ * Returns the event manager.
+ */
+ public EventManager getEventManager() {
+ return eventManager;
+ }
+
+ /**
+ * Set to false to avoid scanning local machine processes to speed up testing.
+ */
+ public void setProcessScan(boolean processScan) {
+ this.processScan = processScan;
+ }
+
+ public void assertAll(ConfigurationFacet cf, ResourceDescriptor rd) throws Exception {
+ Configuration config = cf.loadResourceConfiguration();
+ List<JAXBElement<? extends ConfigurationProperty>> templates = rd.getResourceConfiguration().getConfigurationProperty();
+ for (JAXBElement<? extends ConfigurationProperty> template : templates) {
+ String name = template.getValue().getName();
+ // Property property = config.get(name);
+ assertNotNull("config contains " + name, config.get(name));
+ Object value = config.getSimpleValue(name, null);
+ assertNotNull("value for " + name, value);
+ log.debug("config found " + name + " value " + value );
+ }
+ }
+
+}
diff --git a/modules/plugins/database/src/test/java/org/rhq/plugins/database/H2Database.java b/modules/plugins/database/src/test/java/org/rhq/plugins/database/H2Database.java
new file mode 100644
index 0000000..a81d998
--- /dev/null
+++ b/modules/plugins/database/src/test/java/org/rhq/plugins/database/H2Database.java
@@ -0,0 +1,79 @@
+package org.rhq.plugins.database;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.util.jdbc.JDBCUtil;
+
+/**
+ * Tests using the H2Database.
+ */
+public class H2Database implements DatabaseComponent<ResourceComponent<?>> {
+
+ private Log log = LogFactory.getLog(this.getClass());
+ protected ResourceContext resourceContext;
+ private Connection connection;
+ private Configuration configuration;
+
+ public void start(ResourceContext resourceContext) throws InvalidPluginConfigurationException, Exception {
+ this.resourceContext = resourceContext;
+ this.configuration = resourceContext.getPluginConfiguration();
+ }
+
+ public void stop() {
+ removeConnection();
+ }
+
+ public AvailabilityType getAvailability() {
+ Connection conn = getConnection();
+ AvailabilityType result = AvailabilityType.DOWN;
+ if (conn != null) {
+ result = AvailabilityType.UP;
+ }
+ return result;
+
+ }
+
+ public Connection getConnection() {
+ try {
+ if (this.connection == null || connection.isClosed()) {
+ this.connection = buildConnection();
+ }
+ } catch (SQLException e) {
+ log.info("Unable to create connection", e);
+ }
+ return this.connection;
+ }
+
+ @Override
+ public void removeConnection() {
+ JDBCUtil.safeClose(connection);
+ this.connection = null;
+ }
+
+ private Connection buildConnection() throws SQLException {
+ String driverClass = configuration.getSimpleValue("driverClass", "org.h2.Driver");
+ try {
+ Class.forName(driverClass);
+ } catch (ClassNotFoundException e) {
+ throw new InvalidPluginConfigurationException("Specified JDBC driver class (" + driverClass
+ + ") not found.");
+ }
+
+ String url = configuration.getSimpleValue("url", "jdbc:h2:test");
+ String username = configuration.getSimpleValue("username", "sa");
+ String password = configuration.getSimpleValue("password", "");
+ log.debug("Attempting JDBC connection to [" + url + "]");
+ return DriverManager.getConnection(url, username, password);
+ }
+
+
+}
diff --git a/modules/plugins/database/src/test/java/org/rhq/plugins/database/H2DatabaseDiscovery.java b/modules/plugins/database/src/test/java/org/rhq/plugins/database/H2DatabaseDiscovery.java
new file mode 100644
index 0000000..dbce116
--- /dev/null
+++ b/modules/plugins/database/src/test/java/org/rhq/plugins/database/H2DatabaseDiscovery.java
@@ -0,0 +1,46 @@
+package org.rhq.plugins.database;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.jetbrains.annotations.Nullable;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
+import org.rhq.core.pluginapi.inventory.ManualAddFacet;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+import org.rhq.core.system.ProcessInfo;
+
+public class H2DatabaseDiscovery implements ResourceDiscoveryComponent<ResourceComponent<?>>, ManualAddFacet<ResourceComponent<?>> {
+
+ @Override
+ public Set<DiscoveredResourceDetails> discoverResources(
+ ResourceDiscoveryContext<ResourceComponent<?>> context) {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public DiscoveredResourceDetails discoverResource(Configuration pluginConfiguration,
+ ResourceDiscoveryContext<ResourceComponent<?>> context)
+ throws InvalidPluginConfigurationException {
+
+ String version = "";
+ DiscoveredResourceDetails details = createResourceDetails(context, pluginConfiguration,
+ version, null);
+ return details;
+
+ }
+
+ private static DiscoveredResourceDetails createResourceDetails(ResourceDiscoveryContext discoveryContext,
+ Configuration pluginConfig, String version, @Nullable
+ ProcessInfo processInfo) {
+ String key = pluginConfig.getSimpleValue("url", "");
+ String name = key;
+ String description = "Database " + version + " (" + key + ")";
+ return new DiscoveredResourceDetails(discoveryContext.getResourceType(), key, name, version, description,
+ pluginConfig, processInfo);
+ }
+
+}
diff --git a/modules/plugins/database/src/test/java/org/rhq/plugins/database/PluginTest.java b/modules/plugins/database/src/test/java/org/rhq/plugins/database/PluginTest.java
new file mode 100644
index 0000000..4ce8107
--- /dev/null
+++ b/modules/plugins/database/src/test/java/org/rhq/plugins/database/PluginTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.plugins.database;
+
+import java.sql.Connection;
+import java.util.List;
+import java.util.Map;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.resource.ResourceType;
+import org.testng.annotations.Test;
+import org.testng.AssertJUnit;
+
+@Test
+public class PluginTest extends ComponentTest {
+
+ public void test() throws Exception {
+ H2Database db = (H2Database)manuallyAdd("H2 Database");
+ assertUp(db);
+ Connection connection = db.getConnection();
+ connection.prepareStatement("create table sometable(a int, b int)").execute();
+ connection.prepareStatement("insert into sometable values(42, 54)").execute();
+ ResourceType rt = resourceTypes.get("Generic Query");
+ Configuration configuration = getConfiguration(rt);
+ CustomTableComponent ctc = (CustomTableComponent) manuallyAdd(rt, configuration, db);
+ MeasurementReport report = getMeasurementReport(ctc);
+ assertAll(report, getResourceDescriptor("Generic Query"));
+ List<Map<String, Object>> grid = DatabaseQueryUtility.getGridValues(db, "select a, b from sometable");
+ assert grid.size() == 1;
+ Map<String, Object> map = grid.get(0);
+ AssertJUnit.assertEquals(42, map.get("A"));
+ }
+
+}
diff --git a/modules/plugins/database/src/test/resources/META-INF/rhq-plugin.xml b/modules/plugins/database/src/test/resources/META-INF/rhq-plugin.xml
new file mode 100644
index 0000000..1e8f7d1
--- /dev/null
+++ b/modules/plugins/database/src/test/resources/META-INF/rhq-plugin.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<plugin name="H2"
+ displayName="H2 Database"
+ description="Plugin supporting H2 database"
+ package="org.rhq.plugins.database"
+ pluginLifecycleListener="DatabasePluginLifecycleListener"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:c="urn:xmlns:rhq-configuration"
+ xmlns="urn:xmlns:rhq-plugin">
+
+ <depends plugin="Database" useClasses="true"/>
+
+ <server name="H2 Database" class="org.rhq.plugins.database.H2Database" discovery="org.rhq.plugins.database.H2DatabaseDiscovery">
+ <plugin-configuration>
+ <c:simple-property name="url" type="string" default="jdbc:h2:mem:"/>
+ <c:simple-property name="username" type="string" default="sa"/>
+ <c:simple-property name="password" type="string" default=""/>
+ </plugin-configuration>
+
+ </server>
+
+ <service name="Generic Query" class="org.rhq.plugins.database.CustomTableComponent"
+ discovery="org.rhq.plugins.database.CustomTableDiscoveryComponent"
+ description="Query the database for various results"
+ supportsManualAdd="true" singleton="false"
+ createDeletePolicy="both">
+
+ <runs-inside>
+ <parent-resource-type name="H2 Database" plugin="H2"/>
+ </runs-inside>
+
+ <plugin-configuration>
+ <c:simple-property name="metricQuery" type="string" default="select a, b from sometable"/>
+ <c:simple-property name="column" type="boolean" default="true"/>
+ </plugin-configuration>
+ <metric property="A" displayName="A results" displayType="summary"
+ description="Number appearing in A column"
+ units="none" dataType="measurement"/>
+ <metric property="B" displayName="B results" displayType="summary"
+ description="Number appearing in B column"
+ units="none" dataType="measurement"/>
+ </service>
+
+
+</plugin>
+
commit cb5bd253f36a04710b2906f89429d36b9f9a1b8a
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu Jul 5 12:26:50 2012 -0700
[BZ 815305] Min/max constraints on PropertyList not honored. Change IntegerItems to SpinnerItems on configuration screens making sure validations still work as SpinnerItem validations is little different than IntegerItems.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
index 9932499..4e188dd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
@@ -52,24 +52,8 @@ import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.ValuesManager;
import com.smartgwt.client.widgets.form.events.ItemChangedEvent;
import com.smartgwt.client.widgets.form.events.ItemChangedHandler;
-import com.smartgwt.client.widgets.form.fields.ButtonItem;
-import com.smartgwt.client.widgets.form.fields.CanvasItem;
-import com.smartgwt.client.widgets.form.fields.CheckboxItem;
-import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
-import com.smartgwt.client.widgets.form.fields.FloatItem;
-import com.smartgwt.client.widgets.form.fields.FormItem;
-import com.smartgwt.client.widgets.form.fields.IntegerItem;
-import com.smartgwt.client.widgets.form.fields.PasswordItem;
-import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
-import com.smartgwt.client.widgets.form.fields.SelectItem;
-import com.smartgwt.client.widgets.form.fields.SpacerItem;
-import com.smartgwt.client.widgets.form.fields.StaticTextItem;
-import com.smartgwt.client.widgets.form.fields.TextAreaItem;
-import com.smartgwt.client.widgets.form.fields.TextItem;
-import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
-import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
-import com.smartgwt.client.widgets.form.fields.events.FocusEvent;
-import com.smartgwt.client.widgets.form.fields.events.FocusHandler;
+import com.smartgwt.client.widgets.form.fields.*;
+import com.smartgwt.client.widgets.form.fields.events.*;
import com.smartgwt.client.widgets.form.validator.CustomValidator;
import com.smartgwt.client.widgets.form.validator.FloatRangeValidator;
import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator;
@@ -134,6 +118,7 @@ import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableSectionStack
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableToolStrip;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableWindow;
+import sun.net.www.content.image.png;
/**
* A SmartGWT widget for editing an RHQ {@link Configuration} that conforms to a {@link ConfigurationDefinition}.
@@ -1031,13 +1016,13 @@ public class ConfigurationEditor extends LocatableVLayout {
toolStrip.setWidth100();
if (!propertyReadOnly) {
IButton addRowButton = new IButton();
- addRowButton.setIcon(Window.getImgURL("[SKIN]/actions/add.png"));
- addRowButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
- public void onClick(ClickEvent clickEvent) {
- displayMapEditor(summaryTable, null, propertyDefinitionList, propertyList,
- memberPropertyDefinitionMap, null, mapReadOnly);
- }
- });
+ addRowButton.setIcon(Window.getImgURL(ImageManager.getAddIcon()));
+ addRowButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
+ public void onClick(ClickEvent clickEvent) {
+ displayMapEditor(summaryTable, null, propertyDefinitionList, propertyList,
+ memberPropertyDefinitionMap, null, mapReadOnly);
+ }
+ });
toolStrip.addMember(addRowButton);
}
@@ -1341,15 +1326,10 @@ public class ConfigurationEditor extends LocatableVLayout {
valueItem = radioGroupItem;
break;
case INTEGER:
- // Ideally, we'd use SpinnerItems for INTEGER props, but unfortunately, as of version 2.4, SmartGWT
- // has a nasty bug where it does not fire ValueChangedEvents or ItemChangedEvents when the value of
- // a SpinnerItem changes...
- /*SpinnerItem spinnerItem = new SpinnerItem();
+ SpinnerItem spinnerItem = new SpinnerItem();
spinnerItem.setMin(Integer.MIN_VALUE);
spinnerItem.setMax(Integer.MAX_VALUE);
- // TODO: If an integer constraint is defined on the propdef, use that to set the min and max.
- valueItem = spinnerItem;*/
- valueItem = new IntegerItem();
+ valueItem = spinnerItem;
break;
case FLOAT:
case DOUBLE:
@@ -1378,6 +1358,25 @@ public class ConfigurationEditor extends LocatableVLayout {
}
}
});
+ // Since spinnerItems only fire ChangedEvent once the spinner buttons are pushed
+ // we add blur handler to pick up any changes to that field when leaving
+ if(valueItem instanceof SpinnerItem){
+ valueItem.addBlurHandler(new BlurHandler() {
+ @Override
+ public void onBlur(BlurEvent event) {
+ updatePropertySimpleValue(event.getItem(), event.getItem().getValue(), propertySimple,
+ propertyDefinitionSimple);
+ // Only fire a prop value change event if the prop's a top-level simple or a simple within a
+ // top-level map.
+ if (shouldFireEventOnPropertyValueChange(event.getItem(), propertyDefinitionSimple,
+ propertySimple)) {
+ boolean isValid = event.getItem().validate();
+ firePropertyChangedEvent(propertySimple, propertyDefinitionSimple, isValid);
+ }
+
+ }
+ });
+ }
}
}
commit 21ca86fc1c1be1d5c4108918d965b03119ec9895
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Thu Jul 5 09:09:13 2012 -0400
[BZ 828938] fix typo and add thread identification.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
index e1883e4..0470d9b 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
@@ -700,13 +700,14 @@ public class PluginContainer {
rebootListener.reboot();
}
});
+ rebootThread.setName("Plugin Container Reboot Thread");
rebootThread.setDaemon(false);
rebootThread.start();
try {
rebootThread.join();
} catch (InterruptedException e) {
log.error("Interrupted while rebooting agent after one or more resource types "
- + " have been marked for deletion. You man need to manually reboot the agent/plugin container to purge "
+ + " have been marked for deletion. You may need to manually reboot the agent/plugin container to purge "
+ "stale types.");
}
}
commit 2e121e658b517b35ccb8752ff4a8c0489d14d90b
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Jul 4 18:44:51 2012 +0200
Use the correct language name for the javascript language.
diff --git a/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/client/security/test/JndiAccessTest.java b/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/client/security/test/JndiAccessTest.java
index f96b081..302fa10 100644
--- a/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/client/security/test/JndiAccessTest.java
+++ b/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/client/security/test/JndiAccessTest.java
@@ -196,7 +196,8 @@ public class JndiAccessTest extends AbstractEJB3Test {
PermissionCollection perms = new StandardScriptPermissions();
- return ScriptEngineFactory.getSecuredScriptEngine("JavaScript", new PackageFinder(Collections.<File>emptyList()), bindings, perms);
+ return ScriptEngineFactory.getSecuredScriptEngine("javascript",
+ new PackageFinder(Collections.<File> emptyList()), bindings, perms);
}
private static void checkIsDesiredSecurityException(ScriptException e) {
diff --git a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
index 8ca0b39..98246a0 100644
--- a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
+++ b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
@@ -71,7 +71,7 @@ import org.rhq.scripting.ScriptSourceProviderFactory;
*/
public class CliSender extends AlertSender<CliComponent> {
- private static final String ENGINE_NAME = "JavaScript";
+ private static final String ENGINE_NAME = "javascript";
private static final int MAX_RESULT_SIZE = 4000;
commit f94c0df7851ee1ae64cb0995abf75ed9ec93cf32
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Jul 4 18:44:20 2012 +0200
LocalClient now generates proxies inside a privileged block to correctly
work in the restricted environment of the RHQ server where we disallow
the scripts to do "unattended" JNDI lookups against the RHQ server.
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
index 7f8efad..5cbed7e 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
@@ -97,19 +97,24 @@ public class LocalClient implements RhqFacade {
}
@Override
- public <T> T getProxy(Class<T> remoteApiIface) {
- RhqManager manager = RhqManager.forInterface(remoteApiIface);
+ public <T> T getProxy(final Class<T> remoteApiIface) {
+ final RhqManager manager = RhqManager.forInterface(remoteApiIface);
if (manager == null) {
throw new IllegalArgumentException("Unknown remote interface " + remoteApiIface);
}
- Object localSLSB = getLocalSLSB(manager);
+ return AccessController.doPrivileged(new PrivilegedAction<T>() {
+ @Override
+ public T run() {
+ Object localSLSB = getLocalSLSB(manager);
- Object proxy = Proxy.newProxyInstance(remoteApiIface.getClassLoader(), new Class<?>[] { remoteApiIface },
- new LocalClientProxy(localSLSB, this, manager));
+ Object proxy = Proxy.newProxyInstance(remoteApiIface.getClassLoader(),
+ new Class<?>[] { remoteApiIface }, new LocalClientProxy(localSLSB, LocalClient.this, manager));
- return remoteApiIface.cast(proxy);
+ return remoteApiIface.cast(proxy);
+ }
+ });
}
private Object getScriptingProxy(Object slsb, RhqManager manager) {
commit b63714a7093588f7688c196e649e5003b7cdf701
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Jul 4 18:41:51 2012 +0200
Fixed a problem with copying annotations with no attributes.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
index dc29bc9..dc07d4e 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
@@ -229,15 +229,17 @@ public class InterfaceSimplifier {
Annotation ret = new Annotation(annotation.getTypeName(), constPool);
- for (Object m : annotation.getMemberNames()) {
- final String memberName = (String) m;
+ if (annotation.getMemberNames() != null) {
+ for (Object m : annotation.getMemberNames()) {
+ final String memberName = (String) m;
- MemberValue origValue = annotation.getMemberValue(memberName);
- final MemberValue[] newValue = new MemberValue[1];
+ MemberValue origValue = annotation.getMemberValue(memberName);
+ final MemberValue[] newValue = new MemberValue[1];
- origValue.accept(new ArrayIndexAssigningVisitor(newValue, 0, constPool));
+ origValue.accept(new ArrayIndexAssigningVisitor(newValue, 0, constPool));
- ret.addMemberValue(memberName, newValue[0]);
+ ret.addMemberValue(memberName, newValue[0]);
+ }
}
return ret;
commit fd22cb9644d17d43d876945f34689492bcf84c9b
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Jul 4 18:41:20 2012 +0200
Fixing the build. The RHQ's javascript language module now bundles
Rhino in the jar itself to ease the deployment, added the javascript module
as a test dep to a number of modules that have tests utilizing scripting.
diff --git a/modules/enterprise/binding/pom.xml b/modules/enterprise/binding/pom.xml
index 945b4bc..7d37053 100644
--- a/modules/enterprise/binding/pom.xml
+++ b/modules/enterprise/binding/pom.xml
@@ -209,6 +209,20 @@
<artifactId>javassist</artifactId>
</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>
+
</dependencies>
<build>
diff --git a/modules/enterprise/remoting/cli/pom.xml b/modules/enterprise/remoting/cli/pom.xml
index ae77f1e..3924ff0 100644
--- a/modules/enterprise/remoting/cli/pom.xml
+++ b/modules/enterprise/remoting/cli/pom.xml
@@ -163,19 +163,6 @@
</plugin>
<plugin>
- <artifactId>maven-jar-plugin</artifactId>
- <configuration>
- <includes>
- <include>org/rhq/**</include>
- <include>client-messages*</include>
- </includes>
- <archive>
- <index>true</index>
- </archive>
- </configuration>
- </plugin>
-
- <plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
diff --git a/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml b/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
index 202bef7..808bd82 100644
--- a/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
+++ b/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
@@ -70,7 +70,6 @@
<copy file="${settings.localRepository}/org/rhq/rhq-scripting-api/${project.version}/rhq-scripting-api-${project.version}.jar" tofile="${lib.home}/rhq-scripting-api-${project.version}.jar" verbose="true" />
<copy file="${settings.localRepository}/org/rhq/rhq-scripting-javascript/${project.version}/rhq-scripting-javascript-${project.version}.jar" tofile="${lib.home}/rhq-scripting-javascript-${project.version}.jar" verbose="true" />
- <copy file="${settings.localRepository}/org/mozilla/rhino/${rhino.version}/rhino-${rhino.version}.jar" tofile="${lib.home}/rhino-${rhino.version}.jar" verbose="true" />
</target>
<target name="prepare-samples-dir">
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index e813d3b..11f3784 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -1,205 +1,230 @@
-<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-scripting-parent</artifactId>
- <groupId>org.rhq</groupId>
- <version>4.5.0-SNAPSHOT</version>
- </parent>
- <artifactId>rhq-scripting-javascript</artifactId>
- <version>4.5.0-SNAPSHOT</version>
- <name>RHQ Javascript support</name>
- <description>Provides RHQ scripting in Javascript using Rhino</description>
+<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-scripting-parent</artifactId>
+ <groupId>org.rhq</groupId>
+ <version>4.5.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>rhq-scripting-javascript</artifactId>
+ <version>4.5.0-SNAPSHOT</version>
+ <name>RHQ Javascript support</name>
+ <description>Provides RHQ scripting in Javascript using Rhino</description>
- <dependencies>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>rhq-scripting-api</artifactId>
- <version>${project.version}</version>
- </dependency>
-
- <dependency>
- <groupId>org.mozilla</groupId>
- <artifactId>rhino</artifactId>
- <version>1.7R3</version>
- </dependency>
-
-<!-- we no longer depend on Phobos because we now bundle the Phobos script engine with
- our own modifications.
- <dependency>
- <groupId>com.sun.phobos</groupId>
- <artifactId>phobos-js</artifactId>
- <version>0.6.2</version>
- <exclusions>
- <exclusion>
- <groupId>com.sun.phobos</groupId>
- <artifactId>phobos-rhino</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- -->
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
- <argLine>-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>
- </plugin>
- </plugins>
- </build>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-scripting-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
- <profiles>
+ <dependency>
+ <groupId>org.mozilla</groupId>
+ <artifactId>rhino</artifactId>
+ <version>1.7R3</version>
+ </dependency>
- <profile>
- <id>dev</id>
+ </dependencies>
- <properties>
- <rhq.rootDir>../../..</rhq.rootDir>
- <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
- <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/lib</rhq.deploymentDir>
- </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.sonatype.plugins</groupId>
+ <artifactId>jarjar-maven-plugin</artifactId>
+ <version>1.5</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>jarjar</goal>
+ </goals>
+ <configuration>
+ <includes>
+ <include>org.mozilla:rhino</include>
+ </includes>
+ <rules>
+ <keep>
+ <pattern>*.**</pattern>
+ </keep>
+ </rules>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
- <build>
- <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+ <argLine>-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>
+ </plugin>
+ </plugins>
+ </build>
- <plugin>
- <artifactId>maven-antrun-plugin</artifactId>
- <version>1.1</version>
- <executions>
+ <profiles>
- <execution>
- <id>deploy</id>
- <phase>compile</phase>
- <configuration>
- <tasks>
- <mkdir dir="${rhq.deploymentDir}" />
- <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
- <echo>*** Updating
- ${deployment.file}...</echo>
- <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
- </tasks>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
+ <profile>
+ <id>dev</id>
- <execution>
- <id>undeploy</id>
- <phase>clean</phase>
- <configuration>
- <tasks>
- <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
- <echo>*** Deleting
- ${deployment.file}...</echo>
- <delete file="${deployment.file}" />
- </tasks>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
+ <properties>
+ <rhq.rootDir>../../..</rhq.rootDir>
+ <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+ <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/lib</rhq.deploymentDir>
+ </properties>
- </executions>
- </plugin>
- </plugins>
- </build>
- </profile>
+ <build>
+ <plugins>
- <profile>
- <id>cobertura-plugins</id>
- <activation>
- <activeByDefault>false</activeByDefault>
- </activation>
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-antrun-plugin</artifactId>
- <dependencies>
- <dependency>
- <groupId>net.sourceforge.cobertura</groupId>
- <artifactId>cobertura</artifactId>
- <version>1.9.4.1</version>
- </dependency>
- </dependencies>
- <executions>
- <execution>
- <id>cobertura-instrument</id>
- <phase>pre-integration-test</phase>
- <configuration>
- <tasks>
- <!-- prepare directory structure
- for cobertura -->
- <mkdir dir="target/cobertura" />
- <mkdir dir="target/cobertura/backup" />
- <!-- backup all classes so that we
- can instrument the original classes -->
- <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
- <fileset dir="target/classes">
- <include name="**/*.class" />
- </fileset>
- </copy>
- <!-- create a properties file and
- save there location of cobertura data file -->
- <touch file="target/classes/cobertura.properties" />
- <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
- <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
- <!-- instrument all classes in target/classes
- directory -->
- <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser" todir="${project.build.directory}/classes">
- <fileset dir="${project.build.directory}/classes">
- <include name="**/*.class" />
- </fileset>
- </cobertura-instrument>
- </tasks>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- <execution>
- <id>cobertura-report</id>
- <phase>post-integration-test</phase>
- <configuration>
- <tasks>
- <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
- <!-- prepare directory structure
- for cobertura -->
- <mkdir dir="target/cobertura" />
- <mkdir dir="target/site/cobertura" />
- <!-- restore classes from backup
- folder to classes folder -->
- <copy toDir="target/classes" verbose="true" overwrite="true">
- <fileset dir="target/cobertura/backup">
- <include name="**/*.class" />
- </fileset>
- </copy>
- <!-- delete backup folder -->
- <delete dir="target/cobertura/backup" />
- <!-- create a code coverage report -->
- <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser" destdir="${project.build.directory}/site/cobertura">
- <fileset dir="${basedir}/src/main/java">
- <include name="**/*.java" />
- </fileset>
- </cobertura-report>
- <!-- delete cobertura.properties
- file -->
- <delete file="target/classes/cobertura.properties" />
- </tasks>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </profile>
- </profiles>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.1</version>
+ <executions>
+
+ <execution>
+ <id>deploy</id>
+ <phase>compile</phase>
+ <configuration>
+ <tasks>
+ <mkdir dir="${rhq.deploymentDir}" />
+ <property name="deployment.file"
+ location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Updating
+ ${deployment.file}...</echo>
+ <jar destfile="${deployment.file}"
+ basedir="${project.build.outputDirectory}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>undeploy</id>
+ <phase>clean</phase>
+ <configuration>
+ <tasks>
+ <property name="deployment.file"
+ location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Deleting
+ ${deployment.file}...</echo>
+ <delete file="${deployment.file}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+
+ <profile>
+ <id>cobertura-plugins</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>net.sourceforge.cobertura</groupId>
+ <artifactId>cobertura</artifactId>
+ <version>1.9.4.1</version>
+ </dependency>
+ </dependencies>
+ <executions>
+ <execution>
+ <id>cobertura-instrument</id>
+ <phase>pre-integration-test</phase>
+ <configuration>
+ <tasks>
+ <!-- prepare directory structure for cobertura -->
+ <mkdir dir="target/cobertura" />
+ <mkdir dir="target/cobertura/backup" />
+ <!-- backup all classes so that we can instrument
+ the original classes -->
+ <copy toDir="target/cobertura/backup"
+ verbose="true" overwrite="true">
+ <fileset dir="target/classes">
+ <include name="**/*.class" />
+ </fileset>
+ </copy>
+ <!-- create a properties file and save there
+ location of cobertura data file -->
+ <touch
+ file="target/classes/cobertura.properties" />
+ <echo
+ file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
+ <taskdef classpathref="maven.plugin.classpath"
+ resource="tasks.properties" />
+ <!-- instrument all classes in target/classes
+ directory -->
+ <cobertura-instrument
+ datafile="${project.build.directory}/cobertura/cobertura.ser"
+ todir="${project.build.directory}/classes">
+ <fileset
+ dir="${project.build.directory}/classes">
+ <include name="**/*.class" />
+ </fileset>
+ </cobertura-instrument>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>cobertura-report</id>
+ <phase>post-integration-test</phase>
+ <configuration>
+ <tasks>
+ <taskdef classpathref="maven.plugin.classpath"
+ resource="tasks.properties" />
+ <!-- prepare directory structure for cobertura -->
+ <mkdir dir="target/cobertura" />
+ <mkdir dir="target/site/cobertura" />
+ <!-- restore classes from backup folder to
+ classes folder -->
+ <copy toDir="target/classes" verbose="true"
+ overwrite="true">
+ <fileset dir="target/cobertura/backup">
+ <include name="**/*.class" />
+ </fileset>
+ </copy>
+ <!-- delete backup folder -->
+ <delete dir="target/cobertura/backup" />
+ <!-- create a code coverage report -->
+ <cobertura-report format="html"
+ datafile="${project.build.directory}/cobertura/cobertura.ser"
+ destdir="${project.build.directory}/site/cobertura">
+ <fileset dir="${basedir}/src/main/java">
+ <include name="**/*.java" />
+ </fileset>
+ </cobertura-report>
+ <!-- delete cobertura.properties file -->
+ <delete
+ file="target/classes/cobertura.properties" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
</project>
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index 46ec595..10b613e 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -97,6 +97,12 @@
</dependency>
<dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-scripting-javascript</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-server-client-api</artifactId>
<version>${project.version}</version>
diff --git a/modules/enterprise/server/itests/pom.xml b/modules/enterprise/server/itests/pom.xml
index 3f3f03f..43a14c8 100644
--- a/modules/enterprise/server/itests/pom.xml
+++ b/modules/enterprise/server/itests/pom.xml
@@ -99,6 +99,13 @@
<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>
commit b70072126da6810a1fc96d6e33cbd100c438e369
Author: Elias Ross <genman(a)noderunner.net>
Date: Wed Jul 4 14:19:46 2012 +0200
BZ 797356 - Allow to disable automatic table discovery per database
diff --git a/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlDatabaseDiscoveryComponent.java b/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlDatabaseDiscoveryComponent.java
index c8f8673..100e536 100644
--- a/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlDatabaseDiscoveryComponent.java
+++ b/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlDatabaseDiscoveryComponent.java
@@ -61,7 +61,7 @@ public class MySqlDatabaseDiscoveryComponent implements ResourceDiscoveryCompone
while (resultSet.next()) {
String databaseName = resultSet.getString(1);
- Configuration config = new Configuration();
+ Configuration config = context.getDefaultPluginConfiguration();
config.put(new PropertySimple("databaseName",databaseName));
DiscoveredResourceDetails details =
new DiscoveredResourceDetails(
diff --git a/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlTableDiscoveryComponent.java b/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlTableDiscoveryComponent.java
index 5b62118..4d7b354 100644
--- a/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlTableDiscoveryComponent.java
+++ b/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlTableDiscoveryComponent.java
@@ -35,11 +35,12 @@ import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
import org.rhq.plugins.database.DatabaseQueryUtility;
/**
- *
+ * Discovers MySQL tables.
* @author Steve Millidge (C2B2 Consulting Limited)
*/
public class MySqlTableDiscoveryComponent implements ResourceDiscoveryComponent {
+ private static final String TABLE_DISCOVERY = "tableDiscovery";
private Log log = LogFactory.getLog(this.getClass());
@Override
@@ -47,6 +48,14 @@ public class MySqlTableDiscoveryComponent implements ResourceDiscoveryComponent
HashSet<DiscoveredResourceDetails> set = new HashSet<DiscoveredResourceDetails>();
MySqlDatabaseComponent parent = (MySqlDatabaseComponent)rdc.getParentResourceComponent();
+ Configuration pconfig = rdc.getParentResourceContext().getPluginConfiguration();
+ // If the user has disabled table discovery on the parent, we don't autodiscover
+ // them, as we may hit temporary ones that go away any time soon again
+ // See BZ-797356
+ if (!Boolean.parseBoolean(pconfig.getSimpleValue(TABLE_DISCOVERY, "true"))) {
+ log.debug("table discovery disabled");
+ return set;
+ }
Connection conn = parent.getConnection();
if (conn != null) {
diff --git a/modules/plugins/mysql/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/mysql/src/main/resources/META-INF/rhq-plugin.xml
index 439370e..a2986e9 100644
--- a/modules/plugins/mysql/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/mysql/src/main/resources/META-INF/rhq-plugin.xml
@@ -335,6 +335,7 @@
<service name="Database" class="MySqlDatabaseComponent" discovery="MySqlDatabaseDiscoveryComponent">
<plugin-configuration>
<c:simple-property name="databaseName" displayName="Database Name" readOnly="true" />
+ <c:simple-property name="tableDiscovery" displayName="Table Discovery" readOnly="false" type="boolean" default="true"/>
</plugin-configuration>
<operation name="invokeSql" description="Execute arbitrary SQL">
diff --git a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
new file mode 100644
index 0000000..1e5b9e8
--- /dev/null
+++ b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
@@ -0,0 +1,545 @@
+package org.rhq.plugins.mysql;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertTrue;
+import static org.testng.AssertJUnit.fail;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import javax.xml.bind.JAXBElement;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
+import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
+import org.rhq.core.clientapi.descriptor.configuration.ConfigurationProperty;
+import org.rhq.core.clientapi.descriptor.plugin.MetricDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.ResourceDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.ServerDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.ServiceDescriptor;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+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.resource.ProcessScan;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pc.PluginContainer;
+import org.rhq.core.pc.PluginContainerConfiguration;
+import org.rhq.core.pc.availability.AvailabilityContextImpl;
+import org.rhq.core.pc.content.ContentContextImpl;
+import org.rhq.core.pc.event.EventContextImpl;
+import org.rhq.core.pc.event.EventManager;
+import org.rhq.core.pc.inventory.ResourceContainer;
+import org.rhq.core.pc.operation.OperationContextImpl;
+import org.rhq.core.pluginapi.availability.AvailabilityContext;
+import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
+import org.rhq.core.pluginapi.content.ContentContext;
+import org.rhq.core.pluginapi.event.EventContext;
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
+import org.rhq.core.pluginapi.inventory.ProcessScanResult;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+import org.rhq.core.pluginapi.operation.OperationContext;
+import org.rhq.core.system.ProcessInfo;
+import org.rhq.core.system.SystemInfo;
+import org.rhq.core.system.SystemInfoFactory;
+import org.rhq.core.system.pquery.ProcessInfoQuery;
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeSuite;
+
+/**
+ * Base class for RHQ Component Testing.
+ * Initializes a plugin configuration.
+ *
+ * Methods to override:
+ *
+ * {@link #setConfiguration(Configuration, ResourceType)}
+ */
+public abstract class ComponentTest {
+
+ /**
+ * Logging component.
+ */
+ protected final Log log = LogFactory.getLog(getClass());
+
+ private static File temp = new File(System.getProperty("java.io.tmpdir"));
+
+ /**
+ * Associates a resource component with a resource.
+ */
+ protected Map<ResourceComponent, Resource> components = new LinkedHashMap<ResourceComponent, Resource>();
+
+ /**
+ * Associates a name of a resource with a resource descriptor.
+ */
+ protected Map<String, ResourceDescriptor> descriptors = new LinkedHashMap<String, ResourceDescriptor>();
+
+ /**
+ * Associates a name of a resource with a type.
+ * This is useful for manually adding resources.
+ *
+ * @see #manuallyAdd(ResourceType, Configuration)
+ */
+ protected Map<String, ResourceType> resourceTypes = new LinkedHashMap<String, ResourceType>();
+
+ /**
+ * Event manager; used to obtain events.
+ */
+ private EventManager eventManager;
+
+ private PluginContainer pluginContainer = PluginContainer.getInstance();
+
+ private SystemInfo systemInfo = SystemInfoFactory.createSystemInfo();
+
+ /**
+ * Scan all processes before starting; false will disable this feature.
+ * Disabling is suggested for running tests against a remote instance.
+ */
+ private boolean processScan = true;
+
+ // TODO
+
+ private final PluginMetadataManager pmm = new PluginMetadataManager();
+ private final File temporaryDirectory = temp;
+ private final File dataDirectory = temp;
+ private final String pluginContainerName = "rhq";
+ private final OperationContext operationContext = new OperationContextImpl(0);
+ private final ContentContext contentContext = new ContentContextImpl(0);
+ private final Executor availCollectorThreadPool = Executors.newCachedThreadPool();
+ private PluginContainerDeployment pluginContainerDeployment = null;
+ private Resource platform;
+ private ResourceContainer platformContainer;
+ private List<ProcessInfo> processInfo = Collections.emptyList();
+ private PluginDescriptor pluginDescriptor;
+
+ /**
+ * Constructs a new component test.
+ */
+ protected ComponentTest() {
+ }
+
+ /**
+ * Initializes the plugin container.
+ * This is run before {@link #before()}.
+ */
+ @BeforeSuite
+ protected void beforeSuite() {
+ // Speed up propagation of events by adjusting delay/period to 1 second
+ PluginContainerConfiguration pcc = new PluginContainerConfiguration();
+ pcc.setEventSenderInitialDelay(1);
+ pcc.setEventSenderPeriod(1);
+ pluginContainer.setConfiguration(pcc);
+ pluginContainer.initialize();
+ eventManager = pluginContainer.getEventManager();
+ platform = pluginContainer.getInventoryManager().getPlatform();
+ platformContainer = pluginContainer.getInventoryManager().getResourceContainer(platform);
+ if (platformContainer == null) {
+ platformContainer = new ResourceContainer(platform, getClass().getClassLoader());
+ }
+ }
+
+ /**
+ * Initializes all plugins defined in the system; using auto-discovery where possible.
+ * This is run once per test class.
+ */
+ @BeforeClass
+ protected void before() throws Exception {
+ if (processScan) {
+ processInfo = getProcessInfos();
+ if (processInfo == null)
+ processInfo = Collections.emptyList();
+ log.debug("Process Info " + processInfo);
+ for (ProcessInfo i : processInfo) {
+ log.debug(i.getBaseName() + " " + Arrays.toString(i.getCommandLine()));
+ }
+ }
+ Enumeration<URL> e = getClass().getClassLoader().getResources("META-INF/rhq-plugin.xml");
+ List<URL> l = Collections.list(e);
+ Collections.sort(l, new Comparator<URL>() {
+ @Override
+ public int compare(URL u1, URL u2) {
+ return u2.toString().compareTo(u1.toString());
+ }
+ });
+ for (URL url : l) {
+ log.debug("parse " + url);
+ InputStream is = url.openStream();
+ PluginDescriptor pd = AgentPluginDescriptorUtil.parsePluginDescriptor(is);
+ processPluginDescriptor(pd);
+ log.debug("pmm names " + pmm.getPluginNames());
+ buildDesc(pd.getServers());
+ buildDesc(pd.getServices());
+ is.close();
+ }
+ }
+
+ @AfterSuite
+ protected void afterSuite() {
+ pluginContainer.shutdown();
+ }
+
+ /**
+ * Process a plugin descriptor.
+ */
+ private void processPluginDescriptor(PluginDescriptor pd) throws Exception {
+ this.pluginDescriptor = pd;
+ Set<ResourceType> types = pmm.loadPlugin(pd);
+ mapResourceTypeNames(types);
+ log.info("Resource types: " + resourceTypes);
+ resources(types, platform, platformContainer.getResourceComponent(), platformContainer.getResourceContext());
+ log.info("ResourceComponent map: " + components);
+ }
+
+ private void mapResourceTypeNames(Set<ResourceType> types) {
+ for (ResourceType type : types) {
+ this.resourceTypes.put(type.getName(), type);
+ mapResourceTypeNames(type.getChildResourceTypes());
+ }
+ }
+
+ /**
+ * Manually create a component by name.
+ */
+ public ResourceComponent manuallyAdd(String name) throws Exception {
+ ResourceType resourceType = resourceTypes.get(name);
+ if (resourceType == null)
+ throw new IllegalStateException("no type " + name);
+ Configuration configuration = resourceType.getPluginConfigurationDefinition().getDefaultTemplate().createConfiguration();
+ setConfiguration(configuration, resourceType);
+ return manuallyAdd(resourceType, configuration);
+ }
+
+ /**
+ * Manually create a component by resource type.
+ */
+ public ResourceComponent manuallyAdd(ResourceType type, Configuration configuration) throws Exception {
+ return manuallyAdd(type, configuration, platformContainer.getResourceComponent());
+ }
+
+ /**
+ * Manually create a component by resource type, configuration, parent.
+ */
+ public ResourceComponent manuallyAdd(ResourceType type, Configuration configuration, ResourceComponent parent) throws Exception {
+ DiscoveredResourceDetails drd = new DiscoveredResourceDetails(type,
+ "key", "name", "ver", "desc", configuration, (ProcessInfo) null);
+ ResourceDiscoveryComponent c = null;
+ return createChild(drd, platform, configuration, parent, c);
+ }
+
+ private ResourceComponent createChild(DiscoveredResourceDetails drd,
+ Resource resource,
+ Configuration configuration,
+ ResourceComponent parentComponent,
+ ResourceDiscoveryComponent rdc) throws Exception
+ {
+ ResourceType type = pmm.getType(drd.getResourceType());
+
+ Resource cresource = new Resource();
+ cresource.setResourceType(type);
+ cresource.setPluginConfiguration(configuration);
+ cresource.setResourceKey(drd.getResourceKey());
+ cresource.setParentResource(resource);
+ cresource.setName(drd.getResourceName());
+ cresource.setVersion(drd.getResourceVersion());
+
+ String rclassname = pmm.getComponentClass(type);
+ ResourceComponent component = (ResourceComponent) Class.forName(rclassname).newInstance();
+
+ AvailabilityContext availContext = new AvailabilityContextImpl(cresource,availCollectorThreadPool);
+
+ EventContext eventContext = new EventContextImpl(resource);
+ ResourceContext context = new ResourceContext(cresource, parentComponent,
+ null, rdc, systemInfo, temporaryDirectory, dataDirectory,
+ pluginContainerName, eventContext, operationContext, contentContext,
+ availContext, pluginContainerDeployment);
+
+ component.start(context);
+ components.put(component, cresource);
+ resources(type.getChildResourceTypes(), cresource, component, context);
+ return component;
+ }
+
+ private void resources(Set<ResourceType> types, Resource parent, ResourceComponent component, ResourceContext context) throws Exception {
+ for (ResourceType type : types) {
+ String s = pmm.getDiscoveryClass(type);
+ if (s == null) {
+ throw new NullPointerException("no discovery " + type);
+ }
+ ResourceDiscoveryComponent rdc = (ResourceDiscoveryComponent) Class.forName(s).newInstance();
+ log.debug("rdc=" + rdc);
+ List<Configuration> configList = new ArrayList<Configuration>();
+ ResourceDiscoveryContext resourceDiscoveryContext = new ResourceDiscoveryContext(type, component,
+ context, systemInfo,
+ performProcessScans(type), configList,
+ pluginContainerName, pluginContainerDeployment);
+ Set<DiscoveredResourceDetails> drds = rdc.discoverResources(resourceDiscoveryContext);
+ for (DiscoveredResourceDetails drd : drds) {
+ log.debug("discovered " + drd);
+ ResourceType resourceType = drd.getResourceType();
+ setConfiguration(drd.getPluginConfiguration(), resourceType);
+ createChild(drd, parent, drd.getPluginConfiguration(), component, rdc);
+ }
+ if (drds.isEmpty()) {
+ log.warn("not discovered " + type);
+ context.getPluginConfiguration();
+ }
+ }
+
+ }
+
+ /**
+ * Called before the configuration is processed; override to set specific plugin parameters.
+ */
+ protected void setConfiguration(Configuration configuration, ResourceType resourceType) {
+ }
+
+ /**
+ * Stops all components, stops the plugin container.
+ */
+ @AfterTest
+ protected void after() throws Exception {
+ for (ResourceComponent c : components.keySet())
+ c.stop();
+ PluginContainer.getInstance().shutdown();
+ }
+
+ /**
+ * Returns a measurement report.
+ */
+ public MeasurementReport getMeasurementReport(ResourceComponent component) throws Exception {
+ Resource resource = this.components.get(component);
+ ResourceType type = resource.getResourceType();
+ MeasurementReport report = new MeasurementReport();
+ Set<MeasurementScheduleRequest> s = new HashSet<MeasurementScheduleRequest>();
+ for (MeasurementDefinition md : type.getMetricDefinitions())
+ s.add(new MeasurementScheduleRequest(new MeasurementSchedule(md, resource)));
+ ((MeasurementFacet)component).getValues(report, s);
+ return report;
+ }
+
+ /**
+ * Returns the first resource component by resource name, then looks by matching resource type name,
+ * then asserts failure if not found.
+ */
+ public ResourceComponent getComponent(String name) {
+ for (Map.Entry<ResourceComponent, Resource> c : components.entrySet())
+ if (c.getValue().getName().equals(name))
+ return c.getKey();
+ for (Map.Entry<ResourceComponent, Resource> c : components.entrySet())
+ if (c.getValue().getResourceType().getName().equals(name))
+ return c.getKey();
+ fail("component not found " + name + " in " + components.entrySet());
+ return null;
+ }
+
+ /**
+ * Returns a resource matching this component.
+ */
+ public Resource getResource(ResourceComponent rc) {
+ Resource r = components.get(rc);
+ if (r == null)
+ throw new IllegalStateException();
+ return r;
+ }
+
+ /**
+ * Returns a resource matching this name.
+ */
+ public Resource getResource(String name) {
+ return getResource(getComponent(name));
+ }
+
+ /**
+ * Builds a new configuration for a resource type.
+ */
+ public Configuration getConfiguration(ResourceType resourceType) {
+ Configuration configuration = resourceType.getPluginConfigurationDefinition().getDefaultTemplate().createConfiguration();
+ setConfiguration(configuration, resourceType);
+ return configuration;
+ }
+
+ // ASSERT METHOD
+
+ /**
+ * From a measurement report, returns a measurement value, or asserts failure if no such value exists.
+ */
+ public static Double getValue(MeasurementReport report, String name) {
+ for (MeasurementDataNumeric m: report.getNumericData()) {
+ if (m.getName().equals(name)) {
+ return m.getValue();
+ }
+ }
+ fail("report does not incude " + name + " report " + report.getNumericData());
+ return null;
+ }
+
+ /**
+ * Asserts the resource component is available.
+ */
+ public static void assertUp(ResourceComponent component) {
+ assertEquals("up " + component, AvailabilityType.UP, component.getAvailability());
+ }
+
+ /**
+ * Asserts the resource component is unavailable.
+ */
+ public static void assertDown(ResourceComponent component) {
+ assertEquals("down " + component, AvailabilityType.DOWN, component.getAvailability());
+ }
+
+ /**
+ * Sets a configuration option.
+ */
+ public static void set(Configuration config, String name, String value) {
+ PropertySimple s = config.getSimple(name);
+ if (s == null) {
+ s = new PropertySimple(name, value);
+ config.put(s);
+ } else {
+ s.setStringValue(value);
+ }
+ }
+
+ private List<ProcessScanResult> performProcessScans(ResourceType serverType) {
+ List<ProcessScanResult> scanResults = new ArrayList<ProcessScanResult>();
+ Set<ProcessScan> processScans = serverType.getProcessScans();
+ log.debug("Executing process scans for server type " + serverType + "...");
+ ProcessInfoQuery piq = new ProcessInfoQuery(processInfo);
+ for (ProcessScan processScan : processScans) {
+ List<ProcessInfo> queryResults = piq.query(processScan.getQuery());
+ for (ProcessInfo autoDiscoveredProcess : queryResults) {
+ scanResults.add(new ProcessScanResult(processScan, autoDiscoveredProcess));
+ log.info("Process scan auto-detected new server resource: scan=[" + processScan
+ + "], discovered-process=[" + autoDiscoveredProcess + "]");
+ }
+ }
+ return scanResults;
+ }
+
+ /**
+ * AutoDiscoveryExecutor method.
+ */
+ private List<ProcessInfo> getProcessInfos() {
+ SystemInfo systemInfo = SystemInfoFactory.createSystemInfo();
+ log.debug("Retrieving process table...");
+ long startTime = System.currentTimeMillis();
+ List<ProcessInfo> processInfos = null;
+ try {
+ processInfos = systemInfo.getAllProcesses();
+ } catch (UnsupportedOperationException uoe) {
+ log.debug("Cannot perform process scan - not supported on this platform. (" + systemInfo.getClass() + ")");
+ }
+ long elapsedTime = System.currentTimeMillis() - startTime;
+ log.debug("Retrieval of process table took " + elapsedTime + " ms.");
+ return processInfos;
+ }
+
+ /**
+ * Returns the plugin descriptor.
+ */
+ public PluginDescriptor getPluginDescriptor() {
+ return pluginDescriptor;
+ }
+
+ /**
+ * Returns the plugin descriptor.
+ */
+ public ResourceDescriptor getResourceDescriptor(String name) {
+ ResourceDescriptor rd = descriptors.get(name);
+ if (rd == null)
+ throw new IllegalStateException("no descriptor " + name + " in " + descriptors.keySet());
+ return rd;
+ }
+
+ private void buildDesc(List<? extends ResourceDescriptor> l) {
+ for (ResourceDescriptor rd : l) {
+ descriptors.put(rd.getName(), rd);
+ if (rd instanceof ServerDescriptor) {
+ buildDesc(((ServerDescriptor)rd).getServers());
+ buildDesc(((ServerDescriptor)rd).getServices());
+ }
+ if (rd instanceof ServiceDescriptor) {
+ buildDesc(((ServiceDescriptor)rd).getServices());
+ buildDesc(((ServiceDescriptor)rd).getServices());
+ }
+ }
+ }
+
+ /**
+ * Asserts that all measurements in the report are present
+ * according to the resource descriptor.
+ *
+ * @see #getResourceDescriptor(String) for obtaining this.
+ * @param report
+ */
+ public static void assertAll(MeasurementReport report, ResourceDescriptor l) {
+ HashMap<String, MetricDescriptor> map = new HashMap<String, MetricDescriptor>();
+ for (MetricDescriptor md : l.getMetric()) {
+ map.put(md.getProperty(), md);
+ }
+ for (MeasurementDataNumeric n : report.getNumericData()) {
+ map.remove(n.getName());
+ }
+ for (MeasurementDataTrait n : report.getTraitData()) {
+ map.remove(n.getName());
+ }
+ assertTrue("Measurements not found " + map.keySet(), map.isEmpty());
+ }
+
+ /**
+ * Returns the event manager.
+ */
+ public EventManager getEventManager() {
+ return eventManager;
+ }
+
+ /**
+ * Set to false to avoid scanning local machine processes to speed up testing.
+ */
+ public void setProcessScan(boolean processScan) {
+ this.processScan = processScan;
+ }
+
+ public void assertAll(ConfigurationFacet cf, ResourceDescriptor rd) throws Exception {
+ Configuration config = cf.loadResourceConfiguration();
+ List<JAXBElement<? extends ConfigurationProperty>> templates = rd.getResourceConfiguration().getConfigurationProperty();
+ for (JAXBElement<? extends ConfigurationProperty> template : templates) {
+ String name = template.getValue().getName();
+ // Property property = config.get(name);
+ assertNotNull("config contains " + name, config.get(name));
+ Object value = config.getSimpleValue(name, null);
+ assertNotNull("value for " + name, value);
+ log.debug("config found " + name + " value " + value );
+ }
+ }
+
+}
diff --git a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java
new file mode 100644
index 0000000..3f35c65
--- /dev/null
+++ b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java
@@ -0,0 +1,41 @@
+package org.rhq.plugins.mysql;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.testng.annotations.Test;
+
+/**
+ * Tests MySql Server.
+ */
+@Test
+public class PluginTest extends ComponentTest {
+
+ String host = System.getProperty("host", "localhost");
+ String principal = System.getProperty("principal", "mysql");
+ String credentials = System.getProperty("credentials", "");
+ String rtn = "MySql Server";
+
+ {
+ setProcessScan(false);
+ }
+
+ @Override
+ protected void setConfiguration(Configuration c, ResourceType resourceType) {
+ if (resourceType.getName().equals(rtn)) {
+ c.getSimple("host").setStringValue(host);
+ c.getSimple("principal").setStringValue(principal);
+ c.getSimple("credentials").setStringValue(credentials);
+ }
+ if (resourceType.getName().equals("Database")) {
+ c.getSimple("tableDiscovery").setBooleanValue(false);
+ }
+ }
+
+ public void test() throws Exception {
+ manuallyAdd("MySql Server");
+ ResourceComponent resource = getComponent("MySql Server");
+ assertUp(resource);
+ }
+
+}
diff --git a/modules/plugins/mysql/src/test/resources/log4j.xml b/modules/plugins/mysql/src/test/resources/log4j.xml
new file mode 100644
index 0000000..69a897c
--- /dev/null
+++ b/modules/plugins/mysql/src/test/resources/log4j.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<!-- tests configuration that only dumps WARN or higher messages due to appender threadhold -->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
+
+ <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+ <param name="Threshold" value="ERROR"/>
+ <param name="Target" value="System.out"/>
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%t] (%c{5}) - %m%n"/>
+ </layout>
+ </appender>
+
+ <appender name="FILE" class="org.apache.log4j.FileAppender">
+ <param name="File" value="target/test.log"/>
+ <param name="Threshold" value="DEBUG"/>
+ <param name="Append" value="false"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %d{dd-MM HH:mm:ss,SSS} (%F:%M:%L) -%m%n"/>
+ </layout>
+ </appender>
+
+ <category name="org.jboss.on">
+ <priority value="DEBUG"/>
+ </category>
+
+ <root>
+ <appender-ref ref="CONSOLE"/>
+ <appender-ref ref="FILE"/>
+ </root>
+
+</log4j:configuration>
commit 005484491e18d138e1c58c5f65a330abf435bbe4
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Jul 4 09:46:11 2012 +0200
BZ 797331 - If a network adapter is down on plugin component start, mark it as disabled.
diff --git a/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/NetworkAdapterComponent.java b/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/NetworkAdapterComponent.java
index 774dd08..72cea4e 100644
--- a/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/NetworkAdapterComponent.java
+++ b/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/NetworkAdapterComponent.java
@@ -1,99 +1,106 @@
-/*
- * 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.plugins.platform;
-
-import java.net.InetAddress;
-import java.util.List;
-import java.util.Set;
-
-import org.rhq.core.domain.measurement.AvailabilityType;
-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.core.pluginapi.inventory.ResourceComponent;
-import org.rhq.core.pluginapi.inventory.ResourceContext;
-import org.rhq.core.pluginapi.measurement.MeasurementFacet;
-import org.rhq.core.pluginapi.util.ObjectUtil;
-import org.rhq.core.system.NetworkAdapterInfo;
-import org.rhq.core.system.NetworkAdapterStats;
-
-public class NetworkAdapterComponent implements ResourceComponent<PlatformComponent>, MeasurementFacet {
- //private final Log log = LogFactory.getLog(NetworkAdapterComponent.class);
-
- private ResourceContext<PlatformComponent> context;
-
- public void start(ResourceContext<PlatformComponent> resourceContext) {
- this.context = resourceContext;
- }
-
- public void stop() {
- }
-
- public AvailabilityType getAvailability() {
- if (getInfo().getOperationalStatus() == NetworkAdapterInfo.OperationState.UP) {
- return AvailabilityType.UP;
- }
-
- return AvailabilityType.DOWN;
- }
-
- private NetworkAdapterInfo getInfo() {
- for (NetworkAdapterInfo info : this.context.getSystemInformation().getAllNetworkAdapters()) {
- if (context.getResourceKey().equals(info.getName())) {
- return info;
- }
- }
-
- throw new RuntimeException("Could not find network adapter info [" + context.getResourceKey() + "]");
- }
-
- public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) {
- NetworkAdapterInfo info = getInfo();
- NetworkAdapterStats stats = this.context.getSystemInformation().getNetworkAdapterStats(info.getName());
-
- for (MeasurementScheduleRequest request : metrics) {
- String property = request.getName();
-
- if (property.startsWith("Trait.net4.address")) // TODO
- { // this trait is supported regardless of having native support or not
- List<InetAddress> addrs = info.getUnicastAddresses();
- String ifAddrs = (addrs.size() > 0) ? addrs.get(0).getHostAddress() : "";
- for (int i = 1; i < addrs.size(); i++) {
- ifAddrs += "," + addrs.get(i).getHostAddress();
- }
-
- report.addData(new MeasurementDataTrait(request, ifAddrs));
- } else if (property.equals("Trait.interfaceFlags")) {
- report.addData(new MeasurementDataTrait(request, info.getAllFlags()));
- } else {
- Number number = ((Number) ObjectUtil.lookupAttributeProperty(stats, request.getName()));
- if (number != null) {
- report.addData(new MeasurementDataNumeric(request, number.doubleValue()));
- }
- }
- }
-
- return;
- }
+/*
+ * 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.plugins.platform;
+
+import java.net.InetAddress;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.domain.measurement.AvailabilityType;
+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.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+import org.rhq.core.pluginapi.util.ObjectUtil;
+import org.rhq.core.system.NetworkAdapterInfo;
+import org.rhq.core.system.NetworkAdapterStats;
+
+public class NetworkAdapterComponent implements ResourceComponent<PlatformComponent>, MeasurementFacet {
+ private final Log log = LogFactory.getLog(NetworkAdapterComponent.class);
+
+ private ResourceContext<PlatformComponent> context;
+
+ public void start(ResourceContext<PlatformComponent> resourceContext) {
+ this.context = resourceContext;
+ if (getInfo().getOperationalStatus()==NetworkAdapterInfo.OperationState.DOWN) {
+ context.getAvailabilityContext().disable();
+ log.info("Disabled " + context.getResourceKey() + " as it was down on start");
+ }
+ }
+
+ public void stop() {
+ }
+
+ public AvailabilityType getAvailability() {
+ if (getInfo().getOperationalStatus() == NetworkAdapterInfo.OperationState.UP) {
+ return AvailabilityType.UP;
+ }
+
+ return AvailabilityType.DOWN;
+ }
+
+ private NetworkAdapterInfo getInfo() {
+ for (NetworkAdapterInfo info : this.context.getSystemInformation().getAllNetworkAdapters()) {
+ if (context.getResourceKey().equals(info.getName())) {
+ return info;
+ }
+ }
+
+ throw new RuntimeException("Could not find network adapter info [" + context.getResourceKey() + "]");
+ }
+
+ public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) {
+ NetworkAdapterInfo info = getInfo();
+ NetworkAdapterStats stats = this.context.getSystemInformation().getNetworkAdapterStats(info.getName());
+
+ for (MeasurementScheduleRequest request : metrics) {
+ String property = request.getName();
+
+ if (property.startsWith("Trait.net4.address")) // TODO
+ { // this trait is supported regardless of having native support or not
+ List<InetAddress> addrs = info.getUnicastAddresses();
+ String ifAddrs = (addrs.size() > 0) ? addrs.get(0).getHostAddress() : "";
+ for (int i = 1; i < addrs.size(); i++) {
+ ifAddrs += "," + addrs.get(i).getHostAddress();
+ }
+
+ report.addData(new MeasurementDataTrait(request, ifAddrs));
+ } else if (property.equals("Trait.interfaceFlags")) {
+ report.addData(new MeasurementDataTrait(request, info.getAllFlags()));
+ } else {
+ Number number = ((Number) ObjectUtil.lookupAttributeProperty(stats, request.getName()));
+ if (number != null) {
+ report.addData(new MeasurementDataNumeric(request, number.doubleValue()));
+ }
+ }
+ }
+
+ return;
+ }
}
\ No newline at end of file
commit 0a0c9a990684675cecf7b0dbef03a6a37bc20432
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Tue Jul 3 16:59:03 2012 -0400
[BZ 828938] make sure reboot listener persists when agent is running in background.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
index 3515c55..e1883e4 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
@@ -693,7 +693,22 @@ public class PluginContainer {
}
public void notifyRebootRequestListener() {
- rebootListener.reboot();
+ //BZ 828938: the thread needs to run as non-daemon so that it's allowed to complete cleanup in daemon mode
+ Thread rebootThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ rebootListener.reboot();
+ }
+ });
+ rebootThread.setDaemon(false);
+ rebootThread.start();
+ try {
+ rebootThread.join();
+ } catch (InterruptedException e) {
+ log.error("Interrupted while rebooting agent after one or more resource types "
+ + " have been marked for deletion. You man need to manually reboot the agent/plugin container to purge "
+ + "stale types.");
+ }
}
/**
commit fc82a357767f64e22356588cb5645f17fa626fc0
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Jul 3 16:05:35 2012 -0400
[BZ 836664] allow oracle plugin to connect using the "service name URL". Thanks go to Richard Hensman for the patch.
diff --git a/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleServerComponent.java b/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleServerComponent.java
index 3d70eef..3849657 100644
--- a/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleServerComponent.java
+++ b/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleServerComponent.java
@@ -24,8 +24,10 @@ import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.measurement.MeasurementDataNumeric;
@@ -128,7 +130,13 @@ public class OracleServerComponent implements DatabaseComponent, MeasurementFace
}
private static String buildUrl(Configuration configuration) {
- return "jdbc:oracle:thin:@" + configuration.getSimpleValue("host", "localhost") + ":"
- + configuration.getSimpleValue("port", "1521") + ":" + configuration.getSimpleValue("sid", "XE");
+ String connMethod = configuration.getSimpleValue("connectionMethod", "SID");
+ if (connMethod.equalsIgnoreCase("SID")) {
+ return "jdbc:oracle:thin:@" + configuration.getSimpleValue("host", "localhost") + ":"
+ + configuration.getSimpleValue("port", "1521") + ":" + configuration.getSimpleValue("sid", "XE");
+ } else {
+ return "jdbc:oracle:thin:@//" + configuration.getSimpleValue("host", "localhost") + ":"
+ + configuration.getSimpleValue("port", "1521") + "/" + configuration.getSimpleValue("sid", "XE");
+ }
}
}
\ No newline at end of file
diff --git a/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
index 27c9033..00f0284 100644
--- a/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
@@ -21,7 +21,16 @@
<plugin-configuration>
<c:simple-property name="host" default="localhost" displayName="Listen host" description="the hostname or IP address that the database is listening on"/>
<c:simple-property name="port" default="1521" displayName="Listen port" description="the TCP port that the database is listening on"/>
- <c:simple-property name="sid" default="XE" displayName="Database SID" description="the name of the database to connect to"/>
+
+ <c:simple-property name="connectionMethod" displayName="Connection Method" type="string" required="true" default="SID"
+ description="The method used to connect to Oracle; defaults to 'SID'.">
+ <c:property-options>
+ <c:option value="SID" name="SID"/>
+ <c:option value="SERVICENAME" name="Service name"/>
+ </c:property-options>
+ </c:simple-property>
+
+ <c:simple-property name="sid" default="XE" displayName="Database SID/Service name" description="SID or service name of the database to connect to"/>
<c:simple-property name="driverClass" default="oracle.jdbc.driver.OracleDriver" displayName="JDBC driver class"
description="the fully-qualified classname of the JDBC driver class" required="false"/>
commit a0b4f34693d070063c74c22dc463b34fd8b82cdf
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Jul 3 21:39:22 2012 +0200
Update RESTEasy to 2.3.4.Final and enable GZIP compression on some methods.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
index d602751..7c664b7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
@@ -60,8 +60,6 @@ import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
-import com.arjuna.ats.internal.jdbc.drivers.modifiers.list;
-
import org.jboss.cache.Fqn;
import org.rhq.core.domain.common.EntityContext;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
index 472fd1c..8ec3d82 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
@@ -45,6 +45,8 @@ import com.wordnik.swagger.annotations.ApiErrors;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
+import org.jboss.resteasy.annotations.GZIP;
+
import org.rhq.enterprise.server.rest.domain.Baseline;
import org.rhq.enterprise.server.rest.domain.MetricAggregate;
import org.rhq.enterprise.server.rest.domain.MetricSchedule;
@@ -65,6 +67,7 @@ public interface MetricHandlerLocal {
static String NO_RESOURCE_FOR_ID = "If no resource with the passed id exists";
static String NO_SCHEDULE_FOR_ID = "No schedule with the passed id exists";
+ @GZIP
@GET
@Path("data/{scheduleId}")
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
@@ -143,6 +146,7 @@ public interface MetricHandlerLocal {
* @param headers Injected HttpHeaders
* @return an encoded stream of numerical values
*/
+ @GZIP
@ApiOperation(value = "Expose the raw metrics of a single schedule. This can only expose raw data, which means the start date may "
+ "not be older than 7 days.")
@GET
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java
index 867a0e4..b30f8ce 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java
@@ -41,6 +41,7 @@ import com.wordnik.swagger.annotations.ApiError;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
+import org.jboss.resteasy.annotations.GZIP;
import org.jboss.resteasy.annotations.cache.Cache;
import org.jboss.resteasy.links.AddLinks;
import org.jboss.resteasy.links.LinkResource;
@@ -74,6 +75,7 @@ public interface ResourceHandlerLocal {
@Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo);
+ @GZIP
@GET
@Path("/platforms")
@Cache(isPrivate = true,maxAge = 300)
@@ -97,6 +99,7 @@ public interface ResourceHandlerLocal {
Response getAvailability(
@ApiParam("Id of the resource to query") @PathParam("id") int resourceId, @Context HttpHeaders headers);
+ @GZIP
@GET
@Path("/{id}/availability/history")
@ApiError(code = 404, reason = NO_RESOURCE_FOR_ID)
@@ -115,6 +118,7 @@ public interface ResourceHandlerLocal {
@ApiParam("Id of the resource to update") @PathParam("id") int resourceId,
@ApiParam(value= "New Availability setting", required = true) AvailabilityRest avail);
+ @GZIP
@GET
@Path("/{id}/schedules")
@LinkResource(rel="schedules",value = MetricSchedule.class)
@@ -130,6 +134,7 @@ public interface ResourceHandlerLocal {
@Context UriInfo uriInfo);
+ @GZIP
@GET
@Path("/{id}/children")
@LinkResource(rel="children", value = ResourceWithType.class)
@@ -141,6 +146,7 @@ public interface ResourceHandlerLocal {
@Context UriInfo uriInfo);
+ @GZIP
@AddLinks
@GET
@Path(("/{id}/alerts"))
diff --git a/modules/enterprise/server/jar/src/main/xsl/apiout2docbook.xsl b/modules/enterprise/server/jar/src/main/xsl/apiout2docbook.xsl
index f9a5f83..d97645a 100644
--- a/modules/enterprise/server/jar/src/main/xsl/apiout2docbook.xsl
+++ b/modules/enterprise/server/jar/src/main/xsl/apiout2docbook.xsl
@@ -97,6 +97,9 @@
</emphasis>
</simpara>
<simpara><xsl:value-of select="@description"/></simpara>
+ <xsl:if test="not(@gzip = '')">
+ <simpara>Supports returning a gzip'ed Content-Encoding</simpara>
+ </xsl:if>
<xsl:choose>
<xsl:when test="param">
<table>
diff --git a/modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl b/modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl
index dff70ba..4cf7d4f 100644
--- a/modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl
+++ b/modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl
@@ -87,6 +87,9 @@
</h3>
<em><xsl:value-of select="@description"/></em>
<br/>
+ <xsl:if test="not(@gzip = '')">
+ <p><em>Supports returning a gzip'ed Content-Encoding</em></p>
+ </xsl:if>
<xsl:choose>
<xsl:when test="param">
Parameters:
diff --git a/modules/helpers/rest-docs-generator/pom.xml b/modules/helpers/rest-docs-generator/pom.xml
index 4010747..b6be916 100644
--- a/modules/helpers/rest-docs-generator/pom.xml
+++ b/modules/helpers/rest-docs-generator/pom.xml
@@ -149,6 +149,11 @@
<version>1.1-SNAPSHOT</version>
</dependency>
<dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ <version>${resteasy.version}</version>
+ </dependency>
+ <dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${commons-logging.version}</version>
diff --git a/modules/helpers/rest-docs-generator/src/main/java/org/rhq/helpers/rest_docs_generator/ClassLevelProcessor.java b/modules/helpers/rest-docs-generator/src/main/java/org/rhq/helpers/rest_docs_generator/ClassLevelProcessor.java
index 8144273..a3a6ddf 100644
--- a/modules/helpers/rest-docs-generator/src/main/java/org/rhq/helpers/rest_docs_generator/ClassLevelProcessor.java
+++ b/modules/helpers/rest-docs-generator/src/main/java/org/rhq/helpers/rest_docs_generator/ClassLevelProcessor.java
@@ -47,6 +47,8 @@ import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import org.jboss.resteasy.annotations.GZIP;
+
/**
* Processor for JAX-RS classes
* @author Heiko W. Rupp
@@ -213,6 +215,10 @@ public class ClassLevelProcessor extends AbstractProcessor {
Element methodElement = doc.createElement("method");
methodElement.setAttribute("path",path);
+ GZIP gzip = td.getAnnotation(GZIP.class);
+ if (gzip!=null) {
+ methodElement.setAttribute("gzip","true");
+ }
classElement.appendChild(methodElement);
Name elementName = td.getSimpleName();
methodElement.setAttribute("name", elementName.toString());
diff --git a/pom.xml b/pom.xml
index 603b89d..8e99665 100644
--- a/pom.xml
+++ b/pom.xml
@@ -107,7 +107,7 @@
<augeas.zip.location>${settings.localRepository}/net/augeas/augeas-native/${augeas.version}</augeas.zip.location>
<augeas.zip.mask>*-${augeas.classifier}.zip</augeas.zip.mask>
<ant.contrib.version>1.0b3</ant.contrib.version>
- <resteasy.version>2.3.3.Final</resteasy.version>
+ <resteasy.version>2.3.4.Final</resteasy.version>
<freemarker.version>2.3.18</freemarker.version>
<powermock.version>1.4.11</powermock.version>
<arquillian.version>1.0.1.Final</arquillian.version>
commit 4412e1e77d7914f7712a4426cb36f86d769f53c6
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Jul 3 21:27:49 2012 +0200
A couple of changes in this commit:
1) RhqFacade.getManagers() returns a Map<RhqManager, Object> instead of
a Map<String, Object>. Strong typing is good.
2) ScriptSourceProviders hooked up with the ScriptEngineFactory and the
StandardBindings so that they can be installed into the script engine
and use the standard bindings or the rhq facade to do weird and wonderful
things. A couple of basic impls of the ScriptSourceProviders were
sprinkled about the codebase.
3) ScriptSourceProviders are now loadable from META-INF/services so that
it is easy for third parties to add their own impls.
4) A new method added to RepoManagerRemote that enables download of an
arbitrary package version from a repository (this is used by one of the
script source providers to remotely download a script from the server).
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
index fbaf1a7..9887958 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
@@ -40,11 +40,14 @@ import javax.script.ScriptException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.rhq.bindings.client.RhqManager;
+import org.rhq.bindings.util.MultiScriptSourceProvider;
import org.rhq.bindings.util.NoTopLevelIndirection;
import org.rhq.bindings.util.PackageFinder;
import org.rhq.scripting.CodeCompletion;
import org.rhq.scripting.ScriptEngineInitializer;
import org.rhq.scripting.ScriptEngineProvider;
+import org.rhq.scripting.ScriptSourceProvider;
/**
* This is RHQ specific imitation of ScriptEngineFactory.
@@ -117,26 +120,26 @@ public class ScriptEngineFactory {
* @param language the language of the script to instantiate
* @param packageFinder the package finder to find the standard packages in user provided locations
* @param bindings the initial standard bindings or null if none required
- * @return the initialized engine or null if the engine for given language isn't known.
+ *
+ * @return the initialized engine or null if a {@link ScriptEngineProvider} for given language isn't known.
*
* @throws ScriptException on error during initialization of the script environment
* @throws IOException if the package finder fails to find the packages
*/
- public static ScriptEngine getScriptEngine(String language, PackageFinder packageFinder, StandardBindings bindings)
- throws ScriptException, IOException {
-
- return getSecuredScriptEngine(language, packageFinder, bindings, null);
+ public static ScriptEngine getScriptEngine(String language, PackageFinder packageFinder, StandardBindings bindings) throws ScriptException, IOException {
+
+ return getSecuredScriptEngine(language, packageFinder, bindings, null);
}
/**
- * This method is similar to the {@link #getScriptEngine(String, PackageFinder, StandardBindings)} method
+ * This method is similar to the {@link #getScriptEngine(String, PackageFinder, StandardBindings, ScriptSourceProvider...)} method
* but additionally applies a security wrapper on the returned script engine so that the scripts execute
* with the provided java permissions.
*
- * @see #getScriptEngine(String, PackageFinder, StandardBindings)
+ * @see #getScriptEngine(String, PackageFinder, StandardBindings, ScriptSourceProvider...)
*/
- public static ScriptEngine getSecuredScriptEngine(final String language, final PackageFinder packageFinder,
- final StandardBindings bindings, final PermissionCollection permissions) throws ScriptException, IOException {
+ public static ScriptEngine getSecuredScriptEngine(String language, PackageFinder packageFinder,
+ StandardBindings bindings, PermissionCollection permissions) throws ScriptException, IOException {
ScriptEngineInitializer initializer = getInitializer(language);
@@ -144,9 +147,8 @@ public class ScriptEngineFactory {
return null;
}
- //TODO change this so that we support supplying a custom module source provider so that callers
- //have control over the location of the loadable scripts.
- ScriptEngine engine = initializer.instantiate(packageFinder.findPackages("org.rhq.core.domain"), null, permissions);
+ ScriptEngine engine = initializer.instantiate(packageFinder.findPackages("org.rhq.core.domain"),
+ permissions);
if (bindings != null) {
injectStandardBindings(engine, bindings, true);
@@ -162,10 +164,15 @@ public class ScriptEngineFactory {
* @param engine the engine
* @param bindings the bindings
* @param deleteExistingBindings true if the existing bindings should be replaced by the provided ones, false
- * if the provided bindings should be added to the existing ones (possibly overwriting bindings with the same name).
+ * if the provided bindings should be added to the existing ones (possibly overwriting bindings with the same name).
+ * @param scriptSourceProviders the list of script source providers to be used by the script engine to locate the scripts.
+ * Note that the providers become associated with the script engine and its bindings and therefore should
+ * not be used with any other script engine. If the providers implement the
+ * {@link StandardBindings.RhqFacadeChangeListener} interface, they will be automatically hooked up with the
+ * <code>bindings</code> so that the providers will get notified whenever the rhq facade changes.
*/
public static void injectStandardBindings(ScriptEngine engine, StandardBindings bindings,
- boolean deleteExistingBindings) {
+ boolean deleteExistingBindings, ScriptSourceProvider... scriptSourceProviders) {
bindings.preInject(engine);
Bindings engineBindings = deleteExistingBindings ? engine.createBindings() : engine
@@ -175,6 +182,28 @@ public class ScriptEngineFactory {
engineBindings.put(entry.getKey(), entry.getValue());
}
+ if (scriptSourceProviders != null) {
+ //first figure out which initializer to use with this script engine
+ String language = (String) engine.getFactory().getParameter(ScriptEngine.NAME);
+ ScriptEngineProvider engineProvider = KNOWN_PROVIDERS.get(language);
+ if (engineProvider == null) {
+ throw new IllegalArgumentException("The supplied script engine [" + engine + "] is not supported.");
+ }
+
+ ScriptEngineInitializer initializer = engineProvider.getInitializer();
+
+ ScriptSourceProvider provider = null;
+
+ for (ScriptSourceProvider p : scriptSourceProviders) {
+ if (p instanceof StandardBindings.RhqFacadeChangeListener) {
+ bindings.addRhqFacadeChangeListener((StandardBindings.RhqFacadeChangeListener) p);
+ }
+ }
+ provider = new MultiScriptSourceProvider(scriptSourceProviders);
+
+ initializer.installScriptSourceProvider(engine, provider);
+ }
+
engine.setBindings(engineBindings, ScriptContext.ENGINE_SCOPE);
bindings.postInject(engine);
@@ -186,12 +215,12 @@ public class ScriptEngineFactory {
* @param engine the engine
* @param keySet the binding keys to be removed
*/
- public static void removeBindings(ScriptEngine engine, Set<String> keySet) {
+ public static void removeBindings(ScriptEngine engine, Set<RhqManager> keySet) {
Bindings engineBindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
- for (String key : keySet) {
- engineBindings.remove(key);
+ for (RhqManager key : keySet) {
+ engineBindings.remove(key.name());
}
engine.setBindings(engineBindings, ScriptContext.ENGINE_SCOPE);
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
index 812b4ae..3e1e137 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
@@ -22,13 +22,15 @@ package org.rhq.bindings;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
-import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import org.rhq.bindings.client.ResourceClientFactory;
import org.rhq.bindings.client.RhqFacade;
+import org.rhq.bindings.client.RhqManager;
import org.rhq.bindings.export.Exporter;
import org.rhq.bindings.output.TabularWriter;
import org.rhq.bindings.util.ScriptAssert;
@@ -49,6 +51,14 @@ import org.rhq.core.domain.util.PageControl;
*/
public class StandardBindings extends HashMap<String, Object> {
+ /**
+ * A listener interface for objects that need to be aware of the fact that the
+ * RHQ facade associated with the bidings has changed.
+ */
+ public interface RhqFacadeChangeListener {
+ void rhqFacadeChanged(StandardBindings bindings);
+ }
+
private static final long serialVersionUID = 1L;
public static final String UNLIMITED_PC = "unlimitedPC";
@@ -60,7 +70,9 @@ public class StandardBindings extends HashMap<String, Object> {
public static final String PROXY_FACTORY = "ProxyFactory";
public static final String ASSERT = "Assert";
- private Map<String, Object> managers;
+ private Map<RhqManager, Object> managers;
+ private Set<RhqFacadeChangeListener> facadeChangeListeners;
+ private RhqFacade rhqFacade;
private static class CastingEntry<T> implements Map.Entry<String, T> {
@@ -90,6 +102,7 @@ public class StandardBindings extends HashMap<String, Object> {
}
public StandardBindings(PrintWriter output, RhqFacade rhqFacade) {
+ facadeChangeListeners = new HashSet<RhqFacadeChangeListener>();
PageControl pc = new PageControl();
pc.setPageNumber(-1);
@@ -110,8 +123,8 @@ public class StandardBindings extends HashMap<String, Object> {
public void setFacade(PrintWriter output, RhqFacade rhqFacade) {
// remove any existing managers
if (null != managers) {
- for (String manager : managers.keySet()) {
- remove(manager);
+ for (RhqManager manager : managers.keySet()) {
+ remove(manager.name());
}
managers.clear();
}
@@ -130,7 +143,26 @@ public class StandardBindings extends HashMap<String, Object> {
put(PROXY_FACTORY, null);
}
- putAll(managers);
+ for (Map.Entry<RhqManager, Object> entry : managers.entrySet()) {
+ put(entry.getKey().name(), entry.getValue());
+ }
+
+ this.rhqFacade = rhqFacade;
+
+ notifyFacadeChanged();
+ }
+
+ public RhqFacade getAssociatedRhqFacade() {
+ return rhqFacade;
+ }
+
+ public void addRhqFacadeChangeListener(RhqFacadeChangeListener listener) {
+ this.facadeChangeListeners.add(listener);
+ listener.rhqFacadeChanged(this);
+ }
+
+ public void removeRhqFacadeChangeListere(RhqFacadeChangeListener listener) {
+ this.facadeChangeListeners.remove(listener);
}
public void preInject(ScriptEngine scriptEngine) {
@@ -171,7 +203,7 @@ public class StandardBindings extends HashMap<String, Object> {
return castEntry(PROXY_FACTORY, ResourceClientFactory.class);
}
- public Map<String, Object> getManagers() {
+ public Map<RhqManager, Object> getManagers() {
//XXX ideally this should be a projection into our map
return (null == managers) ? managers = Collections.emptyMap() : managers;
}
@@ -196,4 +228,10 @@ public class StandardBindings extends HashMap<String, Object> {
return new CastingEntry<T>(entry, clazz);
}
+
+ private void notifyFacadeChanged() {
+ for (RhqFacadeChangeListener listener : facadeChangeListeners) {
+ listener.rhqFacadeChanged(this);
+ }
+ }
}
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
index b975436..2f80f0c 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
@@ -47,7 +47,7 @@ public interface RhqFacade {
*
* @return a map of all available proxied managers keyed by their names.
*/
- Map<String, Object> getScriptingAPI();
+ Map<RhqManager, Object> getScriptingAPI();
/**
* Unlike the {@link #getScriptingAPI()} method that returns objects with modified signatures
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java
new file mode 100644
index 0000000..d90403d
--- /dev/null
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java
@@ -0,0 +1,63 @@
+/*
+ * 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.bindings.script;
+
+import java.io.Reader;
+import java.net.URI;
+
+import org.rhq.scripting.ScriptSourceProvider;
+
+/**
+ * @author Lukas Krejci
+ */
+public abstract class BaseRhqSchemeScriptSourceProvider implements ScriptSourceProvider {
+
+ public static final String SCHEME = "rhq";
+
+ @Override
+ public Reader getScriptSource(URI scriptUri) {
+ if (scriptUri == null || !SCHEME.equals(scriptUri.getScheme())) {
+ return null;
+ }
+
+ String path = scriptUri.getSchemeSpecificPart();
+
+ if (!path.startsWith("//")) {
+ return null;
+ }
+
+ return doGetScriptSource(scriptUri);
+ }
+
+ /**
+ * Implement this method to provide the script source.
+ * The base implementation of the {@link #getScriptSource(URI)} method
+ * only checks that the scheme of the URI is "rhq" and that the scheme
+ * specific part starts with "//".
+ *
+ * @param scriptUri
+ * @return the reader of the script or null if the script could not be
+ * found using the URI
+ *
+ * @see #getScriptSource(URI)
+ */
+ protected abstract Reader doGetScriptSource(URI scriptUri);
+}
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/RepoScriptSourceProvider.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/RepoScriptSourceProvider.java
new file mode 100644
index 0000000..b316dea
--- /dev/null
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/RepoScriptSourceProvider.java
@@ -0,0 +1,127 @@
+/*
+ * 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.bindings.script;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.bindings.StandardBindings;
+import org.rhq.bindings.client.RhqFacade;
+import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.content.composite.PackageAndLatestVersionComposite;
+import org.rhq.core.domain.criteria.PackageCriteria;
+import org.rhq.core.domain.criteria.RepoCriteria;
+import org.rhq.enterprise.server.content.ContentManagerRemote;
+import org.rhq.enterprise.server.content.RepoManagerRemote;
+
+/**
+ * The implementation of script source provider that is able to locate the script files
+ * in the repositories on the RHQ server.
+ * <p>
+ * The URI looks like:<br>
+ * <code>
+ * rhq://repositories/repositoryName/scriptFile
+ * </code>
+ *
+ * @author Lukas Krejci
+ */
+public class RepoScriptSourceProvider extends BaseRhqSchemeScriptSourceProvider implements
+ StandardBindings.RhqFacadeChangeListener {
+
+ private static final Log LOG = LogFactory.getLog(RepoScriptSourceProvider.class);
+
+ private static final String PREFIX = "//repositories/";
+
+ private RhqFacade rhqFacade;
+
+ @Override
+ public void rhqFacadeChanged(StandardBindings bindings) {
+ this.rhqFacade = bindings.getAssociatedRhqFacade();
+ }
+
+ @Override
+ protected Reader doGetScriptSource(URI scriptUri) {
+ if (rhqFacade == null) {
+ return null;
+ }
+
+ String path = scriptUri.getSchemeSpecificPart();
+
+ if (!path.startsWith(PREFIX)) {
+ return null;
+ }
+
+ path = path.substring(PREFIX.length());
+
+ int slashIdx = path.indexOf('/');
+
+ if (slashIdx == -1) {
+ return null;
+ }
+
+ String repoName = path.substring(0, slashIdx);
+ String scriptName = path.substring(slashIdx + 1);
+
+ try {
+ RepoManagerRemote repoManager = rhqFacade.getProxy(RepoManagerRemote.class);
+
+ RepoCriteria repoCrit = new RepoCriteria();
+ repoCrit.addFilterName(repoName);
+ List<Repo> repos = repoManager.findReposByCriteria(rhqFacade.getSubject(), repoCrit);
+
+ if (repos.isEmpty()) {
+ return null;
+ }
+
+ ContentManagerRemote contentManager = rhqFacade.getProxy(ContentManagerRemote.class);
+
+ for (Repo repo : repos) {
+ PackageCriteria pCrit = new PackageCriteria();
+ pCrit.addFilterName(scriptName);
+ pCrit.addFilterRepoId(repo.getId());
+
+ List<PackageAndLatestVersionComposite> pvs = contentManager.findPackagesWithLatestVersion(
+ rhqFacade.getSubject(), pCrit);
+
+ if (!pvs.isEmpty()) {
+ PackageAndLatestVersionComposite pv = pvs.get(0);
+
+ byte[] bytes = repoManager.getPackageVersionBytes(rhqFacade.getSubject(), repo.getId(), pv
+ .getLatestPackageVersion().getId());
+
+ return new InputStreamReader(new ByteArrayInputStream(bytes), Charset.forName("UTF-8"));
+ }
+ }
+ } catch (Exception e) {
+ LOG.debug("Failed to download bytes for the script: " + scriptUri.toString(), e);
+ }
+
+ return null;
+ }
+
+}
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/MultiScriptSourceProvider.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/MultiScriptSourceProvider.java
new file mode 100644
index 0000000..072e70f
--- /dev/null
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/MultiScriptSourceProvider.java
@@ -0,0 +1,66 @@
+/*
+ * 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.bindings.util;
+
+import java.io.Reader;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.rhq.scripting.ScriptSourceProvider;
+
+/**
+ * An implementation of the script source provider that uses a collection of another
+ * providers to locate the scripts.
+ * <p>
+ * The providers are tried in the order they were supplied to the constructor of this class
+ * and the first script source provider that manages to provide a non-null reader for
+ * given URI "wins".
+ *
+ * @author Lukas Krejci
+ */
+public class MultiScriptSourceProvider implements ScriptSourceProvider {
+
+ private Collection<ScriptSourceProvider> providers;
+
+ public MultiScriptSourceProvider(Collection<? extends ScriptSourceProvider> providers) {
+ this.providers = new ArrayList<ScriptSourceProvider>(providers);
+ }
+
+ public MultiScriptSourceProvider(ScriptSourceProvider... providers) {
+ this.providers = new ArrayList<ScriptSourceProvider>(Arrays.asList(providers));
+ }
+
+ @Override
+ public Reader getScriptSource(URI scriptUri) {
+
+ for (ScriptSourceProvider provider : providers) {
+ Reader rdr = provider.getScriptSource(scriptUri);
+ if (rdr != null) {
+ return rdr;
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/modules/enterprise/binding/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider b/modules/enterprise/binding/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
new file mode 100644
index 0000000..4d0472e
--- /dev/null
+++ b/modules/enterprise/binding/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
@@ -0,0 +1 @@
+org.rhq.bindings.script.RepoScriptSourceProvider
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java
index d42f3e1..39cb145 100644
--- a/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java
@@ -23,6 +23,7 @@ import java.util.Collections;
import java.util.Map;
import org.rhq.bindings.client.RhqFacade;
+import org.rhq.bindings.client.RhqManager;
import org.rhq.core.domain.auth.Subject;
public class FakeRhqFacade implements RhqFacade {
@@ -43,7 +44,7 @@ public class FakeRhqFacade implements RhqFacade {
return false;
}
- public Map<String, Object> getScriptingAPI() {
+ public Map<RhqManager, Object> getScriptingAPI() {
return Collections.emptyMap();
}
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/script/RepoScriptSourceProviderTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/script/RepoScriptSourceProviderTest.java
new file mode 100644
index 0000000..db3953a
--- /dev/null
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/script/RepoScriptSourceProviderTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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.bindings.script;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.Reader;
+import java.lang.reflect.Field;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.rhq.bindings.StandardBindings;
+import org.rhq.bindings.client.RhqFacade;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.content.composite.PackageAndLatestVersionComposite;
+import org.rhq.core.domain.criteria.PackageCriteria;
+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.content.ContentManagerRemote;
+import org.rhq.enterprise.server.content.RepoManagerRemote;
+
+/**
+ * @author Lukas Krejci
+ */
+@Test
+public class RepoScriptSourceProviderTest {
+
+ private static final String SCRIPT_CONTENTS = "java.lang.System.out.println('This works!');";
+ private static final String CORRECT_REPO_NAME = "my-repo";
+ private static final int CORRECT_REPO_ID = 1;
+ private static final String CORRECT_PACKAGE_NAME = "my-script.js";
+ private static final int CORRECT_PACKAGE_VERSION_ID = 2;
+
+ public void testCanDownloadScript() throws Exception {
+ RhqFacade rhqFacade = mock(RhqFacade.class);
+
+ RepoManagerRemote repoManager = mock(RepoManagerRemote.class);
+ ContentManagerRemote contentManager = mock(ContentManagerRemote.class);
+
+ when(rhqFacade.getProxy(RepoManagerRemote.class)).thenReturn(repoManager);
+ when(rhqFacade.getProxy(ContentManagerRemote.class)).thenReturn(contentManager);
+
+ when(repoManager.findReposByCriteria(any(Subject.class), any(RepoCriteria.class))).then(
+ new Answer<List<Repo>>() {
+ @Override
+ public List<Repo> answer(InvocationOnMock invocation) throws Throwable {
+ RepoCriteria crit = (RepoCriteria) invocation.getArguments()[1];
+
+ //this is so wrong...
+ Field f = RepoCriteria.class.getDeclaredField("filterName");
+ f.setAccessible(true);
+ String name = (String) f.get(crit);
+
+ if (CORRECT_REPO_NAME.equals(name)) {
+ Repo repo = new Repo(CORRECT_REPO_NAME);
+ repo.setId(CORRECT_REPO_ID);
+
+ PageList<Repo> ret = new PageList<Repo>(PageControl.getUnlimitedInstance());
+ ret.add(repo);
+ return ret;
+ } else {
+ return new PageList<Repo>(PageControl.getUnlimitedInstance());
+ }
+ }
+ });
+
+ when(contentManager.findPackagesWithLatestVersion(any(Subject.class), any(PackageCriteria.class))).then(
+ new Answer<List<PackageAndLatestVersionComposite>>() {
+ @Override
+ public List<PackageAndLatestVersionComposite> answer(InvocationOnMock invocation) throws Throwable {
+ PackageCriteria crit = (PackageCriteria) invocation.getArguments()[1];
+
+ //this is so wrong...
+ Field f = PackageCriteria.class.getDeclaredField("filterName");
+ f.setAccessible(true);
+ String name = (String) f.get(crit);
+
+ if (CORRECT_PACKAGE_NAME.equals(name)) {
+ PackageAndLatestVersionComposite composite = new PackageAndLatestVersionComposite();
+
+ composite
+ .setGeneralPackage(new org.rhq.core.domain.content.Package(CORRECT_PACKAGE_NAME, null));
+
+ PackageVersion pv = new PackageVersion();
+ pv.setId(CORRECT_PACKAGE_VERSION_ID);
+
+ composite.setLatestPackageVersion(pv);
+
+ PageList<PackageAndLatestVersionComposite> ret = new PageList<PackageAndLatestVersionComposite>(
+ PageControl.getUnlimitedInstance());
+ ret.add(composite);
+ return ret;
+ } else {
+ return new PageList<PackageAndLatestVersionComposite>(PageControl.getUnlimitedInstance());
+ }
+ }
+ });
+
+ when(repoManager.getPackageVersionBytes(any(Subject.class), anyInt(), anyInt())).then(
+ new Answer<byte[]>() {
+ @Override
+ public byte[] answer(InvocationOnMock invocation) throws Throwable {
+ int repoId = (Integer) invocation.getArguments()[1];
+ int packageId = (Integer) invocation.getArguments()[2];
+
+ if (repoId == CORRECT_REPO_ID && packageId == CORRECT_PACKAGE_VERSION_ID) {
+ return SCRIPT_CONTENTS.getBytes(Charset.forName("UTF-8"));
+ } else {
+ //TODO throw exceptions as the original method does
+ return null;
+ }
+ }
+ });
+
+ RepoScriptSourceProvider provider = new RepoScriptSourceProvider();
+ provider.rhqFacadeChanged(new StandardBindings(null, rhqFacade));
+
+ URI uri = new URI("rhq://repositories/" + CORRECT_REPO_NAME + "/" + CORRECT_PACKAGE_NAME);
+
+ Reader rdr = provider.getScriptSource(uri);
+
+ StringBuilder bld = new StringBuilder();
+ int c;
+ while ((c = rdr.read()) != -1) {
+ bld.append((char) c);
+ }
+
+ Assert.assertEquals(bld.toString(), SCRIPT_CONTENTS, "Unexpected script contents.");
+ }
+}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java
index 69b3c7a..a415f25 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java
@@ -18,9 +18,9 @@
*/
package org.rhq.enterprise.client.commands;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
-import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -28,12 +28,13 @@ import java.util.Comparator;
import java.util.List;
import java.util.Map;
+import javax.jws.WebParam;
+
+import org.rhq.bindings.client.RhqManager;
import org.rhq.bindings.output.TabularWriter;
import org.rhq.enterprise.client.ClientMain;
import org.rhq.enterprise.client.utility.ReflectionUtility;
-import javax.jws.WebParam;
-
/**
* @author Greg Hinkle
*/
@@ -61,16 +62,16 @@ public class HelpCommand implements ClientCommand {
tw.setHideRowCount(true);
tw.print(data);
} else if ("api".equals(args[1])) {
- Map<String, Object> services = client.getRemoteClient().getScriptingAPI();
+ Map<RhqManager, Object> services = client.getRemoteClient().getScriptingAPI();
if (args.length == 2) {
TabularWriter tw = new TabularWriter(client.getPrintWriter(), "API", "Package");
tw.setWidth(client.getConsoleWidth());
String[][] data = new String[services.size()][2];
int i = 0;
- for (String apiName : services.keySet()) {
- data[i][0] = apiName;
- Object service = services.get(apiName);
+ for (RhqManager api : services.keySet()) {
+ data[i][0] = api.name();
+ Object service = services.get(api);
data[i][1] = service.getClass().getInterfaces()[0].getPackage().getName();
i++;
}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
index e80c346..a511310 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
@@ -27,7 +27,6 @@ import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Arrays;
-import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
@@ -38,7 +37,6 @@ import org.rhq.bindings.ScriptEngineFactory;
import org.rhq.bindings.StandardBindings;
import org.rhq.bindings.client.RhqManager;
import org.rhq.bindings.output.TabularWriter;
-import org.rhq.bindings.util.PackageFinder;
import org.rhq.enterprise.client.ClientMain;
import org.rhq.enterprise.client.Controller;
import org.rhq.enterprise.client.proxy.ConfigurationEditor;
@@ -49,6 +47,8 @@ import org.rhq.enterprise.client.script.CommandLineParseException;
import org.rhq.enterprise.client.script.NamedScriptArg;
import org.rhq.enterprise.client.script.ScriptArg;
import org.rhq.enterprise.client.script.ScriptCmdLine;
+import org.rhq.scripting.ScriptSourceProvider;
+import org.rhq.scripting.ScriptSourceProviderFactory;
/**
* @author Greg Hinkle
@@ -185,7 +185,9 @@ public class ScriptCommand implements ClientCommand {
ScriptEngine engine = client.getScriptEngine();
- ScriptEngineFactory.injectStandardBindings(engine, bindings, false);
+ ScriptSourceProvider[] sourceProviders = ScriptSourceProviderFactory.get(null);
+
+ ScriptEngineFactory.injectStandardBindings(engine, bindings, false, sourceProviders);
ScriptEngineFactory.bindIndirectionMethods(engine, "configurationEditor");
ScriptEngineFactory.bindIndirectionMethods(engine, "rhq");
@@ -206,7 +208,7 @@ public class ScriptCommand implements ClientCommand {
// update the engine with the new client bindings. Keep the existing engine bindings as they
// may contain bindings outside this standard set (like any var created by the script or command line user)
- ScriptEngineFactory.injectStandardBindings(engine, bindings, false);
+ ScriptEngineFactory.injectStandardBindings(engine, bindings, false, ScriptSourceProviderFactory.get(null));
}
return;
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/SamplesScriptSourceProvider.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/SamplesScriptSourceProvider.java
new file mode 100644
index 0000000..ca328b1
--- /dev/null
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/SamplesScriptSourceProvider.java
@@ -0,0 +1,67 @@
+/*
+ * 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.client.script;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URI;
+import java.nio.charset.Charset;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.bindings.script.BaseRhqSchemeScriptSourceProvider;
+
+/**
+ * @author Lukas Krejci
+ */
+public class SamplesScriptSourceProvider extends BaseRhqSchemeScriptSourceProvider {
+
+ private static final Log LOG = LogFactory.getLog(SamplesScriptSourceProvider.class);
+
+ private static final String PREFIX = "//samples/";
+
+ @Override
+ protected Reader doGetScriptSource(URI scriptUri) {
+ String path = scriptUri.getSchemeSpecificPart();
+
+ if (!path.startsWith(PREFIX)) {
+ return null;
+ }
+
+ path = path.substring(2); //remove the leading '//';
+
+ //here we suppose that the CLI was started using the rhq-cli.(sh|bat) script
+ //which sets the working directory to the root of the CLI deployment
+ File file = new File(path);
+
+ try {
+ return new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8"));
+ } catch (FileNotFoundException e) {
+ LOG.debug("Failed to locate the script at: " + scriptUri, e);
+ return null;
+ }
+ }
+
+}
diff --git a/modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider b/modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
new file mode 100644
index 0000000..9722a1c
--- /dev/null
+++ b/modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
@@ -0,0 +1 @@
+org.rhq.enterprise.client.script.SamplesScriptSourceProvider
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
index 4ea3267..0fd4b92 100644
--- a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
@@ -62,7 +62,7 @@ public class RemoteClient implements RhqFacade {
private final int port;
private boolean loggedIn;
private boolean connected;
- private Map<String, Object> managers;
+ private Map<RhqManager, Object> managers;
private Subject subject;
private Client remotingClient;
private String subsystem = null;
@@ -277,16 +277,16 @@ public class RemoteClient implements RhqFacade {
*
* @return Map K=manager name V=remote proxy
*/
- public Map<String, Object> getScriptingAPI() {
+ public Map<RhqManager, Object> getScriptingAPI() {
if (this.managers == null) {
- this.managers = new HashMap<String, Object>();
+ this.managers = new HashMap<RhqManager, Object>();
for (RhqManager manager : RhqManager.values()) {
if (manager.enabled()) {
try {
Object proxy = getProcessor(this, manager, true);
- this.managers.put(manager.name(), proxy);
+ this.managers.put(manager, proxy);
} catch (Throwable e) {
LOG.error("Failed to load manager " + manager + " due to missing class.", e);
}
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RhqDownloadsScriptSourceProvider.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RhqDownloadsScriptSourceProvider.java
new file mode 100644
index 0000000..663e1b3
--- /dev/null
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RhqDownloadsScriptSourceProvider.java
@@ -0,0 +1,89 @@
+/*
+ * 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.clientapi;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.bindings.StandardBindings;
+import org.rhq.bindings.client.RhqFacade;
+import org.rhq.bindings.script.BaseRhqSchemeScriptSourceProvider;
+
+/**
+ * @author Lukas Krejci
+ */
+public class RhqDownloadsScriptSourceProvider extends BaseRhqSchemeScriptSourceProvider implements
+ StandardBindings.RhqFacadeChangeListener {
+
+ private static final Log LOG = LogFactory.getLog(RhqDownloadsScriptSourceProvider.class);
+
+ private static final String PREFIX = "//downloads/";
+
+ private RemoteClient remoteClient;
+
+ @Override
+ public void rhqFacadeChanged(StandardBindings bindings) {
+ RhqFacade facade = bindings.getAssociatedRhqFacade();
+
+ if (facade instanceof RemoteClient) {
+ remoteClient = (RemoteClient) facade;
+ } else {
+ remoteClient = null;
+ }
+ }
+
+ @Override
+ protected Reader doGetScriptSource(URI scriptUri) {
+ if (remoteClient == null) {
+ return null;
+ }
+
+ String path = scriptUri.getSchemeSpecificPart();
+
+ if (!path.startsWith(PREFIX)) {
+ return null;
+ }
+
+ path.substring(1); //remove the leading '/'
+
+ String urlString = remoteClient.getTransport() + "://" + remoteClient.getHost() + ":" + remoteClient.getPort()
+ + path;
+
+ try {
+ URL downloadUrl = new URL(urlString);
+
+ return new InputStreamReader(downloadUrl.openStream());
+ } catch (MalformedURLException e) {
+ LOG.debug("Failed to download the script from the RHQ server using URL: " + urlString, e);
+ } catch (IOException e) {
+ LOG.debug("Failed to download the script from the RHQ server using URL: " + urlString, e);
+ }
+
+ return null;
+ }
+}
diff --git a/modules/enterprise/remoting/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider b/modules/enterprise/remoting/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
new file mode 100644
index 0000000..4008d4a
--- /dev/null
+++ b/modules/enterprise/remoting/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
@@ -0,0 +1 @@
+org.rhq.enterprise.clientapi.RhqDownloadsScriptSourceProvider
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
index 9365304..ffeffd7 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
@@ -47,9 +47,19 @@ public interface ScriptEngineInitializer {
* @return a newly instantiated script engine configured as above
* @throws ScriptException
*/
- ScriptEngine instantiate(Set<String> packages, ScriptSourceProvider scriptSourceProvider, PermissionCollection permissions) throws ScriptException;
+ ScriptEngine instantiate(Set<String> packages, PermissionCollection permissions) throws ScriptException;
/**
+ * Installs given script source provider into the script engine.
+ *
+ * @param scriptEngine
+ * @param scriptSourceProvider
+ *
+ * @throws IllegalArgumentException if the script engine is not supported by this initializer
+ */
+ void installScriptSourceProvider(ScriptEngine scriptEngine, ScriptSourceProvider scriptSourceProvider);
+
+ /**
* This function returns a definition string in the script engine's language
* that provides an indirection to calling the method on the bound object.
*
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
index 2742970..067ed90 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
@@ -25,7 +25,15 @@ import org.jetbrains.annotations.Nullable;
/**
* This is the service interface for scripting language implementations for RHQ
* (loaded using the META-INF/services mechanism).
- *
+ * <p>
+ * Note that the API module provides no factory class that would load the ScriptEngineProvider
+ * implementations present on the classpath. That is because for the script engine to be
+ * usable by RHQ, it needs to be initialized with a couple of dependencies that are not
+ * appropriate for the API module.
+ * <p>
+ * The factory is located in the <code>rhq-script-bindings</code> module as
+ * <code>org.rhq.bindings.ScriptEngineFactory</code>.
+ *
* @author Lukas Krejci
*/
public interface ScriptEngineProvider {
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
index 276e385..c91b706 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
@@ -26,7 +26,10 @@ import java.net.URI;
* Scripts in RHQ can be stored in various locations or maybe not even in the filesystem.
* Implementations of this interface can be used to provide the contents of the scripts
* based on URIs.
- *
+ * <p>
+ * Implementations of this interface can be located using the {@link ScriptSourceProviderFactory}
+ * if they are registered in META-INF/services.
+ *
* @author Lukas Krejci
*/
public interface ScriptSourceProvider {
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProviderFactory.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProviderFactory.java
new file mode 100644
index 0000000..3373792
--- /dev/null
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProviderFactory.java
@@ -0,0 +1,61 @@
+/*
+ * 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.scripting;
+
+import java.util.ArrayList;
+import java.util.ServiceLoader;
+
+/**
+ * A factory class for the ScriptSourceProvider implementations.
+ *
+ * @author Lukas Krejci
+ */
+public final class ScriptSourceProviderFactory {
+
+ private ScriptSourceProviderFactory() {
+
+ }
+
+ /**
+ * Loads the set of the available {@link ScriptSourceProvider} implementations
+ * present on the classpath and registered in META-INF/services.
+ *
+ * @param classLoader the classloader to be used to locate the impls or null if the
+ * context class loader of the current thread should be used.
+ *
+ * @return the set of the script source providers available
+ */
+ public static ScriptSourceProvider[] get(ClassLoader classLoader) {
+ ArrayList<ScriptSourceProvider> ps = new ArrayList<ScriptSourceProvider>();
+
+ if (classLoader == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ }
+
+ ServiceLoader<ScriptSourceProvider> loader = ServiceLoader.load(ScriptSourceProvider.class, classLoader);
+
+ for (ScriptSourceProvider provider : loader) {
+ ps.add(provider);
+ }
+
+ return ps.toArray(new ScriptSourceProvider[ps.size()]);
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
index 771ec1f..f4e2292 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
@@ -52,11 +52,10 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
private ScriptEngineManager engineManager = new ScriptEngineManager();
@Override
- public ScriptEngine instantiate(final Set<String> packages, final ScriptSourceProvider scriptSourceProvider,
- PermissionCollection permissions) throws ScriptException {
+ public ScriptEngine instantiate(final Set<String> packages, PermissionCollection permissions) throws ScriptException {
if (permissions == null) {
- return instantiateUnsecured(packages, scriptSourceProvider);
+ return instantiateUnsecured(packages);
} else {
try {
CodeSource cs = new CodeSource(null, (Certificate[]) null);
@@ -67,7 +66,7 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
return AccessController.doPrivileged(new PrivilegedExceptionAction<ScriptEngine>() {
@Override
public ScriptEngine run() throws Exception {
- return instantiateUnsecured(packages, scriptSourceProvider);
+ return instantiateUnsecured(packages);
}
}, acc);
} catch (PrivilegedActionException e) {
@@ -81,6 +80,21 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
}
@Override
+ public void installScriptSourceProvider(ScriptEngine scriptEngine, ScriptSourceProvider scriptSourceProvider) {
+ if (!(scriptEngine instanceof RhinoScriptEngine)) {
+ throw new IllegalArgumentException("Provided script engine cannot be handled by " + this.getClass()
+ + ". Expected " + RhinoScriptEngine.class + " but got "
+ + (scriptEngine == null ? "null" : scriptEngine.getClass().getName()));
+ }
+
+ RhinoScriptEngine eng = (RhinoScriptEngine) scriptEngine;
+
+ if (scriptSourceProvider != null) {
+ eng.setModuleSourceProvider(new ScriptSourceToModuleSourceProviderAdapter(scriptSourceProvider));
+ }
+ }
+
+ @Override
public Set<String> generateIndirectionMethods(String boundObjectName, Set<Method> methods) {
if (methods.size() == 0) {
return Collections.emptySet();
@@ -132,7 +146,7 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
return errorMessage;
}
- private ScriptEngine instantiateUnsecured(Set<String> packages, ScriptSourceProvider scriptSourceProvider)
+ private ScriptEngine instantiateUnsecured(Set<String> packages)
throws ScriptException {
RhinoScriptEngine eng = (RhinoScriptEngine) engineManager.getEngineByName("rhino-nonjdk");
@@ -140,10 +154,6 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
throw new IllegalStateException("Failed to instantiate the 'rhino-nonjdk' script engine. This means that either the required library is missing from the classpath or that there are some security issues preventing it from being instantiated.");
}
- if (scriptSourceProvider != null) {
- eng.setModuleSourceProvider(new ScriptSourceToModuleSourceProviderAdapter(scriptSourceProvider));
- }
-
for (String pkg : packages) {
eng.eval("importPackage(" + pkg + ")");
}
diff --git a/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java
index 3a50839..e71155b 100644
--- a/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java
+++ b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java
@@ -89,7 +89,7 @@ public class InitializerTest {
perms.add(new FilePermission("<<ALL FILES>>", "read"));
perms.add(new PropertyPermission("*", "read"));
- ScriptEngine eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), null, perms);
+ ScriptEngine eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), perms);
try {
eng.eval("java.lang.System.exit(1)");
@@ -103,7 +103,7 @@ public class InitializerTest {
String script = "var m = require('rhq://test-module1.js'); m.func1();";
//first let's try to find the scripts with the default source provider...
- ScriptEngine eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), null, null);
+ ScriptEngine eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), null);
try {
eng.eval(script);
fail("The module should not have been loaded using the default source provider.");
@@ -111,17 +111,18 @@ public class InitializerTest {
//expected
}
- eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), new ScriptSourceProvider() {
+ eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), null);
+ new JsEngineInitializer().installScriptSourceProvider(eng, new ScriptSourceProvider() {
@Override
public Reader getScriptSource(URI location) {
if (!"rhq".equals(location.getScheme())) {
return null;
}
String scriptName = location.getSchemeSpecificPart().substring(2); //remove the '//'
- InputStream src = getClass().getClassLoader().getResourceAsStream(scriptName);
+ InputStream src = getClass().getClassLoader().getResourceAsStream(scriptName);
return new InputStreamReader(src);
}
- }, null);
+ });
try {
eng.eval(script);
@@ -133,7 +134,7 @@ public class InitializerTest {
public void indirectionMethodsValid() throws Exception {
JsEngineInitializer initializer = new JsEngineInitializer();
- ScriptEngine eng = initializer.instantiate(Collections.<String>emptySet(), null, null);
+ ScriptEngine eng = initializer.instantiate(Collections.<String>emptySet(), null);
TestClass myObject = new TestClass();
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
index 9ee50b8..07ed8eb 100644
--- a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
@@ -43,8 +43,7 @@ public class PythonScriptEngineInitializer implements ScriptEngineInitializer {
private ScriptEngineManager engineManager = new ScriptEngineManager();
@Override
- public ScriptEngine instantiate(Set<String> packages, ScriptSourceProvider scriptSourceProvider,
- PermissionCollection permissions) throws ScriptException {
+ public ScriptEngine instantiate(Set<String> packages, PermissionCollection permissions) throws ScriptException {
ScriptEngine eng = engineManager.getEngineByName("python");
@@ -52,23 +51,26 @@ public class PythonScriptEngineInitializer implements ScriptEngineInitializer {
eng.eval("from " + pkg + " import *\n");
}
- //TODO add support for script source providers... possibly using http://www.python.org/dev/peps/pep-0302/
-
//fingers crossed we can secure jython like this
return new SandboxedScriptEngine(eng, permissions);
}
@Override
+ public void installScriptSourceProvider(ScriptEngine scriptEngine, ScriptSourceProvider provider) {
+ //TODO add support for script source providers... possibly using http://www.python.org/dev/peps/pep-0302/
+ }
+
+ @Override
public Set<String> generateIndirectionMethods(String boundObjectName, Set<Method> overloadedMethods) {
if (overloadedMethods == null || overloadedMethods.isEmpty()) {
return Collections.emptySet();
}
Set<Integer> argCnts = new HashSet<Integer>();
- for(Method m : overloadedMethods) {
+ for (Method m : overloadedMethods) {
argCnts.add(m.getParameterTypes().length);
}
-
+
String methodName = overloadedMethods.iterator().next().getName();
StringBuilder functionBody = new StringBuilder();
@@ -76,18 +78,18 @@ public class PythonScriptEngineInitializer implements ScriptEngineInitializer {
functionBody.append("\t").append("if len(kwargs) > 0:\n");
functionBody.append("\t\t").append("raise ValueError(\"Named arguments not supported for Java methods\")\n");
functionBody.append("\t").append("argCnt = len(args)\n");
-
- for(Integer argCnt : argCnts) {
+
+ for (Integer argCnt : argCnts) {
functionBody.append("\t").append("if argCnt == ").append(argCnt).append(":\n");
functionBody.append("\t\treturn ").append(boundObjectName).append(".").append(methodName).append("(");
int last = argCnt - 1;
- for(int i = 0; i < argCnt; ++i) {
+ for (int i = 0; i < argCnt; ++i) {
functionBody.append("args[").append(i).append("]");
if (i < last) {
functionBody.append(", ");
}
}
- functionBody.append(")\n");
+ functionBody.append(")\n");
}
return Collections.singleton(functionBody.toString());
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
index 384a6e0..7f8efad 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
@@ -44,7 +44,7 @@ public class LocalClient implements RhqFacade {
private static final Log LOG = LogFactory.getLog(LocalClient.class);
private Subject subject;
- private Map<String, Object> managers;
+ private Map<RhqManager, Object> managers;
public LocalClient(Subject subject) {
this.subject = subject;
@@ -70,10 +70,10 @@ public class LocalClient implements RhqFacade {
}
@Override
- public Map<String, Object> getScriptingAPI() {
+ public Map<RhqManager, Object> getScriptingAPI() {
if (managers == null) {
- managers = new HashMap<String, Object>();
+ managers = new HashMap<RhqManager, Object>();
for (final RhqManager manager : RhqManager.values()) {
if (manager.enabled()) {
@@ -85,7 +85,7 @@ public class LocalClient implements RhqFacade {
}
});
- managers.put(manager.name(), proxy);
+ managers.put(manager, proxy);
} catch (Throwable e) {
LOG.error("Failed to load manager " + manager + " due to missing class.", e);
}
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java
new file mode 100644
index 0000000..7b9232a
--- /dev/null
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java
@@ -0,0 +1,80 @@
+/*
+ * 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.client;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URI;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.bindings.script.BaseRhqSchemeScriptSourceProvider;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.common.ServerDetails;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.system.SystemManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * @author Lukas Krejci
+ */
+public class RhqDownloadsScriptSourceProvider extends BaseRhqSchemeScriptSourceProvider {
+
+ private static final Log LOG = LogFactory.getLog(RhqDownloadsScriptSourceProvider.class);
+
+ private static final String PREFIX = "//downloads/";
+
+ private SystemManagerLocal systemManager = LookupUtil.getSystemManager();
+ private SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+
+ @Override
+ protected Reader doGetScriptSource(URI scriptUri) {
+ String path = scriptUri.getSchemeSpecificPart();
+
+ if (!path.startsWith(PREFIX)) {
+ return null;
+ }
+
+ path = path.substring(PREFIX.length());
+
+ Subject overlord = subjectManager.getOverlord();
+
+ ServerDetails serverDetails = systemManager.getServerDetails(overlord);
+
+ String serverHomeDir = serverDetails.getDetails().get(ServerDetails.Detail.SERVER_HOME_DIR);
+
+ File downloads = new File(serverHomeDir, "deploy/rhq.ear/rhq-downloads");
+
+ File file = new File(downloads, path);
+
+ try {
+ return new InputStreamReader(new FileInputStream(file));
+ } catch (FileNotFoundException e) {
+ LOG.debug("Failed to locate the download file: " + scriptUri, e);
+ return null;
+ }
+ }
+
+}
diff --git a/modules/enterprise/server/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider b/modules/enterprise/server/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
new file mode 100644
index 0000000..7523c32
--- /dev/null
+++ b/modules/enterprise/server/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
@@ -0,0 +1 @@
+org.rhq.enterprise.client.RhqDownloadsScriptSourceProvider
diff --git a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
index 2236923..61f9ea0 100644
--- a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
+++ b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
@@ -112,7 +112,7 @@ public class LocalClientTest extends JMockTest {
LocalClient lc = new LocalClient(null);
//this call creates the proxy and is theoretically prone to the context classloader
- Object am = lc.getScriptingAPI().get("AlertManager");
+ Object am = lc.getScriptingAPI().get(RhqManager.AlertManager);
//check that only the simplified method exists on the returned object
try {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java
index fc72896..abc8ba5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java
@@ -421,7 +421,7 @@ public interface ContentManagerLocal {
InstalledPackage getBackingPackageForResource(Subject subject, int resourceId);
/**
- * @see {@link ContentManagerRemote#getPackageBytes(Subject, int, int)
+ * @see {@link ContentManagerRemote#getPackageBytes(Subject, int, int)}
*/
byte[] getPackageBytes(Subject user, int resourceId, int installedPackageId);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java
index a75d78f..e2e37c5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java
@@ -292,5 +292,4 @@ public interface ContentManagerRemote {
@WebMethod
byte[] getPackageBytes(@WebParam(name = "subject") Subject user, @WebParam(name = "resourceId") int resourceId,
@WebParam(name = "installedPackageId") int installedPackageId);
-
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java
index 72d7bee..9bcf553 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java
@@ -18,6 +18,8 @@
*/
package org.rhq.enterprise.server.content;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Comparator;
@@ -990,6 +992,35 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
repo.addRepoRelationship(repoRelationship);
}
+ @Override
+ public byte[] getPackageVersionBytes(Subject subject, int repoId, int packageVersionId) {
+ if (!authzManager.canViewRepo(subject, repoId)) {
+ throw new PermissionException("User [" + subject + "] cannot access a repo with id " + repoId);
+ }
+
+ //check that the provided package version actually belongs to the repo
+ Repo repo = entityManager.find(Repo.class, repoId);
+
+ PackageVersion pv = entityManager.find(PackageVersion.class, packageVersionId);
+ if (pv == null || !pv.getRepos().contains(repo)) {
+ throw new IllegalArgumentException("The package version with id " + packageVersionId
+ + " does not belong to the repo with id " + repoId + " or does not exist.");
+ }
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ contentSourceManager.outputPackageVersionBits(pv, out);
+
+ byte[] ret = out.toByteArray();
+
+ try {
+ out.close();
+ } catch (IOException e) {
+ //this is not gonna happen with a byte array stream
+ }
+
+ return ret;
+ }
+
private void validateFields(Repo repo) throws RepoException {
if (repo.getName() == null || repo.getName().trim().equals("")) {
throw new RepoException("Repo name is required");
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerLocal.java
index 51957bd..94c1159 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerLocal.java
@@ -18,7 +18,6 @@
*/
package org.rhq.enterprise.server.content;
-import java.util.Comparator;
import java.util.List;
import javax.ejb.Local;
@@ -415,4 +414,6 @@ public interface RepoManagerLocal {
* @return
*/
List<SubscribedRepo> findSubscriptions(Subject subject, int resourceId);
+
+ byte[] getPackageVersionBytes(Subject user, int repoId, int packageVersionId);
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerRemote.java
index d144443..45c0c5a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerRemote.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerRemote.java
@@ -18,7 +18,6 @@
*/
package org.rhq.enterprise.server.content;
-import java.util.Comparator;
import java.util.List;
import javax.ejb.Remote;
@@ -260,4 +259,17 @@ public interface RepoManagerRemote {
@WebParam(name = "subject") Subject subject, //
@WebParam(name = "repoIds") int[] repoIds) //
throws Exception;
+
+ /**
+ * This method allows for downloading the bytes of an arbitrary package version. This call can be dangerous with
+ * large packages because it will attempt to load the whole package in memory.
+ *
+ * @param user
+ * @param repoId
+ * @param packageVersionId
+ * @return the bytes of the package version
+ */
+ @WebMethod
+ byte[] getPackageVersionBytes(@WebParam(name = "subject") Subject user, @WebParam(name = "repoId") int repoId,
+ @WebParam(name = "packageVersionId") int packageVersionId);
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
index 27cdabd..69d797a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
@@ -903,6 +903,10 @@ public class WebservicesManagerBean implements WebservicesRemote {
return repoManager.synchronizeRepos(subject, repoIds);
}
+ public byte[] getPackageVersionBytes(Subject user, int repoId, int packageVersionId) {
+ return repoManager.getPackageVersionBytes(user, repoId, packageVersionId);
+ }
+
//REPOMANAGER: END ----------------------------------
//RESOURCEFACTORYMANAGER: BEGIN ----------------------------------
diff --git a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
index 09dc8a5..8ca0b39 100644
--- a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
+++ b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
@@ -61,6 +61,8 @@ import org.rhq.enterprise.server.plugin.pc.alert.AlertSender;
import org.rhq.enterprise.server.plugin.pc.alert.AlertSenderValidationResults;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.scripting.ScriptEngineInitializer;
+import org.rhq.scripting.ScriptSourceProvider;
+import org.rhq.scripting.ScriptSourceProviderFactory;
/**
* Uses CLI to perform the alert notification.
@@ -425,9 +427,10 @@ public class CliSender extends AlertSender<CliComponent> {
if (engine == null) {
engine = ScriptEngineFactory.getSecuredScriptEngine(ENGINE_NAME,
new PackageFinder(Collections.<File> emptyList()), bindings, new StandardScriptPermissions());
- } else {
- ScriptEngineFactory.injectStandardBindings(engine, bindings, true);
}
+ //TODO is this OK, or should we use a different classloader than the context classloader?
+ ScriptSourceProvider[] providers = ScriptSourceProviderFactory.get(null);
+ ScriptEngineFactory.injectStandardBindings(engine, bindings, true, providers);
++ENGINES_IN_USE;
commit e7b13bd50bbac52f88cdde48b28a90286740e896
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jul 3 11:43:44 2012 -0700
On Resource Detail Configuration Tab - Move Save Button bar down to bottom of screen (from top) to match other button bars.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
index 6725e98..9d2d1a2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
@@ -80,6 +80,18 @@ public class ResourceConfigurationEditView extends LocatableVLayout implements P
protected void onDraw() {
super.onDraw();
+ //createButtonBar();
+
+ refresh();
+
+ if (!this.resourcePermission.isConfigureWrite()) {
+ Message message = new Message(MSG.view_configurationDetails_noPermission(), Message.Severity.Info, EnumSet
+ .of(Message.Option.Transient, Message.Option.Sticky));
+ CoreGUI.getMessageCenter().notify(message);
+ }
+ }
+
+ private ToolStrip createButtonBar() {
this.buttonbar = new ToolStrip();
buttonbar.setWidth100();
buttonbar.setExtraSpace(10);
@@ -95,15 +107,7 @@ public class ResourceConfigurationEditView extends LocatableVLayout implements P
buttonbar.addMember(saveButton);
// The button bar will remain hidden until the configuration has been successfully loaded.
buttonbar.setVisible(false);
- addMember(buttonbar);
-
- refresh();
-
- if (!this.resourcePermission.isConfigureWrite()) {
- Message message = new Message(MSG.view_configurationDetails_noPermission(), Message.Severity.Info, EnumSet
- .of(Message.Option.Transient, Message.Option.Sticky));
- CoreGUI.getMessageCenter().notify(message);
- }
+ return buttonbar;
}
@Override
@@ -113,11 +117,12 @@ public class ResourceConfigurationEditView extends LocatableVLayout implements P
}
this.refreshing = true;
- this.buttonbar.setVisible(false);
if (editor != null) {
editor.destroy();
removeMember(editor);
+ buttonbar.destroy();
+ removeMember(buttonbar);
}
GWTServiceLookup.getConfigurationService().getLatestResourceConfigurationUpdate(resource.getId(),
@@ -155,6 +160,7 @@ public class ResourceConfigurationEditView extends LocatableVLayout implements P
editor.addPropertyValueChangeListener(ResourceConfigurationEditView.this);
editor.setReadOnly(!resourcePermission.isConfigureWrite());
addMember(editor);
+ addMember(createButtonBar());
saveButton.disable();
buttonbar.setVisible(true);
commit 00db03b19d5a70e9798405b33f91ed150e38382e
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Jul 3 13:06:41 2012 -0400
[BZ 834019] unit test to make sure we push out the schedule properly for late-collected metrics
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java
index 518d5da..e7661ac 100644
--- a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java
@@ -21,6 +21,7 @@ import org.rhq.core.pc.PluginContainer;
import org.rhq.core.pc.inventory.ResourceContainer;
import org.rhq.plugins.test.SingleResourceDiscoveryComponent;
import org.rhq.plugins.test.measurement.BZ834019ResourceComponent;
+import org.rhq.plugins.test.measurement.BZ834019ResourceComponent.CollectedMetric;
import org.rhq.test.arquillian.AfterDiscovery;
import org.rhq.test.arquillian.BeforeDiscovery;
import org.rhq.test.arquillian.FakeServerInventory;
@@ -31,20 +32,22 @@ import org.rhq.test.arquillian.RunDiscovery;
import org.rhq.test.shrinkwrap.RhqAgentPluginArchive;
/**
- * Test for BZ 834019.
+ * Test for BZ 834019. This test requires a long time to complete (about 2.5 minutes) because
+ * we have to wait for the minimum collection intervals (30s) to pass several times.
*/
@RunDiscovery
public class LateMeasurementRescheduleTest extends Arquillian {
- @Deployment(name = "SingleMetricPlugin")
+ @Deployment(name = "TwoMetricPlugin")
@TargetsContainer("connected-pc-with-metric-collection")
public static RhqAgentPluginArchive getTestPlugin() {
- RhqAgentPluginArchive pluginJar = ShrinkWrap
- .create(RhqAgentPluginArchive.class, "single-metric-plugin-1.0.jar");
+ RhqAgentPluginArchive pluginJar = ShrinkWrap.create(RhqAgentPluginArchive.class, "bz834019-plugin-1.0.jar");
HashMap<String, String> replacements = new HashMap<String, String>();
replacements.put("@@@discovery@@@", SingleResourceDiscoveryComponent.class.getName());
replacements.put("@@@class@@@", BZ834019ResourceComponent.class.getName());
- return pluginJar.setPluginDescriptorFromTemplate("single-metric-rhq-plugin.xml", replacements).addClasses(
+ replacements.put("@@@metric1.interval@(a)@", "30000");
+ replacements.put("@@@metric2.interval@(a)@", "35000"); // this MUST be 35s - if you make it 30s, the collections won't be late!
+ return pluginJar.setPluginDescriptorFromTemplate("two-metric-rhq-plugin.xml", replacements).addClasses(
SingleResourceDiscoveryComponent.class, BZ834019ResourceComponent.class);
}
@@ -57,10 +60,10 @@ public class LateMeasurementRescheduleTest extends Arquillian {
private FakeServerInventory fakeServerInventory;
private FakeServerInventory.CompleteDiscoveryChecker discoveryCompleteChecker;
- @ResourceContainers(plugin = "SingleMetricPlugin", resourceType = "SingleMetricServer")
+ @ResourceContainers(plugin = "TwoMetricPlugin", resourceType = "TwoMetricServer")
private Set<ResourceContainer> containers;
- @ResourceComponentInstances(plugin = "SingleMetricPlugin", resourceType = "SingleMetricServer")
+ @ResourceComponentInstances(plugin = "TwoMetricPlugin", resourceType = "TwoMetricServer")
private Set<BZ834019ResourceComponent> components;
@BeforeDiscovery(testMethods = "testBZ834019")
@@ -100,6 +103,73 @@ public class LateMeasurementRescheduleTest extends Arquillian {
BZ834019ResourceComponent server = this.components.iterator().next();
- // TODO do things to test BZ 834019
+ // do things to test BZ 834019. Here's what is happening:
+ // - server has metric1 and metric2 with intervals of 30s and 35s respectively
+ // (MUST make sure metric2 is no less than 35s, else the collections won't be late!)
+ // - the resource component will sleep in its getValues for 91s - no metrics will be reported the first 91s
+ // - the PC will call getValues() in this sequence:
+ // ** metric1 - starting at time 0 (due to the sleep in our getValues, this won't compete until time 91)
+ // ** metric2 - starting at time 0 (completes at time 91)
+ // ** metric1 - starting at time 30 (completes at time 91)
+ // ** metric2 - starting at time 60 (completes at time 91)
+ // ** metric2 - starting at time 90 (completes at time 91)
+ // ** metric2 - starting at time 105 (completes at time 105)
+ // ** metric1 - starting at time 121 (completes at time 121)
+ // Now, I can't explain this behavior entirely, however, it appears that metric1 is considered late so it
+ // is pushed back by our fix. It is last collected at time 30, but doesn't finish timely. The next time it should
+ // be collected is time 60 but because it has been late, that collection is skipped and our fix will re-schedule it
+ // next at time (interval+31), which means: 60 + (interval+31) == 60 + (30+31) == 60+61 == 121.
+ // And you can see above, that is when the next request to collect metric1 is done.
+ // Without the fix, the next collection of metric1 would have been at around time 60 + (interval) == 60 + (30) == 90
+
+ // rather than just blindly sleeping, make this test complete as fast as possible by
+ // stop waiting as soon as we see metric1 having been collected at least 3 times.
+ CollectedMetric[] collectedMetrics = null;
+ boolean keepWaiting = true;
+ int waitCycles = 0;
+ while (keepWaiting) {
+ Thread.sleep(1000);
+ int numberOfTimesMetric1WasCollectedSoFar = 0;
+ collectedMetrics = server.collectedMetrics.toArray(new CollectedMetric[0]); // copy it fast, this is synchronized so our component's thread won't break us
+ for (CollectedMetric collectedMetric : collectedMetrics) {
+ if (collectedMetric.metricName.equals("metric1")) {
+ numberOfTimesMetric1WasCollectedSoFar++;
+ }
+ }
+ if (numberOfTimesMetric1WasCollectedSoFar >= 3) {
+ keepWaiting = false;
+ }
+ if (waitCycles++ > 140) {
+ keepWaiting = false; // stop waiting but the test will probably fail because we should have had three metric1 collections by now
+ }
+ }
+
+ // round all the time values to the nearest second
+ for (CollectedMetric metric : collectedMetrics) {
+ metric.collectedTime = getRoundedSeconds(metric.collectedTime);
+ metric.finishedTime = getRoundedSeconds(metric.finishedTime);
+ System.out.println("BZ 834019 test metric=" + metric.metricName + "; start=" + metric.collectedTime
+ + "; stop=" + metric.finishedTime);
+ }
+
+ // now look at the timings and make sure we see metric1 pushed out into the future like our bug fix wants it to be
+ int collectionNumber = 0;
+ for (CollectedMetric metric : collectedMetrics) {
+ if ("metric1".equals(metric.metricName)) {
+ collectionNumber++; // this tracks that we are on the Nth time the metric was collected, we expect 3 total
+ if (collectionNumber == 1) {
+ assert metric.collectedTime <= 3; // should be 0, but give it some leeway in case our test box is slow
+ } else if (collectionNumber == 2) {
+ assert metric.collectedTime >= 29 && metric.collectedTime <= 32; // should be 30, but give it some leeway
+ } else if (collectionNumber == 3) {
+ assert metric.collectedTime >= 119 && metric.collectedTime <= 123; // should be 121, but give it some leeway
+ }
+ }
+ }
+ assert collectionNumber >= 3 : "test should have collected metric1 at least 3 times: " + collectionNumber;
+ }
+
+ private long getRoundedSeconds(long millis) {
+ return (long) ((millis / 1000.0) + 0.5);
}
}
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
index ed55d63..dedf968 100644
--- a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
@@ -44,6 +44,8 @@ public class ReadOnlyScheduleSetTest extends Arquillian {
HashMap<String, String> replacements = new HashMap<String, String>();
replacements.put("@@@discovery@@@", SingleResourceDiscoveryComponent.class.getName());
replacements.put("@@@class@@@", BZ821058ResourceComponent.class.getName());
+ replacements.put("@@@metric1.interval@(a)@", "30000");
+ replacements.put("@@@metric2.interval@(a)@", "30000");
return pluginJar.setPluginDescriptorFromTemplate("two-metric-rhq-plugin.xml", replacements).addClasses(
SingleResourceDiscoveryComponent.class, BZ821058ResourceComponent.class);
}
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java
index 6a3a93d..a6f7221 100644
--- a/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java
@@ -1,7 +1,10 @@
package org.rhq.plugins.test.measurement;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
+import java.util.Vector;
+import java.util.concurrent.CountDownLatch;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.measurement.MeasurementDataNumeric;
@@ -13,6 +16,16 @@ import org.rhq.core.pluginapi.measurement.MeasurementFacet;
public class BZ834019ResourceComponent implements ResourceComponent<ResourceComponent<?>>, MeasurementFacet {
+ public class CollectedMetric {
+ public String metricName;
+ public long collectedTime; // the collected time as relative to initialCollectionTime
+ public long finishedTime; // the time when the getValues returned relative to initialCollectionTime
+ }
+
+ public CountDownLatch latch;
+ public long initialCollectionTime = 0L;
+ public Vector<CollectedMetric> collectedMetrics = new Vector<CollectedMetric>(); // we want synchronized Vector
+
@Override
public AvailabilityType getAvailability() {
return AvailabilityType.UP;
@@ -28,11 +41,64 @@ public class BZ834019ResourceComponent implements ResourceComponent<ResourceComp
@Override
public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
- // TODO: do things to test BZ 834019
+ boolean doSleep = false;
+ if (initialCollectionTime == 0L) {
+ initialCollectionTime = System.currentTimeMillis();
+ doSleep = true;
+ latch = new CountDownLatch(1); // so the rest of our collections will wait for our sleep to finish
+ }
+
+ ArrayList<CollectedMetric> thisCollection = new ArrayList<CollectedMetric>();
+
+ long now = System.currentTimeMillis() - initialCollectionTime;
for (Iterator<MeasurementScheduleRequest> i = metrics.iterator(); i.hasNext();) {
MeasurementScheduleRequest metric = i.next();
+ log("collecting metric " + (metric.getName() + " (interval=" + metric.getInterval() + ")"));
report.addData(new MeasurementDataNumeric(metric, new Double(1.0)));
+
+ // remember what time we were called and which metric was asked to be collected
+ CollectedMetric collectedMetric = new CollectedMetric();
+ collectedMetric.collectedTime = now;
+ collectedMetric.metricName = metric.getName();
+ collectedMetrics.add(collectedMetric);
+ thisCollection.add(collectedMetric);
+ }
+
+ // delay the initial collection a long time to push back collection of future metrics - we must ignore all interrupts!
+ if (doSleep) {
+ log("before sleep");
+ for (int i = 0; i < 91; i++) {
+ try {
+ Thread.sleep(1000);
+ } catch (Exception e) {
+ log("ignoring interrupt at second #" + i);
+ }
+ }
+ log("after sleep");
+ latch.countDown();
+ } else {
+ // don't let interrupts abort our wait - always wait for the countdown latch to open up
+ boolean shouldWait = true;
+ while (shouldWait) {
+ try {
+ log("before latch wait");
+ latch.await();
+ log("latch opened up");
+ shouldWait = false;
+ } catch (Exception e) {
+ log("latch wait interruptted, go back and wait...");
+ }
+ }
+ }
+
+ now = System.currentTimeMillis() - initialCollectionTime;
+ for (CollectedMetric collection : thisCollection) {
+ collection.finishedTime = now;
}
return;
}
+
+ private void log(String msg) {
+ //System.out.println("!!!!!!!!!!! " + this.getClass().getSimpleName() + ": " + new Date() + ": " + msg);
+ }
}
\ No newline at end of file
diff --git a/modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml b/modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml
index 4d9b7e1..8302160 100644
--- a/modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml
+++ b/modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml
@@ -16,12 +16,12 @@
dataType="measurement"
defaultOn="true"
displayType="summary"
- defaultInterval="30000" />
+ defaultInterval="@@@metric1.interval@(a)@" />
<metric property="metric2"
dataType="measurement"
defaultOn="true"
displayType="summary"
- defaultInterval="30000" />
+ defaultInterval="@@@metric2.interval@(a)@" />
</server>
</plugin>
commit bbf48d7bddbd0361e7406d23762990fd840cd8da
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Jul 3 12:48:30 2012 +0200
BZ 834820 Eliminate call to isLast() which is problematic on Oracle
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
index 5987758..d602751 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
@@ -646,8 +646,13 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
PrintWriter pw = new PrintWriter(outputStream);
if (mediaType.equals(MediaType.APPLICATION_JSON_TYPE)) {
+ boolean needsComma = false;
pw.println("[");
while (rs.next()) {
+ if (needsComma) {
+ pw.print(",\n");
+ }
+ needsComma = true;
pw.print("{");
pw.print("\"scheduleId\":");
pw.print(scheduleId);
@@ -658,8 +663,6 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
pw.print("\"value\":");
pw.print(rs.getDouble(2));
pw.print("}");
- if (!rs.isLast())
- pw.print(",\n");
}
pw.println("]");
}
commit 87f63d5522059ca035c0c1d1377aba569e552b22
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Jul 2 13:19:44 2012 -0700
[BZ 734490] AS7 plugin: resource config: 'Module Name' member props of 'Installed Extensions' map should be read-only
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
index c7de21b..e50fe14 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
@@ -72,6 +72,13 @@ public class ImageManager {
}
/**
+ * Returns a generic add icon.
+ */
+ public static String getAddIcon() {
+ return "[SKIN]/actions/add.png";
+ }
+
+ /**
* Returns a generic approve (aka "ok") icon.
*/
public static String getApproveIcon() {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
index 4e3e9df..9932499 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
@@ -545,7 +545,6 @@ public class ConfigurationEditor extends LocatableVLayout {
if (propertyMap instanceof Configuration) {
this.topLevelPropertiesValuesManager.addMember(form);
}
- //form.setValidateOnExit(true); // TODO: Remove this?
form.setHiliteRequiredFields(true);
form.setNumCols(4);
form.setCellPadding(5);
@@ -1000,7 +999,7 @@ public class ConfigurationEditor extends LocatableVLayout {
removeField.addRecordClickHandler(new RecordClickHandler() {
public void onRecordClick(final RecordClickEvent recordClickEvent) {
- Log.info("You want to delete: " + recordClickEvent.getRecordNum());
+ Log.debug("You want to delete: " + recordClickEvent.getRecordNum());
SC.confirm(MSG.view_configEdit_confirm_2(), new BooleanCallback() {
public void execute(Boolean confirmed) {
if (confirmed) {
@@ -1074,20 +1073,15 @@ public class ConfigurationEditor extends LocatableVLayout {
}
private static boolean isAllReadOnly(List<PropertyDefinition> propertyDefinitions) {
- // TODO (ips, 02/13/12): If we are going to do this correctly, we need to call isPropertyReadOnly() on each
- // member property to determine whether that particular property is read-only or not,
- // rather than relying solely on whether the member property definition is read-only; this
- // is because, for a couple special cases, isPropertyReadOnly() returns false even when
- // the prop def is read-only.
- /*boolean allPropsDefsReadOnly = true;
+ boolean allPropsDefsReadOnly = true;
for (PropertyDefinition subDef : propertyDefinitions) {
if (!subDef.isReadOnly()) {
+ Log.debug("Found at least one non-readOnly property for: "+subDef.getName());
allPropsDefsReadOnly = false;
break;
}
}
- return allPropsDefsReadOnly;*/
- return false;
+ return allPropsDefsReadOnly;
}
private PropertyMapListGridRecord[] buildSummaryRecords(PropertyList propertyList,
@@ -1133,8 +1127,8 @@ public class ConfigurationEditor extends LocatableVLayout {
vLayout.addMember(footer);
final IButton deleteButton = new LocatableIButton(extendLocatorId("Delete"));
- deleteButton.setIcon(Window.getImgURL("[SKIN]/actions/remove.png"));
- deleteButton.setTooltip(MSG.view_configEdit_tooltip_1());
+ deleteButton.setIcon(Window.getImgURL(ImageManager.getRemoveIcon()));
+ deleteButton.setTooltip(MSG.view_configEdit_tooltip_1());
deleteButton.setDisabled(true);
deleteButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
public void onClick(ClickEvent clickEvent) {
@@ -1178,11 +1172,10 @@ public class ConfigurationEditor extends LocatableVLayout {
});
final IButton newButton = new LocatableIButton(vLayout.extendLocatorId("New"), MSG.common_button_new());
- newButton.setIcon(Window.getImgURL("[SKIN]/actions/add.png"));
+ newButton.setIcon(Window.getImgURL(ImageManager.getAddIcon()));
newButton.setTooltip(MSG.view_configEdit_tooltip_2());
newButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
public void onClick(ClickEvent clickEvent) {
- // TODO: selenium locators
final Window popup = new Window();
popup.setTitle(MSG.view_configEdit_addItem());
popup.setWidth(300);
@@ -1276,7 +1269,7 @@ public class ConfigurationEditor extends LocatableVLayout {
return buildComplexPropertyField(vLayout);
}
- private LinkedHashMap<String, String> buildValueMap(PropertyList propertyList) {
+ private static LinkedHashMap<String, String> buildValueMap(PropertyList propertyList) {
LinkedHashMap<String, String> memberValueToIndexMap = new LinkedHashMap<String, String>();
List<Property> memberProperties = propertyList.getList();
int index = 0;
@@ -1296,13 +1289,14 @@ public class ConfigurationEditor extends LocatableVLayout {
protected FormItem buildSimpleField(final PropertyDefinitionSimple propertyDefinitionSimple,
final PropertySimple propertySimple) {
- Log.debug("Building simple field for " + propertySimple + "...");
FormItem valueItem = null;
boolean propertyIsReadOnly = isReadOnly(propertyDefinitionSimple, propertySimple);
+ Log.debug("Building simple field for " + propertySimple +"(read-only:"+propertyIsReadOnly+")...");
+
// TODO (ips, 03/25/11): We eventually want to use StaticTextItems for read-only PASSWORD props too, but we have
- // to wait until we implement masking/unmasking of PASSWORD props at the SLSB layer first.
+ // to wait until we implement masking/unmasking of PASSWORD props at the SLSB layer first.
if (propertyIsReadOnly && propertyDefinitionSimple.getType() != PropertySimpleType.PASSWORD) {
valueItem = new StaticTextItem();
} else {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
index ddf9784..6725e98 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
@@ -47,6 +47,7 @@ import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.ResourceD
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.MetadataType;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.TypeLoadedCallback;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
import org.rhq.enterprise.gui.coregui.client.util.message.MessageCenter;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableIButton;
@@ -190,7 +191,6 @@ public class ResourceConfigurationEditView extends LocatableVLayout implements P
.view_configurationDetails_messageDetailed(version, resource.getName()),
Message.Severity.Info);
} else {
- // TODO: i18n
message = new Message(MSG.view_configurationDetails_configNotUpdatedDueToNoChange(),
Message.Severity.Warning);
}
commit d12f2d22940245491344cc4238eb7651cf18d1a6
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Jun 26 13:36:05 2012 -0700
Minor: Change icon strings to IconEnum for better type safety.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java
index 23bb13d..987dca6 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java
@@ -18,6 +18,7 @@
*/
package org.rhq.enterprise.gui.coregui.client;
+
/**
* Adding type information around Icons instead of having plain Strings.
* Icons imply more than just a String type. There are attributes associated with icons
@@ -26,6 +27,7 @@ package org.rhq.enterprise.gui.coregui.client;
* This provides more type safety than the ImageManager class that deals only with String type.
* IDE's can quickly query on Icon Types and quickly see exactly where that image was used
* and understand the full ramifications of changing an image.
+ * Helps provide consistency of images throughout the app.
* By having the IconEnum represent the icon, we can defer the determination of the
* size of the icon to the implementation while still defining an icon.
* It is also very easy for a method signature to become ambiguous if the string is null.
@@ -58,6 +60,7 @@ public enum IconEnum {
TAGS("global/Tag_16.png","global/Tag_24.png" ),
REPORT("subsystems/report/Document_16.png","subsystems/report/Document_24.png" ),
SUSPECT_METRICS("subsystems/monitor/Monitor_failed_16.png","subsystems/monitor/Monitor_failed_24.png","subsystems/monitor/Monitor_grey_16.png",null),
+ RECENT_MEASUREMENTS("subsystems/monitor/Monitor_16.png","subsystems/monitor/Monitor_24.png"),
CONFIGURATION_HISTORY("subsystems/configure/Configure_16.png", "subsystems/configure/Configure_24.png","subsystems/configure/Configure_grey_16.png",null),
RECENT_OPERATIONS("subsystems/control/Operation_16.png","subsystems/control/Operation_24.png", "subsystems/control/Operation_grey_16.png",null),
RECENT_ALERTS("subsystems/alert/Alert_LOW_16.png"),
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
index 8d9680a..758d8eb 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
@@ -55,6 +55,7 @@ import org.rhq.core.domain.resource.group.GroupCategory;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.gui.coregui.client.IconEnum;
import org.rhq.enterprise.gui.coregui.client.RefreshableView;
import org.rhq.enterprise.gui.coregui.client.components.measurement.CustomConfigMeasurementRangeEditor;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.PortletConfigurationEditorComponent.Constant;
@@ -172,7 +173,7 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
}
//recentMetrics.xhtml
- HLayout recentMetricsTitle = new TitleWithIcon("subsystems/monitor/Monitor_24.png", RECENT_MEASUREMENTS);
+ HLayout recentMetricsTitle = new TitleWithIcon(IconEnum.RECENT_MEASUREMENTS.getIcon24x24Path(), RECENT_MEASUREMENTS);
if ((resource != null) || ((group != null) && (groupCategory.equals(GroupCategory.COMPATIBLE)))) {//resource,CompatibleGroup
leftPane.addMember(recentMetricsTitle);
leftPane.addMember(recentMeasurementsContent);
@@ -180,12 +181,12 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
leftPane.addMember(divider1);
}
//recentAlerts.xhtml
- HLayout recentAlertsTitle = new TitleWithIcon("subsystems/alert/Flag_blue_24.png", RECENT_ALERTS);
+ HLayout recentAlertsTitle = new TitleWithIcon(IconEnum.RECENT_ALERTS.getIcon24x24Path(), RECENT_ALERTS);
leftPane.addMember(recentAlertsTitle);
leftPane.addMember(recentAlertsContent);
recentAlertsContent.setHeight(20);
//recentOOBs.xhtml
- HLayout recentOobsTitle = new TitleWithIcon("subsystems/monitor/Monitor_failed_24.png", RECENT_OOB);
+ HLayout recentOobsTitle = new TitleWithIcon(IconEnum.SUSPECT_METRICS.getIcon24x24Path(), RECENT_OOB);
recentOobContent.setHeight(20);
if ((resource != null) || ((group != null) && (groupCategory.equals(GroupCategory.COMPATIBLE)))) {//resource,CompatibleGroup
leftPane.addMember(divider2);
@@ -199,7 +200,7 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
rightPane.setAutoHeight();
firstRightPanePortletLoaded = false;
//recentConfigUpdates.xhtml
- HLayout recentConfigUpdatesTitle = new TitleWithIcon("subsystems/configure/Configure_24.png",
+ HLayout recentConfigUpdatesTitle = new TitleWithIcon(IconEnum.CONFIGURE.getIcon24x24Path(),
RECENT_CONFIGURATIONS);
recentConfigurationContent.setHeight(20);
if (((resource != null) && (resourceFacets.contains(ResourceTypeFacet.CONFIGURATION)))
@@ -210,7 +211,7 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
}
//recentOperations.xhtml
- HLayout recentOperationsTitle = new TitleWithIcon("subsystems/control/Operation_24.png", RECENT_OPERATIONS);
+ HLayout recentOperationsTitle = new TitleWithIcon(IconEnum.RECENT_OPERATIONS.getIcon24x24Path(), RECENT_OPERATIONS);
recentOperationsContent.setHeight(20);
if (((resource != null) && (resourceFacets.contains(ResourceTypeFacet.OPERATION)))
|| (displayGroupOperations(groupCategory, facets))) {//resource
@@ -222,7 +223,7 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
firstRightPanePortletLoaded = true;
}
//recentEventCounts.xhtml
- HLayout recentEventsTitle = new TitleWithIcon("subsystems/event/Events_24.png", RECENT_EVENTS);
+ HLayout recentEventsTitle = new TitleWithIcon(IconEnum.EVENTS.getIcon24x24Path(), RECENT_EVENTS);
recentEventsContent.setHeight(20);
if (((resource != null) && (resourceFacets.contains(ResourceTypeFacet.EVENT)))
|| displayGroupEvents(groupCategory, facets)) {//resource
@@ -234,7 +235,7 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
firstRightPanePortletLoaded = true;
}
//recentPackageHistory.xhtml
- HLayout recentPkgHistoryTitle = new TitleWithIcon("subsystems/content/Package_24.png", RECENT_PKG_HISTORY);
+ HLayout recentPkgHistoryTitle = new TitleWithIcon(IconEnum.CONTENT.getIcon24x24Path(),RECENT_PKG_HISTORY);
recentPkgHistoryContent.setHeight(20);
if ((resource != null) || ((group != null) && (groupCategory.equals(GroupCategory.COMPATIBLE)))) {//resource,CompatibleGroup
if (firstRightPanePortletLoaded) {
@@ -245,7 +246,7 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
}
//recent bundle deployments
- recentBundleDeployTitle = new TitleWithIcon("subsystems/content/Content_24.png", RECENT_BUNDLE_DEPLOY);
+ recentBundleDeployTitle = new TitleWithIcon(IconEnum.CONTENT.getIcon24x24Path(), RECENT_BUNDLE_DEPLOY);
recentBundleDeployTitle.setHeight(20);
deployBundleViewIfApplicable(resource, group);
@@ -513,7 +514,7 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
/** Takes the current value of the widget and persists it into the configuration object passed in.
*
- * @param configUpdateStatusSelector
+ * @param configStatusSelector
* @param portletConfig
* returns populated configuration object.
*/
commit cbb57a8b8b0a04eb680881f364598bb821cfb6c5
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Jul 2 13:39:09 2012 -0400
[BZ 821058] refactor the unit test to use the templatized descriptor stuff. we now have a reusable descriptor that defines a server with two metrics that this test is using
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
index d94e32f..ed55d63 100644
--- a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
@@ -3,6 +3,7 @@ package org.rhq.core.pc.measurement;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;
+import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -36,11 +37,14 @@ import org.rhq.test.shrinkwrap.RhqAgentPluginArchive;
@RunDiscovery
public class ReadOnlyScheduleSetTest extends Arquillian {
- @Deployment(name = "bz821058Plugin")
+ @Deployment(name = "TwoMetricPlugin")
@TargetsContainer("connected-pc-with-metric-collection")
public static RhqAgentPluginArchive getTestPlugin() {
RhqAgentPluginArchive pluginJar = ShrinkWrap.create(RhqAgentPluginArchive.class, "bz821058-plugin-1.0.jar");
- return pluginJar.setPluginDescriptor("bz821058-rhq-plugin.xml").addClasses(
+ HashMap<String, String> replacements = new HashMap<String, String>();
+ replacements.put("@@@discovery@@@", SingleResourceDiscoveryComponent.class.getName());
+ replacements.put("@@@class@@@", BZ821058ResourceComponent.class.getName());
+ return pluginJar.setPluginDescriptorFromTemplate("two-metric-rhq-plugin.xml", replacements).addClasses(
SingleResourceDiscoveryComponent.class, BZ821058ResourceComponent.class);
}
@@ -53,10 +57,10 @@ public class ReadOnlyScheduleSetTest extends Arquillian {
private FakeServerInventory fakeServerInventory;
private FakeServerInventory.CompleteDiscoveryChecker discoveryCompleteChecker;
- @ResourceContainers(plugin = "bz821058Plugin", resourceType = "BZ821058Server")
+ @ResourceContainers(plugin = "TwoMetricPlugin", resourceType = "TwoMetricServer")
private Set<ResourceContainer> containers;
- @ResourceComponentInstances(plugin = "bz821058Plugin", resourceType = "BZ821058Server")
+ @ResourceComponentInstances(plugin = "TwoMetricPlugin", resourceType = "TwoMetricServer")
private Set<BZ821058ResourceComponent> components;
@BeforeDiscovery(testMethods = "testBZ821058")
diff --git a/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml b/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml
deleted file mode 100644
index c6adda6..0000000
--- a/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<plugin name="bz821058Plugin"
- displayName="Plugin to test BZ 821058"
- description="This will help test that measurement facet is given a read-only schedule set."
- 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="BZ821058Server"
- discovery="org.rhq.plugins.test.SingleResourceDiscoveryComponent"
- class="org.rhq.plugins.test.measurement.BZ821058ResourceComponent">
-
- <metric property="metric1"
- dataType="measurement"
- defaultOn="true"
- displayType="summary"
- defaultInterval="30000" />
-
- <metric property="metric2"
- dataType="measurement"
- defaultOn="true"
- displayType="summary"
- defaultInterval="30000" />
- </server>
-</plugin>
-
diff --git a/modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml b/modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml
new file mode 100644
index 0000000..4d9b7e1
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<plugin name="TwoMetricPlugin"
+ displayName="Plugin that has a single server with a two enabled metrics."
+ description="This will help test measurement collections by providing a server with a two enabled metrics."
+ 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="TwoMetricServer"
+ discovery="@@@discovery@@@"
+ class="@@@class@@@">
+
+ <metric property="metric1"
+ dataType="measurement"
+ defaultOn="true"
+ displayType="summary"
+ defaultInterval="30000" />
+
+ <metric property="metric2"
+ dataType="measurement"
+ defaultOn="true"
+ displayType="summary"
+ defaultInterval="30000" />
+ </server>
+</plugin>
commit 25b62b50adc3b8631f68e52304df22d7e8d7959a
Author: John Sanda <jsanda(a)redhat.com>
Date: Mon Jul 2 11:31:33 2012 -0400
[BZ 826716] Improve error reporting in the UI
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/DuplicateExpressionTypeException.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/DuplicateExpressionTypeException.java
new file mode 100644
index 0000000..4d51fc9
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/DuplicateExpressionTypeException.java
@@ -0,0 +1,38 @@
+/*
+ *
+ * * 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.core.domain.resource.group;
+
+/**
+ * @author John Sanda
+ */
+public class DuplicateExpressionTypeException extends InvalidExpressionException {
+
+ private static final long serialVersionUID = 1L;
+
+ private DuplicateExpressionTypeException() {
+ }
+
+ public DuplicateExpressionTypeException(String predicate) {
+ super("You cannot specify multiple " + predicate + " expressions.");
+ }
+
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/InvalidExpressionException.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/InvalidExpressionException.java
new file mode 100644
index 0000000..600ba04
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/InvalidExpressionException.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core.domain.resource.group;
+
+public class InvalidExpressionException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public InvalidExpressionException() {
+ }
+
+ public InvalidExpressionException(String message) {
+ super(message);
+ }
+
+ public InvalidExpressionException(Throwable cause) {
+ super(cause);
+ }
+
+ public InvalidExpressionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java
index bd196fc..6cd1a43 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java
@@ -27,6 +27,7 @@ import org.rhq.core.domain.resource.group.GroupDefinition;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
/**
* @author Greg Hinkle
@@ -64,9 +65,11 @@ public interface ResourceGroupGWTService extends RemoteService {
void setAssignedResources(int groupId, int[] resourceIds, boolean setType) throws RuntimeException;
- void recalculateGroupDefinitions(int[] groupDefinitionIds) throws RuntimeException;
+ void recalculateGroupDefinitions(int[] groupDefinitionIds)
+ throws DuplicateExpressionTypeException, RuntimeException;
- void updateGroupDefinition(GroupDefinition groupDefinition) throws RuntimeException;
+ void updateGroupDefinition(GroupDefinition groupDefinition)
+ throws DuplicateExpressionTypeException, RuntimeException;
void updateResourceGroup(ResourceGroup group) throws RuntimeException;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java
index ff3cab2..74484dd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java
@@ -33,6 +33,7 @@ import com.smartgwt.client.rpc.RPCResponse;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import org.rhq.core.domain.criteria.ResourceGroupDefinitionCriteria;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
import org.rhq.core.domain.resource.group.GroupDefinition;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
@@ -154,7 +155,11 @@ public class GroupDefinitionDataSource extends RPCDataSource<GroupDefinition, Re
new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_saveFailure(name), caught);
+ if (caught instanceof DuplicateExpressionTypeException) {
+ CoreGUI.getMessageCenter().notify(new Message(caught.getMessage(), Message.Severity.Warning));
+ } else {
+ CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_saveFailure(name), caught);
+ }
}
@Override
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java
index 38b5165..0661533 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java
@@ -18,6 +18,9 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.groups.definitions;
+import java.util.Date;
+import java.util.Set;
+
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.types.ListGridFieldType;
@@ -26,20 +29,23 @@ import com.smartgwt.client.widgets.grid.CellFormatter;
import com.smartgwt.client.widgets.grid.HoverCustomizer;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
+
import org.rhq.core.domain.authz.Permission;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.PermissionsLoadedListener;
import org.rhq.enterprise.gui.coregui.client.PermissionsLoader;
import org.rhq.enterprise.gui.coregui.client.ViewPath;
-import org.rhq.enterprise.gui.coregui.client.components.table.*;
+import org.rhq.enterprise.gui.coregui.client.components.table.AbstractTableAction;
+import org.rhq.enterprise.gui.coregui.client.components.table.EscapedHtmlCellFormatter;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableActionEnablement;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableSection;
+import org.rhq.enterprise.gui.coregui.client.components.table.TimestampCellFormatter;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.util.TableUtility;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
-
-import java.util.Date;
-import java.util.Set;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
/**
* @author Greg Hinkle
@@ -156,7 +162,12 @@ public class GroupDefinitionListView extends TableSection<GroupDefinitionDataSou
resourceGroupManager.recalculateGroupDefinitions(groupDefinitionIds, new AsyncCallback<Void>() {
public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_recalcFailureSelection(), caught);
+ if (caught instanceof DuplicateExpressionTypeException) {
+ CoreGUI.getMessageCenter().notify(new Message(caught.getMessage(),
+ Message.Severity.Warning));
+ } else {
+ CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_recalcFailureSelection(), caught);
+ }
}
public void onSuccess(Void result) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java
index f55c37a..c417426 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java
@@ -61,6 +61,7 @@ import com.smartgwt.client.widgets.layout.HLayout;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.criteria.ResourceGroupDefinitionCriteria;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
import org.rhq.core.domain.resource.group.GroupCategory;
import org.rhq.core.domain.resource.group.GroupDefinition;
import org.rhq.core.domain.util.PageList;
@@ -239,7 +240,11 @@ public class SingleGroupDefinitionView extends LocatableVLayout implements Bookm
new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_recalcFailure(), caught);
+ if (caught instanceof DuplicateExpressionTypeException) {
+ CoreGUI.getMessageCenter().notify(new Message(caught.getMessage(), Message.Severity.Warning));
+ } else {
+ CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_recalcFailure(), caught);
+ }
}
@Override
@@ -487,6 +492,7 @@ public class SingleGroupDefinitionView extends LocatableVLayout implements Bookm
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(
MSG.view_dynagroup_loadDefinitionFailure(String.valueOf(groupDefinitionId)), caught);
+
History.back();
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java
index b098980..8c5c54d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java
@@ -29,6 +29,7 @@ import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTService;
import org.rhq.enterprise.gui.coregui.server.util.SerialUtility;
import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.resource.group.definition.GroupDefinitionManagerLocal;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
import org.rhq.enterprise.server.util.LookupUtil;
/**
@@ -146,20 +147,28 @@ public class ResourceGroupGWTServiceImpl extends AbstractGWTServiceImpl implemen
}
}
- public void updateGroupDefinition(GroupDefinition groupDefinition) throws RuntimeException {
+ public void updateGroupDefinition(GroupDefinition groupDefinition)
+ throws DuplicateExpressionTypeException, RuntimeException {
try {
definitionManager.updateGroupDefinition(getSessionSubject(), groupDefinition);
} catch (Throwable t) {
+ if (t instanceof DuplicateExpressionTypeException) {
+ throw (DuplicateExpressionTypeException) t;
+ }
throw getExceptionToThrowToClient(t);
}
}
- public void recalculateGroupDefinitions(int[] groupDefinitionIds) throws RuntimeException {
+ public void recalculateGroupDefinitions(int[] groupDefinitionIds)
+ throws DuplicateExpressionTypeException, RuntimeException {
try {
for (int nextGroupDefinitionId : groupDefinitionIds) {
definitionManager.calculateGroupMembership(getSessionSubject(), nextGroupDefinitionId);
}
} catch (Throwable t) {
+ if (t instanceof DuplicateExpressionTypeException) {
+ throw (DuplicateExpressionTypeException) t;
+ }
throw getExceptionToThrowToClient(t);
}
}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java
index 262c173..b3a1edd 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java
@@ -31,7 +31,7 @@ import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
import org.rhq.enterprise.server.resource.group.ResourceGroupUpdateException;
import org.rhq.enterprise.server.resource.group.definition.GroupDefinitionManagerLocal;
import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionException;
-import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
import org.rhq.enterprise.server.util.LookupUtil;
public class EditGroupDefinitionGeneralPropertiesUIBean {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java
index 3776c70..190a169 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java
@@ -62,7 +62,7 @@ import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefini
import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionNotFoundException;
import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionUpdateException;
import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
-import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
import org.rhq.enterprise.server.resource.group.definition.mbean.GroupDefinitionRecalculationThreadMonitor;
import org.rhq.enterprise.server.resource.group.definition.mbean.GroupDefinitionRecalculationThreadMonitorMBean;
import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java
index d83c77c..b1d0d1d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java
@@ -33,7 +33,7 @@ import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefini
import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionNotFoundException;
import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionUpdateException;
import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
-import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
@Local
public interface GroupDefinitionManagerLocal {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java
deleted file mode 100644
index 2b34b05..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *
- * * 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.group.definition.framework;
-
-/**
- * @author John Sanda
- */
-public class DuplicateExpressionTypeException extends InvalidExpressionException {
-
- private static final long serialVersionUID = 1L;
-
- private DuplicateExpressionTypeException() {
- }
-
- public DuplicateExpressionTypeException(String predicate) {
- super("You cannot specify multiple " + predicate + " expressions.");
- }
-
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
index 925d59d..7f42f55 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
@@ -28,7 +28,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.TreeSet;
+import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -39,6 +39,8 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
import org.rhq.enterprise.server.common.EntityManagerFacadeLocal;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.util.QueryUtility;
@@ -93,7 +95,7 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
private EntityManagerFacadeLocal entityManagerFacade;
- private Set<String> resourceExpressions = new TreeSet<String>();
+ private Map<String, String> resourceExpressions = new TreeMap<String, String>();
public ExpressionEvaluator() {
/*
@@ -129,69 +131,77 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
*/
whereStatics.add("res.inventoryStatus = org.rhq.core.domain.resource.InventoryStatus.COMMITTED");
- resourceExpressions.add("res.id");
- resourceExpressions.add("child.id");
- resourceExpressions.add("res.parentResource.id");
- resourceExpressions.add("res.parentResource.parentResource.id");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.id");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.id");
-
- resourceExpressions.add("res.name");
- resourceExpressions.add("child.name");
- resourceExpressions.add("res.parentResource.name");
- resourceExpressions.add("res.parentResource.parentResource.name");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.name");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.name");
-
- resourceExpressions.add("res.version");
- resourceExpressions.add("child.version");
- resourceExpressions.add("res.parentResource.version");
- resourceExpressions.add("res.parentResource.parentResource.version");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.version");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.version");
-
-
- resourceExpressions.add("res.resourceType.plugin");
- resourceExpressions.add("res.resourceType.name");
- resourceExpressions.add("child.resourceType.plugin");
- resourceExpressions.add("child.resourceType.name");
- resourceExpressions.add("res.parentResource.resourceType.plugin");
- resourceExpressions.add("res.parentResource.resourceType.name");
- resourceExpressions.add("res.parentResource.parentResource.resourceType.plugin");
- resourceExpressions.add("res.parentResource.parentResource.resourceType.name");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.plugin");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.name");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.plugin");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.name");
-
-
- resourceExpressions.add("res.resourceType.category");
- resourceExpressions.add("child.resourceType.category");
- resourceExpressions.add("res.parentResource.resourceType.category");
- resourceExpressions.add("res.parentResource.parentResource.resourceType.category");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.category");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.category");
-
- resourceExpressions.add("avail.availabilityType");
- resourceExpressions.add("child.avail.availabilityType");
- resourceExpressions.add("res.parentResource.avail.availabilityType");
- resourceExpressions.add("res.parentResource.parentResource.avail.availabilityType");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.avail.availabilityType");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.avail.availabilityType");
-
- resourceExpressions.add("trait.value");
- resourceExpressions.add("child.trait.value");
- resourceExpressions.add("res.parentResource.trait.value");
- resourceExpressions.add("res.parentResource.parentResource.trait.value");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.trait.value");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.trait.value");
-
- resourceExpressions.add("simple.name");
- resourceExpressions.add("child.simple.name");
- resourceExpressions.add("res.parentResource.simple.name");
- resourceExpressions.add("res.parentResource.parentResource.simple.name");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.simple.name");
- resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.simple.name");
+ resourceExpressions.put("res.id", "resource id");
+ resourceExpressions.put("child.id", "resource id");
+ resourceExpressions.put("res.parentResource.id", "resource id");
+ resourceExpressions.put("res.parentResource.parentResource.id", "resource id");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.id", "resource id");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.id", "resource id");
+
+ resourceExpressions.put("res.name", "resource name");
+ resourceExpressions.put("child.name", "resource name");
+ resourceExpressions.put("res.parentResource.name", "resource name");
+ resourceExpressions.put("res.parentResource.parentResource.name", "resource name");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.name", "resource name");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.name",
+ "resource name");
+
+ resourceExpressions.put("res.version", "resource version");
+ resourceExpressions.put("child.version", "resource version");
+ resourceExpressions.put("res.parentResource.version", "resource version");
+ resourceExpressions.put("res.parentResource.parentResource.version", "resource version");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.version", "resource version");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.version",
+ "resource version");
+
+ resourceExpressions.put("res.resourceType.plugin", "resource type");
+ resourceExpressions.put("res.resourceType.name", "resource type");
+ resourceExpressions.put("child.resourceType.plugin", "resource type");
+ resourceExpressions.put("child.resourceType.name", "resource type");
+ resourceExpressions.put("res.parentResource.resourceType.plugin", "resource type");
+ resourceExpressions.put("res.parentResource.resourceType.name", "resource type");
+ resourceExpressions.put("res.parentResource.parentResource.resourceType.plugin", "resource type");
+ resourceExpressions.put("res.parentResource.parentResource.resourceType.name", "resource type");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.resourceType.plugin",
+ "resource type");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.resourceType.name", "resource type");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.resourceType.plugin",
+ "resource type");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.resourceType.name",
+ "resource type");
+
+ resourceExpressions.put("res.resourceType.category", "resource category");
+ resourceExpressions.put("child.resourceType.category", "resource category");
+ resourceExpressions.put("res.parentResource.resourceType.category", "resource category");
+ resourceExpressions.put("res.parentResource.parentResource.resourceType.category", "resource category");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.resourceType.category",
+ "resource category");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.resourceType.category",
+ "resource category");
+
+ resourceExpressions.put("avail.availabilityType", "availability");
+ resourceExpressions.put("child.avail.availabilityType", "availability");
+ resourceExpressions.put("res.parentResource.avail.availabilityType", "availability");
+ resourceExpressions.put("res.parentResource.parentResource.avail.availabilityType", "availability");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.avail.availabilityType",
+ "availability");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.avail.availabilityType",
+ "availability");
+
+ resourceExpressions.put("trait.value", "trait");
+ resourceExpressions.put("child.trait.value", "trait");
+ resourceExpressions.put("res.parentResource.trait.value", "trait");
+ resourceExpressions.put("res.parentResource.parentResource.trait.value", "trait");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.trait.value", "trait");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.trait.value", "trait");
+
+ resourceExpressions.put("simple.name", "configuration");
+ resourceExpressions.put("child.simple.name", "configuration");
+ resourceExpressions.put("res.parentResource.simple.name", "configuration");
+ resourceExpressions.put("res.parentResource.parentResource.simple.name", "configuration");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.simple.name", "configuration");
+ resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.simple.name",
+ "configuration");
}
public class Result {
@@ -231,7 +241,7 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
*
* @return a reference to itself, so that method chaining can be used
*
- * @throws InvalidExpressionException if the expression can not be parsed for any reason, the message will try to
+ * @throws org.rhq.core.domain.resource.group.InvalidExpressionException if the expression can not be parsed for any reason, the message will try to
* get the details as to the parse failure
*/
public ExpressionEvaluator addExpression(String expression) throws InvalidExpressionException {
@@ -779,8 +789,8 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
+ "] for predicate population");
}
- if (resourceExpressions.contains(predicateName) && whereConditions.containsKey(predicateName)) {
- throw new DuplicateExpressionTypeException(predicateName);
+ if (resourceExpressions.containsKey(predicateName) && whereConditions.containsKey(predicateName)) {
+ throw new DuplicateExpressionTypeException(resourceExpressions.get(predicateName));
}
whereConditions.put(predicateName, argumentName);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/InvalidExpressionException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/InvalidExpressionException.java
deleted file mode 100644
index 06c7558..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/InvalidExpressionException.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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;
-
-public class InvalidExpressionException extends Exception {
- private static final long serialVersionUID = 1L;
-
- public InvalidExpressionException() {
- }
-
- public InvalidExpressionException(String message) {
- super(message);
- }
-
- public InvalidExpressionException(Throwable cause) {
- super(cause);
- }
-
- public InvalidExpressionException(String message, Throwable cause) {
- super(message, cause);
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
index 76c5824..a1c8a65 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
@@ -24,9 +24,9 @@ import java.util.List;
import org.testng.annotations.Test;
-import org.rhq.enterprise.server.resource.group.definition.framework.DuplicateExpressionTypeException;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
-import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.util.QueryUtility;
commit c97c6b90b7cd8d54c3974b8bddc61fe808e2b72b
Author: John Sanda <jsanda(a)redhat.com>
Date: Wed Jun 27 14:19:03 2012 -0400
[BZ 826716] Adding tests for plugin and resource config expressions.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
index 32565b6..925d59d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
@@ -178,6 +178,20 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
resourceExpressions.add("res.parentResource.parentResource.avail.availabilityType");
resourceExpressions.add("res.parentResource.parentResource.parentResource.avail.availabilityType");
resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.avail.availabilityType");
+
+ resourceExpressions.add("trait.value");
+ resourceExpressions.add("child.trait.value");
+ resourceExpressions.add("res.parentResource.trait.value");
+ resourceExpressions.add("res.parentResource.parentResource.trait.value");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.trait.value");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.trait.value");
+
+ resourceExpressions.add("simple.name");
+ resourceExpressions.add("child.simple.name");
+ resourceExpressions.add("res.parentResource.simple.name");
+ resourceExpressions.add("res.parentResource.parentResource.simple.name");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.simple.name");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.simple.name");
}
public class Result {
@@ -549,10 +563,6 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
addJoinCondition(JoinCondition.AVAILABILITY);
populatePredicateCollections(JoinCondition.AVAILABILITY.alias + ".availabilityType", type);
} else if (context == ParseContext.Trait) {
- if (whereConditions.containsKey(TRAIT_ALIAS + ".value")) {
- throw new InvalidExpressionException("Cannot have multiple trait expressions.");
- }
-
// SELECT res.id FROM Resource res JOIN res.schedules sched, sched.definition def, MeasurementDataTrait trait
// WHERE def.name = :arg1 AND trait.value = :arg2 AND trait.schedule = sched AND trait.id.timestamp =
// (SELECT max(mdt.id.timestamp) FROM MeasurementDataTrait mdt WHERE sched.id = mdt.schedule.id)
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
index 78ee34f..76c5824 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
@@ -29,7 +29,6 @@ import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionE
import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.util.QueryUtility;
-import org.rhq.test.TransactionCallback;
public class ExpressionEvaluatorTest extends AbstractEJB3Test {
@@ -158,7 +157,7 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
" AND simple.name = simpleDef.name AND simpleDef.type != 'PASSWORD' " }, };
}
-// @Test(groups = "integration.session")
+ @Test(groups = "integration.session")
public void testWellFormedExpressions() throws Exception {
String[][] successTestCases = getSuccessTestCases();
@@ -215,7 +214,7 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
}
}
-// @Test(groups = "integration.session")
+ @Test(groups = "integration.session")
public void testTokenizer() {
String[] input = { "resource.child.name", //
@@ -257,15 +256,6 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
}
}
- private void executeAndRollback(TransactionCallback callback) throws Exception {
- try {
- getTransactionManager().begin();
- callback.execute();
- } finally {
- getTransactionManager().rollback();
- }
- }
-
private static interface ExpressionGenerator {
String[] getExpressions();
}
@@ -284,34 +274,86 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
}
}
- @Test(expectedExceptions = InvalidExpressionException.class,
- expectedExceptionsMessageRegExp = ".*Cannot have multiple trait expressions.*")
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
public void doNotAllowMultipleResourceTraitExpressions() throws Exception {
- executeAndRollback(new TransactionCallback() {
+ evaluateExpressions(new ExpressionGenerator() {
@Override
- public void execute() throws Exception {
- ExpressionEvaluator evaluator = new ExpressionEvaluator();
- evaluator.addExpression("resource.trait[agentHomeDirectory] = /var/rhq-agent");
- evaluator.addExpression("resource.trait[reasonForLastRestart] = OOMError");
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.trait[agentHomeDirectory] = /var/rhq-agent",
+ "resource.trait[reasonForLastRestart] = OOMError"
+ };
+ }
+ });
+ }
- evaluator.execute();
- evaluator.iterator().next();
+ @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 = InvalidExpressionException.class,
- expectedExceptionsMessageRegExp = ".*Cannot have multiple trait expressions.*")
- public void doNotAllowMultiplParentResourceTraitExpressions() throws Exception {
- executeAndRollback(new TransactionCallback() {
+ @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+ expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+ public void doNotAllowMultipleParentResourceTraitExpressions() throws Exception {
+ evaluateExpressions(new ExpressionGenerator() {
@Override
- public void execute() throws Exception {
- ExpressionEvaluator evaluator = new ExpressionEvaluator();
- evaluator.addExpression("resource.parent.trait[agentHomeDirectory] = /var/rhq-agent");
- evaluator.addExpression("resource.parent.trait[reasonForLastRestart] = OOMError");
+ public String[] getExpressions() {
+ return new String[] {
+ "resource.parent.trait[agentHomeDirectory] = /var/rhq-agent",
+ "resource.parent.trait[reasonForLastRestart] = OOMError"
+ };
+ }
+ });
+ }
- evaluator.execute();
- evaluator.iterator().next();
+ @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"
+ };
}
});
}
@@ -748,6 +790,174 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
});
}
+ @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();
}
commit 95a0bf5b8be8a17638bd1b6fbf740e959e19af31
Author: John Sanda <jsanda(a)redhat.com>
Date: Tue Jun 26 17:04:29 2012 -0400
[BZ 667896] Adding more tests to verify we do not allow multiple expressions of the same type
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java
new file mode 100644
index 0000000..2b34b05
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java
@@ -0,0 +1,38 @@
+/*
+ *
+ * * 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.group.definition.framework;
+
+/**
+ * @author John Sanda
+ */
+public class DuplicateExpressionTypeException extends InvalidExpressionException {
+
+ private static final long serialVersionUID = 1L;
+
+ private DuplicateExpressionTypeException() {
+ }
+
+ public DuplicateExpressionTypeException(String predicate) {
+ super("You cannot specify multiple " + predicate + " expressions.");
+ }
+
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
index 1f7e300..32565b6 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
@@ -28,6 +28,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -92,6 +93,8 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
private EntityManagerFacadeLocal entityManagerFacade;
+ private Set<String> resourceExpressions = new TreeSet<String>();
+
public ExpressionEvaluator() {
/*
* used LinkedHashMap for whereConditions on purpose so that the iterator will return them in the same order
@@ -125,6 +128,56 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
* initialization for special handling that all dynagroups should get
*/
whereStatics.add("res.inventoryStatus = org.rhq.core.domain.resource.InventoryStatus.COMMITTED");
+
+ resourceExpressions.add("res.id");
+ resourceExpressions.add("child.id");
+ resourceExpressions.add("res.parentResource.id");
+ resourceExpressions.add("res.parentResource.parentResource.id");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.id");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.id");
+
+ resourceExpressions.add("res.name");
+ resourceExpressions.add("child.name");
+ resourceExpressions.add("res.parentResource.name");
+ resourceExpressions.add("res.parentResource.parentResource.name");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.name");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.name");
+
+ resourceExpressions.add("res.version");
+ resourceExpressions.add("child.version");
+ resourceExpressions.add("res.parentResource.version");
+ resourceExpressions.add("res.parentResource.parentResource.version");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.version");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.version");
+
+
+ resourceExpressions.add("res.resourceType.plugin");
+ resourceExpressions.add("res.resourceType.name");
+ resourceExpressions.add("child.resourceType.plugin");
+ resourceExpressions.add("child.resourceType.name");
+ resourceExpressions.add("res.parentResource.resourceType.plugin");
+ resourceExpressions.add("res.parentResource.resourceType.name");
+ resourceExpressions.add("res.parentResource.parentResource.resourceType.plugin");
+ resourceExpressions.add("res.parentResource.parentResource.resourceType.name");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.plugin");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.name");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.plugin");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.name");
+
+
+ resourceExpressions.add("res.resourceType.category");
+ resourceExpressions.add("child.resourceType.category");
+ resourceExpressions.add("res.parentResource.resourceType.category");
+ resourceExpressions.add("res.parentResource.parentResource.resourceType.category");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.category");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.category");
+
+ resourceExpressions.add("avail.availabilityType");
+ resourceExpressions.add("child.avail.availabilityType");
+ resourceExpressions.add("res.parentResource.avail.availabilityType");
+ resourceExpressions.add("res.parentResource.parentResource.avail.availabilityType");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.avail.availabilityType");
+ resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.avail.availabilityType");
}
public class Result {
@@ -716,6 +769,10 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
+ "] for predicate population");
}
+ if (resourceExpressions.contains(predicateName) && whereConditions.containsKey(predicateName)) {
+ throw new DuplicateExpressionTypeException(predicateName);
+ }
+
whereConditions.put(predicateName, argumentName);
whereReplacements.put(argumentName, value);
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
index f0a64ff..78ee34f 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
@@ -24,10 +24,12 @@ import java.util.List;
import org.testng.annotations.Test;
+import org.rhq.enterprise.server.resource.group.definition.framework.DuplicateExpressionTypeException;
import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.util.QueryUtility;
+import org.rhq.test.TransactionCallback;
public class ExpressionEvaluatorTest extends AbstractEJB3Test {
@@ -255,24 +257,495 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
}
}
- @Test(expectedExceptions = InvalidExpressionException.class)
- public void throwExceptionWhenMultipleResourceTraitsSpecified() throws Exception {
- ExpressionEvaluator evaluator = new ExpressionEvaluator();
- evaluator.addExpression("resource.trait[agentHomeDirectory] = /var/rhq-agent");
- evaluator.addExpression("resource.trait[reasonForLastRestart] = OOMError");
+ private void executeAndRollback(TransactionCallback callback) throws Exception {
+ try {
+ getTransactionManager().begin();
+ callback.execute();
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
- evaluator.execute();
- evaluator.iterator().next();
+ private static interface ExpressionGenerator {
+ String[] getExpressions();
}
- @Test(expectedExceptions = InvalidExpressionException.class)
- public void throwExceptionWhenMultipleResourceParentTraitsSpecified() throws Exception {
- ExpressionEvaluator evaluator = new ExpressionEvaluator();
- evaluator.addExpression("resource.parent.trait[agentHomeDirectory] = /var/rhq-agent");
- evaluator.addExpression("resource.parent.trait[reasonForLastRestart] = OOMError");
+ 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 = InvalidExpressionException.class,
+ expectedExceptionsMessageRegExp = ".*Cannot have multiple trait expressions.*")
+ public void doNotAllowMultipleResourceTraitExpressions() throws Exception {
+ executeAndRollback(new TransactionCallback() {
+ @Override
+ public void execute() throws Exception {
+ ExpressionEvaluator evaluator = new ExpressionEvaluator();
+ evaluator.addExpression("resource.trait[agentHomeDirectory] = /var/rhq-agent");
+ evaluator.addExpression("resource.trait[reasonForLastRestart] = OOMError");
+
+ evaluator.execute();
+ evaluator.iterator().next();
+ }
+ });
+ }
+
+ @Test(expectedExceptions = InvalidExpressionException.class,
+ expectedExceptionsMessageRegExp = ".*Cannot have multiple trait expressions.*")
+ public void doNotAllowMultiplParentResourceTraitExpressions() throws Exception {
+ executeAndRollback(new TransactionCallback() {
+ @Override
+ public void execute() throws Exception {
+ ExpressionEvaluator evaluator = new ExpressionEvaluator();
+ evaluator.addExpression("resource.parent.trait[agentHomeDirectory] = /var/rhq-agent");
+ evaluator.addExpression("resource.parent.trait[reasonForLastRestart] = OOMError");
+
+ evaluator.execute();
+ evaluator.iterator().next();
+ }
+ });
+ }
+
+ @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"
+ };
+ }
+ });
+ }
- evaluator.execute();
- evaluator.iterator().next();
+ @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"
+ };
+ }
+ });
}
private String cleanUp(String result) {
commit 3442a828acc2a6e82e6d845f852246d66b2f2053
Author: John Sanda <jsanda(a)redhat.com>
Date: Fri Jun 22 21:33:59 2012 -0400
[BZ 667896] Throw exception if multiple trait expressions specified
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
index 480c97f..1f7e300 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
@@ -496,6 +496,10 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
addJoinCondition(JoinCondition.AVAILABILITY);
populatePredicateCollections(JoinCondition.AVAILABILITY.alias + ".availabilityType", type);
} else if (context == ParseContext.Trait) {
+ if (whereConditions.containsKey(TRAIT_ALIAS + ".value")) {
+ throw new InvalidExpressionException("Cannot have multiple trait expressions.");
+ }
+
// SELECT res.id FROM Resource res JOIN res.schedules sched, sched.definition def, MeasurementDataTrait trait
// WHERE def.name = :arg1 AND trait.value = :arg2 AND trait.schedule = sched AND trait.id.timestamp =
// (SELECT max(mdt.id.timestamp) FROM MeasurementDataTrait mdt WHERE sched.id = mdt.schedule.id)
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
index fd3db2e..f0a64ff 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
@@ -25,6 +25,7 @@ import java.util.List;
import org.testng.annotations.Test;
import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
+import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.util.QueryUtility;
@@ -155,7 +156,7 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
" AND simple.name = simpleDef.name AND simpleDef.type != 'PASSWORD' " }, };
}
- @Test(groups = "integration.session")
+// @Test(groups = "integration.session")
public void testWellFormedExpressions() throws Exception {
String[][] successTestCases = getSuccessTestCases();
@@ -212,7 +213,7 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
}
}
- @Test(groups = "integration.session")
+// @Test(groups = "integration.session")
public void testTokenizer() {
String[] input = { "resource.child.name", //
@@ -254,6 +255,26 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
}
}
+ @Test(expectedExceptions = InvalidExpressionException.class)
+ public void throwExceptionWhenMultipleResourceTraitsSpecified() throws Exception {
+ ExpressionEvaluator evaluator = new ExpressionEvaluator();
+ evaluator.addExpression("resource.trait[agentHomeDirectory] = /var/rhq-agent");
+ evaluator.addExpression("resource.trait[reasonForLastRestart] = OOMError");
+
+ evaluator.execute();
+ evaluator.iterator().next();
+ }
+
+ @Test(expectedExceptions = InvalidExpressionException.class)
+ public void throwExceptionWhenMultipleResourceParentTraitsSpecified() throws Exception {
+ ExpressionEvaluator evaluator = new ExpressionEvaluator();
+ evaluator.addExpression("resource.parent.trait[agentHomeDirectory] = /var/rhq-agent");
+ evaluator.addExpression("resource.parent.trait[reasonForLastRestart] = OOMError");
+
+ evaluator.execute();
+ evaluator.iterator().next();
+ }
+
private String cleanUp(String result) {
return result.replaceAll("\\s+", " ").trim();
}
commit 73da0abdb93a5925e79ea1d35a62d15557bd96e1
Merge: fbb4fd5 b48676a
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Jul 2 14:47:36 2012 +0200
Merge remote-tracking branch 'origin/master' into lkrejci/modular-scripting
commit fbb4fd565dec268144e29692bb8c20cc98e9c487
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Jul 2 14:36:31 2012 +0200
Javascript completor now correctly outputs the signatures of the methods.
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java
index ff98b5c..a8da737 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java
@@ -22,6 +22,7 @@ package org.rhq.enterprise.client.utility;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import javax.jws.WebParam;
@@ -34,6 +35,26 @@ import org.rhq.scripting.MetadataProvider;
public class CLIMetadataProvider implements MetadataProvider {
@Override
+ public Method getUnproxiedMethod(Method method) {
+ if (Proxy.isProxyClass(method.getDeclaringClass())) {
+ //ok, don't look at the proxy class but at the interface that is actually defining this method
+ for (Class<?> iface : method.getDeclaringClass().getInterfaces()) {
+ try {
+ Method ifaceMethod = iface.getMethod(method.getName(), method.getParameterTypes());
+ return ifaceMethod;
+ } catch (NoSuchMethodException e) {
+ //well, never mind, let's try the next interface
+ } catch (SecurityException e) {
+ //whoa
+ throw new IllegalStateException("Current code doesn't have reflection permissions.", e);
+ }
+ }
+ }
+
+ return method;
+ }
+
+ @Override
public String getParameterName(Method method, int parameterIndex) {
String name = null;
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java
index 598d952..448da46 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java
@@ -37,6 +37,21 @@ import java.lang.reflect.Type;
public interface MetadataProvider {
/**
+ * Many of the objects that RHQ exposes in the scripting environment are implemented
+ * using proxies. But proxies don't seem to maintain the generic types on them.
+ * <p>
+ * This method tries to find out if given method comes from a proxy class and if it is,
+ * it tries to find the method in one of the interfaces that the proxy implements that
+ * corresponds to it. That method is going to have all the metadata - i.e. annotations,
+ * generics, etc.
+ *
+ * @param method the method to inspect
+ * @return the method from one of the interfaces implemented by the given method's declaring class
+ * or the given method itself if it is not proxied.
+ */
+ Method getUnproxiedMethod(Method method);
+
+ /**
* Tries to determine the name of a parameter on a method.
*
* @param method the method
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 36eb060..f90969a 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
@@ -276,6 +276,9 @@ public class JavascriptCompletor implements CodeCompletion {
maxReturnLength = sig[0].length();
}
+ output.println();
+ output.println();
+
for (String[] sig : signatures) {
for (i = 0; i < (maxReturnLength - sig[0].length()); i++) {
output.print(" ");
@@ -500,6 +503,7 @@ public class JavascriptCompletor implements CodeCompletion {
StringBuilder buf = new StringBuilder();
Type[] params = m.getGenericParameterTypes();
int i = 0;
+ m = metadataProvider.getUnproxiedMethod(m);
buf.append(metadataProvider.getTypeName(m.getGenericReturnType(), false));
buf.append(" ");
commit fca41ffec5ff7d32735f4c25d033b240a6d1df4b
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Jul 2 14:32:56 2012 +0200
The CLI interactive console correctly handles the case where the completor outputs some additional text to the output.
The output is flushed and the commandline is re-printed underneath it.
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index 5d1af69..cfe1686 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@ -241,7 +241,7 @@ public class ClientMain {
initCodeCompletion();
consoleReader.addCompletor(new MultiCompletor(new Completor[] {
- new CodeCompletionCompletorWrapper(codeCompletion, outputWriter), helpCompletor,
+ new CodeCompletionCompletorWrapper(codeCompletion, outputWriter, consoleReader), helpCompletor,
commandCompletor }));
// enable pagination
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ChangeRegisteringPrintWriter.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ChangeRegisteringPrintWriter.java
new file mode 100644
index 0000000..dfc03b4
--- /dev/null
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ChangeRegisteringPrintWriter.java
@@ -0,0 +1,233 @@
+/*
+ * 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.client.utility;
+
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Locale;
+
+/**
+ * @author Lukas Krejci
+ *
+ */
+public class ChangeRegisteringPrintWriter extends PrintWriter {
+
+ private boolean changed;
+
+ public ChangeRegisteringPrintWriter(Writer out) {
+ super(out);
+ }
+
+ public boolean isChanged() {
+ return changed;
+ }
+
+ public void setChanged(boolean changed) {
+ this.changed = changed;
+ }
+
+ @Override
+ public PrintWriter append(char c) {
+ setChanged(true);
+ return super.append(c);
+ }
+
+ @Override
+ public void write(int c) {
+ setChanged(true);
+ super.write(c);
+ }
+
+ @Override
+ public void write(char[] buf, int off, int len) {
+ setChanged(true);
+ super.write(buf, off, len);
+ }
+
+ @Override
+ public void write(char[] buf) {
+ setChanged(true);
+ super.write(buf);
+ }
+
+ @Override
+ public void write(String s, int off, int len) {
+ setChanged(true);
+ super.write(s, off, len);
+ }
+
+ @Override
+ public void write(String s) {
+ setChanged(true);
+ super.write(s);
+ }
+
+ @Override
+ public void print(boolean b) {
+ setChanged(true);
+ super.print(b);
+ }
+
+ @Override
+ public void print(char c) {
+ setChanged(true);
+ super.print(c);
+ }
+
+ @Override
+ public void print(int i) {
+ setChanged(true);
+ super.print(i);
+ }
+
+ @Override
+ public void print(long l) {
+ setChanged(true);
+ super.print(l);
+ }
+
+ @Override
+ public void print(float f) {
+ setChanged(true);
+ super.print(f);
+ }
+
+ @Override
+ public void print(double d) {
+ setChanged(true);
+ super.print(d);
+ }
+
+ @Override
+ public void print(char[] s) {
+ setChanged(true);
+ super.print(s);
+ }
+
+ @Override
+ public void print(String s) {
+ setChanged(true);
+ super.print(s);
+ }
+
+ @Override
+ public void print(Object obj) {
+ setChanged(true);
+ super.print(obj);
+ }
+
+ @Override
+ public void println() {
+ setChanged(true);
+ super.println();
+ }
+
+ @Override
+ public void println(boolean x) {
+ setChanged(true);
+ super.println(x);
+ }
+
+ @Override
+ public void println(char x) {
+ setChanged(true);
+ super.println(x);
+ }
+
+ @Override
+ public void println(int x) {
+ setChanged(true);
+ super.println(x);
+ }
+
+ @Override
+ public void println(long x) {
+ setChanged(true);
+ super.println(x);
+ }
+
+ @Override
+ public void println(float x) {
+ setChanged(true);
+ super.println(x);
+ }
+
+ @Override
+ public void println(double x) {
+ setChanged(true);
+ super.println(x);
+ }
+
+ @Override
+ public void println(char[] x) {
+ setChanged(true);
+ super.println(x);
+ }
+
+ @Override
+ public void println(String x) {
+ setChanged(true);
+ super.println(x);
+ }
+
+ @Override
+ public void println(Object x) {
+ setChanged(true);
+ super.println(x);
+ }
+
+ @Override
+ public PrintWriter printf(String format, Object... args) {
+ setChanged(true);
+ return super.printf(format, args);
+ }
+
+ @Override
+ public PrintWriter printf(Locale l, String format, Object... args) {
+ setChanged(true);
+ return super.printf(l, format, args);
+ }
+
+ @Override
+ public PrintWriter format(String format, Object... args) {
+ setChanged(true);
+ return super.format(format, args);
+ }
+
+ @Override
+ public PrintWriter format(Locale l, String format, Object... args) {
+ setChanged(true);
+ return super.format(l, format, args);
+ }
+
+ @Override
+ public PrintWriter append(CharSequence csq) {
+ setChanged(true);
+ return super.append(csq);
+ }
+
+ @Override
+ public PrintWriter append(CharSequence csq, int start, int end) {
+ setChanged(true);
+ return super.append(csq, start, end);
+ }
+
+}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java
index 8f2570c..4be3613 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java
@@ -1,24 +1,48 @@
package org.rhq.enterprise.client.utility;
+import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import jline.Completor;
+import jline.ConsoleReader;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.rhq.scripting.CodeCompletion;
public class CodeCompletionCompletorWrapper implements Completor {
+ private static final Log LOG = LogFactory.getLog(CodeCompletionCompletorWrapper.class);
+
private CodeCompletion completion;
- private PrintWriter output;
+ private ChangeRegisteringPrintWriter output;
+ private ConsoleReader consoleReader;
- public CodeCompletionCompletorWrapper(CodeCompletion completion, PrintWriter output) {
+ public CodeCompletionCompletorWrapper(CodeCompletion completion, PrintWriter output, ConsoleReader consoleReader) {
this.completion = completion;
- this.output = output;
+ this.output = new ChangeRegisteringPrintWriter(output);
+ this.consoleReader = consoleReader;
}
@Override
public int complete(String buffer, int cursor, List candidates) {
- return completion.complete(output, buffer, cursor, candidates);
+ String start = this.consoleReader.getCursorBuffer().getBuffer().toString();
+
+ output.setChanged(false);
+ int ret = completion.complete(output, buffer, cursor, candidates);
+
+ if (output.isChanged()) {
+ try {
+ output.flush();
+ consoleReader.printNewline();
+ consoleReader.drawLine();
+ } catch (IOException e) {
+ LOG.debug("Failed to draw a console reader line.", e);
+ }
+ }
+
+ return ret;
}
}
commit 1d1e61836632b35abe0a30b67b6b999cd4a84ef0
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Jul 2 14:30:32 2012 +0200
InterfaceSimplifier now mirrors the generic type signatures and annotations
on all levels.
The newly generated class preserves the generic type signatures and
annotations on the class, method and method parameter levels.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
index d6835a0..dc29bc9 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
@@ -18,13 +18,37 @@
*/
package org.rhq.bindings.util;
+import java.util.ArrayList;
+import java.util.List;
+
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
+import javassist.Modifier;
import javassist.NotFoundException;
+import javassist.bytecode.AnnotationsAttribute;
+import javassist.bytecode.ClassFile;
+import javassist.bytecode.ConstPool;
import javassist.bytecode.ParameterAnnotationsAttribute;
+import javassist.bytecode.SignatureAttribute;
+import javassist.bytecode.annotation.Annotation;
+import javassist.bytecode.annotation.AnnotationMemberValue;
+import javassist.bytecode.annotation.ArrayMemberValue;
+import javassist.bytecode.annotation.BooleanMemberValue;
+import javassist.bytecode.annotation.ByteMemberValue;
+import javassist.bytecode.annotation.CharMemberValue;
+import javassist.bytecode.annotation.ClassMemberValue;
+import javassist.bytecode.annotation.DoubleMemberValue;
+import javassist.bytecode.annotation.EnumMemberValue;
+import javassist.bytecode.annotation.FloatMemberValue;
+import javassist.bytecode.annotation.IntegerMemberValue;
+import javassist.bytecode.annotation.LongMemberValue;
+import javassist.bytecode.annotation.MemberValue;
+import javassist.bytecode.annotation.MemberValueVisitor;
+import javassist.bytecode.annotation.ShortMemberValue;
+import javassist.bytecode.annotation.StringMemberValue;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -33,18 +57,18 @@ import org.rhq.core.domain.auth.Subject;
/**
* The scripts can use simplified interfaces that omit the first "Subject" argument
- * to most methods. This helper class prepares such simplified interfaces.
+ * to most methods from RHQ's remote API. This helper class prepares such simplified interfaces.
*
* @author Greg Hinkle
* @author Lukas Krejci
*/
public class InterfaceSimplifier {
private static final Log LOG = LogFactory.getLog(InterfaceSimplifier.class);
-
+
private InterfaceSimplifier() {
-
+
}
-
+
public static Class<?> simplify(Class<?> intf) {
try {
ClassPool classPool = ClassPool.getDefault();
@@ -52,65 +76,125 @@ public class InterfaceSimplifier {
String simplifiedName = getSimplifiedName(intf);
LOG.debug("Simplifying " + intf + " (simplified interface name: " + simplifiedName + ")...");
+ CtClass cached = null;
try {
- @SuppressWarnings("unused")
- CtClass cached = classPool.get(simplifiedName);
+ cached = classPool.get(simplifiedName);
return Class.forName(simplifiedName, false, classPool.getClassLoader());
-
} catch (NotFoundException e) {
// ok... load it
} catch (ClassNotFoundException e) {
LOG.debug("Class [" + simplifiedName + "] not found - cause: " + e, e);
+ if (cached != null) {
+ // strange - we found the class definition in the class pool, which means we must have touched it
+ // before but Class.forName failed to find the class in the class pool's class loader.
+ return cached.toClass();
+ }
}
CtClass originalClass = classPool.get(intf.getName());
+ ClassFile originalClassFile = originalClass.getClassFile();
CtClass newClass = classPool.makeInterface(simplifiedName);
newClass.defrost();
+ ClassFile newClassFile = newClass.getClassFile();
+
+ //we'll be adding new constants to the class file (for generics and annotations)
+ ConstPool constPool = newClassFile.getConstPool();
+
+ //copy the annotations on the class
+ AnnotationsAttribute annotations = (AnnotationsAttribute) originalClassFile
+ .getAttribute(AnnotationsAttribute.visibleTag);
+ AnnotationsAttribute newAnnotations = copyAnnotations(annotations, constPool);
+ if (newAnnotations != null) {
+ newClassFile.addAttribute(newAnnotations);
+ }
+
+ //copy the generic signature of the class
+ SignatureAttribute signature = (SignatureAttribute) originalClassFile.getAttribute(SignatureAttribute.tag);
+ if (signature != null) {
+ newClassFile.addAttribute(new SignatureAttribute(constPool, signature.getSignature()));
+ }
+
+ //now copy over the methods
CtMethod[] methods = originalClass.getMethods();
for (CtMethod originalMethod : methods) {
+ //we are only simplifying interfaces here, but the CtClass.getMethods() also returns concrete methods
+ //inherited from Object. Let's just skip those - we don't need to worry about them...
+ if (!Modifier.isAbstract(originalMethod.getModifiers())) {
+ continue;
+ }
+
CtClass[] params = originalMethod.getParameterTypes();
- if (params.length > 0 && params[0].getName().equals(Subject.class.getName())) {
+ //capture all the runtime visible method annotations on the original method
+ annotations = (AnnotationsAttribute) originalMethod.getMethodInfo().getAttribute(
+ AnnotationsAttribute.visibleTag);
+
+ //capture all the runtime visible parameter annotations on the original method
+ ParameterAnnotationsAttribute parameterAnnotations = (ParameterAnnotationsAttribute) originalMethod
+ .getMethodInfo().getAttribute(ParameterAnnotationsAttribute.visibleTag);
+
+ //capture the generic signature of the original method.
+ signature = (SignatureAttribute) originalMethod.getMethodInfo().getAttribute(
+ SignatureAttribute.tag);
+
+ boolean simplify = params.length > 0 && params[0].getName().equals(Subject.class.getName());
+
+ if (simplify) {
+ //generate new params, leaving out the first parameter (the subject)
CtClass[] simpleParams = new CtClass[params.length - 1];
System.arraycopy(params, 1, simpleParams, 0, params.length - 1);
- newClass.defrost();
+ params = simpleParams;
+ }
- CtMethod newMethod = CtNewMethod.abstractMethod(originalMethod.getReturnType(), originalMethod
-.getName(), simpleParams, null, newClass);
+ //generate the new method with possibly modified parameters
+ CtMethod newMethod = CtNewMethod.abstractMethod(originalMethod.getReturnType(),
+ originalMethod.getName(), params, originalMethod.getExceptionTypes(), newClass);
- ParameterAnnotationsAttribute originalAnnotationsAttribute = (ParameterAnnotationsAttribute) originalMethod
- .getMethodInfo().getAttribute(ParameterAnnotationsAttribute.visibleTag);
+ //copy over the method annotations
+ annotations = copyAnnotations(annotations, constPool);
- // If there are any parameter annotations, copy the one's we're keeping
- if (originalAnnotationsAttribute != null) {
+ if (simplify) {
+ if (signature != null) {
+ //fun, we need to modify the signature, too, because we have left out the parameter
+ MethodSignature sig = MethodSignature.parse(signature.getSignature());
- javassist.bytecode.annotation.Annotation[][] originalAnnotations = originalAnnotationsAttribute
- .getAnnotations();
- javassist.bytecode.annotation.Annotation[][] newAnnotations = new javassist.bytecode.annotation.Annotation[originalAnnotations.length - 1][];
+ sig.paramTypes.remove(0);
- for (int i = 1; i < originalAnnotations.length; i++) {
- newAnnotations[i - 1] = new javassist.bytecode.annotation.Annotation[originalAnnotations[i].length];
- System.arraycopy(originalAnnotations[i], 0, newAnnotations[i - 1], 0,
- originalAnnotations[i].length);
- }
+ signature = new SignatureAttribute(constPool, sig.toString());
+ }
- ParameterAnnotationsAttribute newAnnotationsAttribute = new ParameterAnnotationsAttribute(
- newMethod.getMethodInfo().getConstPool(), ParameterAnnotationsAttribute.visibleTag);
+ //next, we need to copy the parameter annotations
+ parameterAnnotations = copyParameterAnnotations(parameterAnnotations, constPool, 1);
+ } else {
+ //just copy the sig and parameter annotations verbatim
+ if (signature != null) {
+ signature = new SignatureAttribute(constPool, signature.getSignature());
+ }
- newAnnotationsAttribute.setAnnotations(newAnnotations);
+ parameterAnnotations = copyParameterAnnotations(parameterAnnotations, constPool, 0);
+ }
- newMethod.getMethodInfo().addAttribute(newAnnotationsAttribute);
+ if (parameterAnnotations != null) {
+ newMethod.getMethodInfo().addAttribute(parameterAnnotations);
+ }
- }
+ if (signature != null) {
+ newMethod.getMethodInfo().addAttribute(signature);
+ }
- newClass.addMethod(newMethod);
+ if (annotations != null) {
+ newMethod.getMethodInfo().addAttribute(annotations);
}
+
+ //it is important to add the method directly to the classfile, not the class
+ //because otherwise the generics info wouldn't survive
+ newClassFile.addMethod(newMethod.getMethodInfo());
}
return newClass.toClass();
@@ -127,9 +211,266 @@ public class InterfaceSimplifier {
String fullName = interfaceClass.getName();
String simpleName = interfaceClass.getSimpleName();
Package pkg = interfaceClass.getPackage();
- String packageName = (pkg != null) ? pkg.getName() :
- fullName.substring(0, fullName.length() - (simpleName.length() + 1));
+ String packageName = (pkg != null) ? pkg.getName() : fullName.substring(0,
+ fullName.length() - (simpleName.length() + 1));
return packageName + ".wrapped." + simpleName + "Simple";
}
+ /**
+ * Copies the provided annotation into the provided const pool.
+ *
+ * @param annotation
+ * @param constPool
+ * @return
+ * @throws NotFoundException
+ */
+ private static Annotation cloneAnnotation(Annotation annotation, final ConstPool constPool)
+ throws NotFoundException {
+
+ Annotation ret = new Annotation(annotation.getTypeName(), constPool);
+
+ for (Object m : annotation.getMemberNames()) {
+ final String memberName = (String) m;
+
+ MemberValue origValue = annotation.getMemberValue(memberName);
+ final MemberValue[] newValue = new MemberValue[1];
+
+ origValue.accept(new ArrayIndexAssigningVisitor(newValue, 0, constPool));
+
+ ret.addMemberValue(memberName, newValue[0]);
+ }
+
+ return ret;
+ }
+
+ private static AnnotationsAttribute copyAnnotations(AnnotationsAttribute annotations, ConstPool constPool)
+ throws NotFoundException {
+ if (annotations != null) {
+ Annotation[] origAnnotations = annotations.getAnnotations();
+ Annotation[] newClassAnnotations = new Annotation[origAnnotations.length];
+ for (int i = 0; i < newClassAnnotations.length; ++i) {
+ newClassAnnotations[i] = cloneAnnotation(origAnnotations[i], constPool);
+ }
+
+ AnnotationsAttribute newAnnotations = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
+ newAnnotations.setAnnotations(newClassAnnotations);
+
+ return newAnnotations;
+ }
+
+ return null;
+ }
+
+ private static ParameterAnnotationsAttribute copyParameterAnnotations(
+ ParameterAnnotationsAttribute parameterAnnotations, ConstPool constPool, int fromIndex)
+ throws NotFoundException {
+
+ if (parameterAnnotations != null) {
+ Annotation[][] originalAnnotations = parameterAnnotations.getAnnotations();
+
+ //return early if there are no annotations to copy
+ if (originalAnnotations.length - fromIndex <= 0) {
+ return null;
+ }
+
+ Annotation[][] newParameterAnnotations = new Annotation[originalAnnotations.length - fromIndex][];
+
+ for (int i = fromIndex; i < originalAnnotations.length; i++) {
+ newParameterAnnotations[i - fromIndex] = new Annotation[originalAnnotations[i].length];
+ for (int j = 0; j < originalAnnotations[i].length; ++j) {
+ Annotation origAnnotation = originalAnnotations[i][j];
+
+ newParameterAnnotations[i - fromIndex][j] = cloneAnnotation(origAnnotation, constPool);
+ }
+ }
+
+ ParameterAnnotationsAttribute newAnnotationsAttribute = new ParameterAnnotationsAttribute(constPool,
+ ParameterAnnotationsAttribute.visibleTag);
+
+ newAnnotationsAttribute.setAnnotations(newParameterAnnotations);
+
+ return newAnnotationsAttribute;
+ }
+
+ return null;
+ }
+
+ private static class ArrayIndexAssigningVisitor implements MemberValueVisitor {
+ private MemberValue[] array;
+ private int index;
+ private ConstPool constPool;
+
+ public ArrayIndexAssigningVisitor(MemberValue[] array, int index, ConstPool constPool) {
+ this.array = array;
+ this.index = index;
+ this.constPool = constPool;
+ }
+
+ @Override
+ public void visitStringMemberValue(StringMemberValue node) {
+ array[index] = new StringMemberValue(node.getValue(), constPool);
+ }
+
+ @Override
+ public void visitShortMemberValue(ShortMemberValue node) {
+ array[index] = new ShortMemberValue(node.getValue(), constPool);
+ }
+
+ @Override
+ public void visitLongMemberValue(LongMemberValue node) {
+ array[index] = new LongMemberValue(node.getValue(), constPool);
+ }
+
+ @Override
+ public void visitIntegerMemberValue(IntegerMemberValue node) {
+ array[index] = new IntegerMemberValue(constPool, node.getValue());
+ }
+
+ @Override
+ public void visitFloatMemberValue(FloatMemberValue node) {
+ array[index] = new FloatMemberValue(node.getValue(), constPool);
+ }
+
+ @Override
+ public void visitEnumMemberValue(EnumMemberValue node) {
+ EnumMemberValue val = new EnumMemberValue(constPool);
+ val.setType(node.getType());
+ val.setValue(node.getValue());
+ array[index] = val;
+ }
+
+ @Override
+ public void visitDoubleMemberValue(DoubleMemberValue node) {
+ array[index] = new DoubleMemberValue(node.getValue(), constPool);
+ }
+
+ @Override
+ public void visitClassMemberValue(ClassMemberValue node) {
+ array[index] = new ClassMemberValue(node.getValue(), constPool);
+ }
+
+ @Override
+ public void visitCharMemberValue(CharMemberValue node) {
+ array[index] = new CharMemberValue(node.getValue(), constPool);
+ }
+
+ @Override
+ public void visitByteMemberValue(ByteMemberValue node) {
+ array[index] = new ByteMemberValue(node.getValue(), constPool);
+ }
+
+ @Override
+ public void visitBooleanMemberValue(BooleanMemberValue node) {
+ array[index] = new BooleanMemberValue(node.getValue(), constPool);
+ }
+
+ @Override
+ public void visitArrayMemberValue(ArrayMemberValue node) {
+ ArrayMemberValue val = new ArrayMemberValue(node.getType(), constPool);
+ MemberValue[] newVals = new MemberValue[node.getValue().length];
+ for (int i = 0; i < node.getValue().length; ++i) {
+ node.getValue()[i].accept(new ArrayIndexAssigningVisitor(newVals, i, constPool));
+ }
+
+ val.setValue(newVals);
+ array[index] = val;
+ }
+
+ @Override
+ public void visitAnnotationMemberValue(AnnotationMemberValue node) {
+ array[index] = new AnnotationMemberValue(node.getValue(), constPool);
+ }
+ }
+
+ //a quick and dirty method signature parser
+ //see http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.4
+ private static class MethodSignature {
+ public String returnType;
+ public List<String> paramTypes = new ArrayList<String>();
+ public String typeParameters;
+ public String exceptionTypes;
+
+ public static MethodSignature parse(String signature) {
+ int startParams = signature.indexOf('(') + 1;
+ int endParams = signature.indexOf(')');
+ int startExceptions = signature.indexOf('^');
+
+ MethodSignature sig = new MethodSignature();
+ sig.typeParameters = signature.substring(0, startParams - 1);
+ if (startExceptions == -1) {
+ sig.returnType = signature.substring(endParams + 1);
+ sig.exceptionTypes = "";
+ } else {
+ sig.returnType = signature.substring(endParams + 1, startExceptions);
+ sig.exceptionTypes = signature.substring(startExceptions);
+ }
+
+ int idx = startParams;
+ while (idx < endParams) {
+ int end = findEndOfTypeSignature(idx, signature);
+ sig.paramTypes.add(signature.substring(idx, end));
+ idx = end;
+ }
+
+ return sig;
+ }
+
+ private static int findEndOfTypeSignature(int idx, String signature) {
+ int c = signature.charAt(idx);
+
+ switch (c) {
+ case 'L':
+ return findEndOfClassSignature(idx, signature);
+ case '[':
+ return findEndOfTypeSignature(idx + 1, signature);
+ case 'T':
+ return signature.indexOf(';', idx + 1) + 1;
+ default:
+ return idx + 1;
+ }
+ }
+
+ private static int findEndOfClassSignature(int indexOfL, String signature) {
+ int idx = indexOfL + 1;
+
+ int genericDeclDepth = 0;
+
+ while (idx < signature.length()) {
+ boolean sigComplete = false;
+
+ char c = signature.charAt(idx++);
+ switch (c) {
+ case '<':
+ genericDeclDepth++;
+ break;
+ case '>':
+ genericDeclDepth--;
+ break;
+ case ';':
+ sigComplete = genericDeclDepth == 0;
+ break;
+ }
+
+ if (sigComplete) {
+ break;
+ }
+ }
+
+ return idx;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder bld = new StringBuilder(typeParameters);
+ bld.append("(");
+ for (String p : paramTypes) {
+ bld.append(p);
+ }
+ bld.append(")");
+ bld.append(returnType);
+ bld.append(exceptionTypes);
+
+ return bld.toString();
+ }
+ }
}
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java
new file mode 100644
index 0000000..4312153
--- /dev/null
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java
@@ -0,0 +1,317 @@
+/*
+ * 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.bindings.util;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.Arrays;
+import java.util.List;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+
+/**
+ * @author Lukas Krejci
+ */
+@Test
+public class InterfaceSimplifierTest {
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ ElementType.TYPE, ElementType.PARAMETER, ElementType.METHOD })
+ public static @interface MyAnnotation {
+ int value() default 1;
+
+ String parameter();
+ }
+
+ public static interface NoSimplifications {
+ void voidMethodWithNoExceptions();
+
+ void voidMethodWithExceptions() throws IOException, InterruptedException;
+
+ int intMethod();
+
+ Object objectMethod();
+
+ Object objectMethodWithParams(int p1, Object p2);
+
+ Object objectMethodWithParamsAndExceptions(int p1, Object p2) throws IOException, InterruptedException;
+ }
+
+ public static interface Simplifications {
+ void voidMethodWithNoExceptions(Subject s);
+
+ void voidMethodWithExceptions(Subject s) throws IOException, InterruptedException;
+
+ int intMethod(Subject s);
+
+ Object objectMethod(Subject s);
+
+ Object objectMethodWithParams(Subject s, int p1, Object p2);
+
+ Object objectMethodWithParamsAndExceptions(Subject s, int p1, Object p2) throws IOException,
+ InterruptedException;
+ }
+
+ public static interface Generics<C extends Type> {
+ void genericParameters(List<String> p, int p2);
+
+ <T extends Type> T typeParameters(T p, int p2);
+
+ <T extends Type> T typeParametersSimplified(Subject s, T p, int p2);
+
+ <T extends C> T classTypeParameters(T p, int p2);
+ }
+
+
+ @MyAnnotation(parameter = "CLASS")
+ public static interface Annotations {
+
+ @MyAnnotation(value = 2, parameter = "a")
+ int method(@MyAnnotation(parameter = "b") int p) throws IOException;
+
+ @MyAnnotation(value = 2, parameter = "c")
+ int methodSimplified(@MyAnnotation(parameter = "disappear") Subject s, @MyAnnotation(parameter = "d") int p)
+ throws IOException;
+ }
+
+ public void testNoSimplifications() throws Exception {
+ Class<?> iface = InterfaceSimplifier.simplify(NoSimplifications.class);
+
+ Method voidMethodWithNoExceptions = iface.getMethod("voidMethodWithNoExceptions");
+ Assert.assertEquals(voidMethodWithNoExceptions.getReturnType(), void.class);
+
+ Method voidMethodWithExceptions = iface.getMethod("voidMethodWithExceptions");
+ List<Class<?>> exceptions = Arrays.asList(voidMethodWithExceptions.getExceptionTypes());
+ Assert.assertTrue(exceptions.contains(IOException.class),
+ "The 'voidMethodWithExceptions doesn't seem to declare throws IOException");
+ Assert.assertTrue(exceptions.contains(InterruptedException.class),
+ "The 'voidMethodWithExceptions doesn't seem to declare throws InterruptedException");
+
+ Method intMethod = iface.getMethod("intMethod");
+ Assert.assertEquals(intMethod.getReturnType(), int.class);
+
+ Method objectMethod = iface.getMethod("objectMethod");
+ Assert.assertEquals(objectMethod.getReturnType(), Object.class);
+
+ Method objectMethodWithParams = iface.getMethod("objectMethodWithParams", int.class, Object.class);
+ Assert.assertEquals(objectMethodWithParams.getReturnType(), Object.class);
+
+ Method objectMethodWithParamsAndExceptions = iface.getMethod("objectMethodWithParamsAndExceptions", int.class,
+ Object.class);
+ Assert.assertEquals(objectMethodWithParamsAndExceptions.getReturnType(), Object.class);
+ exceptions = Arrays.asList(objectMethodWithParamsAndExceptions.getExceptionTypes());
+ Assert.assertTrue(exceptions.contains(IOException.class),
+ "The 'objectMethodWithParamsAndExceptions doesn't seem to declare throws IOException");
+ Assert.assertTrue(exceptions.contains(InterruptedException.class),
+ "The 'objectMethodWithParamsAndExceptions doesn't seem to declare throws InterruptedException");
+ }
+
+ public void testSimplifications() throws Exception {
+ Class<?> iface = InterfaceSimplifier.simplify(Simplifications.class);
+
+ //These tests are exactly the same as for the NoSimplifications class, because
+ //the simplifier should leave out all the subject parameters in the Simplifications
+ //class' methods.
+
+ Method voidMethodWithNoExceptions = iface.getMethod("voidMethodWithNoExceptions");
+ Assert.assertEquals(voidMethodWithNoExceptions.getReturnType(), void.class);
+
+ Method voidMethodWithExceptions = iface.getMethod("voidMethodWithExceptions");
+ List<Class<?>> exceptions = Arrays.asList(voidMethodWithExceptions.getExceptionTypes());
+ Assert.assertTrue(exceptions.contains(IOException.class),
+ "The 'voidMethodWithExceptions doesn't seem to declare throws IOException");
+ Assert.assertTrue(exceptions.contains(InterruptedException.class),
+ "The 'voidMethodWithExceptions doesn't seem to declare throws InterruptedException");
+
+ Method intMethod = iface.getMethod("intMethod");
+ Assert.assertEquals(intMethod.getReturnType(), int.class);
+
+ Method objectMethod = iface.getMethod("objectMethod");
+ Assert.assertEquals(objectMethod.getReturnType(), Object.class);
+
+ Method objectMethodWithParams = iface.getMethod("objectMethodWithParams", int.class, Object.class);
+ Assert.assertEquals(objectMethodWithParams.getReturnType(), Object.class);
+
+ Method objectMethodWithParamsAndExceptions = iface.getMethod("objectMethodWithParamsAndExceptions", int.class,
+ Object.class);
+ Assert.assertEquals(objectMethodWithParamsAndExceptions.getReturnType(), Object.class);
+ exceptions = Arrays.asList(objectMethodWithParamsAndExceptions.getExceptionTypes());
+ Assert.assertTrue(exceptions.contains(IOException.class),
+ "The 'objectMethodWithParamsAndExceptions doesn't seem to declare throws IOException");
+ Assert.assertTrue(exceptions.contains(InterruptedException.class),
+ "The 'objectMethodWithParamsAndExceptions doesn't seem to declare throws InterruptedException");
+ }
+
+ public <T> void testGenerics() throws Exception {
+ @SuppressWarnings("unchecked")
+ Class<T> iface = (Class<T>) InterfaceSimplifier.simplify(Generics.class);
+
+ TypeVariable<Class<T>>[] classTypeParameters = iface.getTypeParameters();
+ Assert.assertEquals(classTypeParameters.length, 1, "There should be 1 type parameter on the class Generics.");
+ TypeVariable<?> typeVariable = classTypeParameters[0];
+ Assert.assertEquals(typeVariable.getName(), "C", "Unexpected type parameter name on 'Generics' class.");
+ Type[] bounds = typeVariable.getBounds();
+ Assert.assertEquals(bounds.length, 1, "The type parameter on the class 'Generics' should have 1 upper bound.");
+ Assert.assertEquals(bounds[0], Type.class,
+ "The type parameter on the class 'Generics' should have the upper bound of the Type class.");
+
+ Method genericParameters = iface.getMethod("genericParameters", List.class, int.class);
+ Assert.assertEquals(genericParameters.getReturnType(), void.class);
+
+ Type firstParamType = genericParameters.getGenericParameterTypes()[0];
+ Assert.assertTrue(firstParamType instanceof ParameterizedType,
+ "The first parameter of the 'genericParameters' should be parameterized.");
+ Assert.assertEquals(((ParameterizedType) firstParamType).getRawType(), List.class,
+ "The first parameter of the 'genericParameters' method should be a List.");
+ Assert.assertEquals(((ParameterizedType) firstParamType).getActualTypeArguments()[0], String.class,
+ "The first parameter of the 'genericParamters' method should be a List<String>");
+
+ Method typeParameters = iface.getMethod("typeParameters", Type.class, int.class);
+ Assert.assertEquals(typeParameters.getReturnType(), Type.class);
+
+ TypeVariable<Method>[] typeVariables = typeParameters.getTypeParameters();
+ Assert.assertEquals(typeVariables.length, 1,
+ "There should be 1 type parameter on the the 'typeParameters' method.");
+ typeVariable = typeVariables[0];
+ Assert.assertEquals(typeVariable.getName(), "T", "Unexpected type parameter name on 'typeParameters' method.");
+ bounds = typeVariable.getBounds();
+ Assert.assertEquals(bounds.length, 1, "The type parameter on the method 'typeParameters' should have 1 upper bound.");
+ Assert.assertEquals(bounds[0], Type.class,
+ "The type parameter on the method 'typeParameters' should have the upper bound of the Type class.");
+
+ Type returnType = typeParameters.getGenericReturnType();
+ Assert.assertTrue(returnType instanceof TypeVariable,
+ "The generic return type of the 'typeParameters' class should be a type variable.");
+ typeVariable = (TypeVariable<?>) returnType;
+ Assert.assertEquals(typeVariable.getName(), "T",
+ "Unexpected type parameter at the return type of the 'typeParameters' method.");
+
+ Method typeParametersSimplified = iface.getMethod("typeParametersSimplified", Type.class, int.class);
+ Assert.assertEquals(typeParameters.getReturnType(), Type.class);
+
+ typeVariables = typeParametersSimplified.getTypeParameters();
+ Assert.assertEquals(typeVariables.length, 1,
+ "There should be 1 type parameter on the the 'typeParametersSimplified' method.");
+ typeVariable = typeVariables[0];
+ Assert.assertEquals(typeVariable.getName(), "T",
+ "Unexpected type parameter name on 'typeParametersSimplified' method.");
+ bounds = typeVariable.getBounds();
+ Assert.assertEquals(bounds.length, 1,
+ "The type parameter on the method 'typeParametersSimplified' should have 1 upper bound.");
+ Assert
+ .assertEquals(bounds[0], Type.class,
+ "The type parameter on the method 'typeParametersSimplified' should have the upper bound of the Type class.");
+
+ returnType = typeParametersSimplified.getGenericReturnType();
+ Assert.assertTrue(returnType instanceof TypeVariable,
+ "The generic return type of the 'typeParametersSimplified' class should be a type variable.");
+ typeVariable = (TypeVariable<?>) returnType;
+ Assert.assertEquals(typeVariable.getName(), "T",
+ "Unexpected type parameter at the return type of the 'typeParametersSimplified' method.");
+ }
+
+ public void testAnnotations() throws Exception {
+ Class<?> iface = InterfaceSimplifier.simplify(Annotations.class);
+
+ Annotation[] annotations = iface.getAnnotations();
+ Assert.assertEquals(annotations.length, 1, "UNexpected number of annotations on the 'Annotations' class.");
+ Annotation annotation = annotations[0];
+ Assert.assertEquals(annotation.annotationType(), MyAnnotation.class,
+ "Unexpected annotation type on the class 'Annotations");
+ Assert.assertEquals(((MyAnnotation) annotation).value(), 1,
+ "Unexpected value of the 'value' attribute on the annotation on the 'Annotations' class.");
+ Assert.assertEquals(((MyAnnotation) annotation).parameter(), "CLASS",
+ "Unexpected value of the 'parameter' attribute on the annotation on the 'Annotations' class.");
+
+ Method method = iface.getMethod("method", int.class);
+ annotations = method.getAnnotations();
+ Assert.assertEquals(annotations.length, 1, "Unexpected number of annotations on the 'method' method.");
+
+ annotation = annotations[0];
+ Assert.assertEquals(annotation.annotationType(), MyAnnotation.class,
+ "Unexpected annotation type on the method 'method");
+
+ Assert.assertEquals(((MyAnnotation) annotation).value(), 2,
+ "Unexpected value of the 'value' attribute on the annotation on the 'method' method.");
+ Assert.assertEquals(((MyAnnotation) annotation).parameter(), "a",
+ "Unexpected value of the 'parameter' attribute on the annotation on the 'method' method.");
+
+ Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+
+ Assert
+ .assertEquals(parameterAnnotations.length, 1,
+ "Method 'Annotations.method(int)' has 1 parameter with annotations but we got a different number of parameters.");
+
+ Assert.assertEquals(parameterAnnotations[0].length, 1,
+ "The parameter of 'Annotations.method(int)' method has an annotation but we couldn't detect any.");
+
+ annotation = parameterAnnotations[0][0];
+ Assert.assertEquals(annotation.annotationType(), MyAnnotation.class,
+ "Unexpected annotation type on the parameter 'p' of 'Annotations.method(int)'");
+ Assert.assertEquals(((MyAnnotation) annotation).value(), 1,
+ "Unexpected value of the 'value' of the annotation on the parameter p of 'Annotations.method(int)'.");
+ Assert.assertEquals(((MyAnnotation) annotation).parameter(), "b",
+ "Unexpected value of the 'parameter' of the annotation on the parameter p of 'Annotations.method(int)'.");
+
+ method = iface.getMethod("methodSimplified", int.class);
+ annotations = method.getAnnotations();
+ Assert
+ .assertEquals(annotations.length, 1, "Unexpected number of annotations on the 'methodSimplified' method.");
+
+ annotation = annotations[0];
+ Assert.assertEquals(annotation.annotationType(), MyAnnotation.class,
+ "Unexpected annotation type on the method 'methodSimplified");
+
+ Assert.assertEquals(((MyAnnotation) annotation).value(), 2,
+ "Unexpected value of the 'value' attribute on the annotation on the 'methodSimplified' method.");
+ Assert.assertEquals(((MyAnnotation) annotation).parameter(), "c",
+ "Unexpected value of the 'parameter' attribute on the annotation on the 'methodSimplified' method.");
+
+ parameterAnnotations = method.getParameterAnnotations();
+
+ Assert
+ .assertEquals(parameterAnnotations.length, 1,
+ "Method 'Annotations.methodSimplified(int)' has 1 parameter with annotations but we got a different number of parameters.");
+
+ Assert.assertEquals(parameterAnnotations[0].length, 1,
+ "The parameter of 'Annotations.methodSimplified(int)' method has an annotation but we couldn't detect any.");
+
+ annotation = parameterAnnotations[0][0];
+ Assert.assertEquals(annotation.annotationType(), MyAnnotation.class,
+ "Unexpected annotation type on the parameter 'p' of 'Annotations.methodSimplified(int)'");
+ Assert.assertEquals(((MyAnnotation) annotation).value(), 1,
+ "Unexpected value of the 'value' of the annotation on the parameter p of 'Annotations.methodSimplified(int)'.");
+ Assert
+ .assertEquals(((MyAnnotation) annotation).parameter(), "d",
+ "Unexpected value of the 'parameter' of the annotation on the parameter p of 'Annotations.methodSimplified(int)'.");
+ }
+}
commit b48676a8552e723f2fce366b00d438dbf2484693
Merge: 5e823b9 00c0ee0
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Jun 29 17:48:02 2012 -0400
Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq.git
commit 5e823b969b8cc830432cfc2e055ed3292464c4d8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Jun 29 17:47:26 2012 -0400
[BZ 834019] enhancement to the arquillian stuff so we can have code that can templatize reusable plugin descriptors. this also has a reusable discovery component. This includes LateMeasurementRescheduleTest that will hopefully, eventually test this BZ but the actual test method is essentially a stub right now
diff --git a/modules/core/arquillian-integration/archive/pom.xml b/modules/core/arquillian-integration/archive/pom.xml
index f92cc5e..edf6add 100644
--- a/modules/core/arquillian-integration/archive/pom.xml
+++ b/modules/core/arquillian-integration/archive/pom.xml
@@ -25,6 +25,12 @@
<dependency>
<groupId>org.rhq</groupId>
+ <artifactId>rhq-core-util</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
<artifactId>rhq-core-client-api</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginArchiveImpl.java b/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginArchiveImpl.java
index ed19397..3d31785 100644
--- a/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginArchiveImpl.java
+++ b/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginArchiveImpl.java
@@ -3,7 +3,9 @@
*/
package org.rhq.test.shrinkwrap;
+import java.io.ByteArrayInputStream;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
@@ -41,6 +43,7 @@ import org.jboss.shrinkwrap.impl.base.container.ContainerBase;
import org.jboss.shrinkwrap.impl.base.path.BasicPath;
import org.rhq.core.clientapi.agent.metadata.PluginDependencyGraph;
+import org.rhq.core.util.stream.StreamUtil;
/**
* @author Lukas Krejci
@@ -122,6 +125,31 @@ public class RhqAgentPluginArchiveImpl extends ContainerBase<RhqAgentPluginArchi
}
@Override
+ public RhqAgentPluginArchive setPluginDescriptorFromTemplate(String resourceName,
+ Map<String, String> replacementValues) throws IllegalArgumentException {
+
+ Validate.notNull(resourceName, "resourceName should be specified");
+ Validate.notNull(replacementValues, "replacementValues should be specified");
+
+ // get the template text and replace all tokens with their replacement values
+ String templateXml = new String(StreamUtil.slurp(new ClassLoaderAsset(resourceName).openStream()));
+ for (Map.Entry<String, String> entry : replacementValues.entrySet()) {
+ templateXml = templateXml.replace(entry.getKey(), entry.getValue());
+ }
+
+ // Make a new descriptor file with the new template content (with variables replaced) in a tmp directory.
+ File newDescriptorFile;
+ try {
+ newDescriptorFile = File.createTempFile(resourceName.replace(".xml", ""), ".xml");
+ StreamUtil.copy(new ByteArrayInputStream(templateXml.getBytes()), new FileOutputStream(newDescriptorFile));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ return setPluginDescriptor(newDescriptorFile);
+ }
+
+ @Override
public RhqAgentPluginArchive setPluginDescriptor(String resourceName) throws IllegalArgumentException {
Validate.notNull(resourceName, "ResourceName should be specified");
return setPluginDescriptor(new ClassLoaderAsset(resourceName));
diff --git a/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginDescriptorContainer.java b/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginDescriptorContainer.java
index 309b341..ff5bdf1 100644
--- a/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginDescriptorContainer.java
+++ b/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginDescriptorContainer.java
@@ -7,6 +7,7 @@ import java.io.File;
import java.net.URL;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ArchivePath;
@@ -36,6 +37,21 @@ public interface RhqAgentPluginDescriptorContainer<T extends Archive<T>> {
ArchivePath getRequiredPluginsPath();
/**
+ * Sets the plugin descriptor using the plugin descriptor template resource, making
+ * a copy of that resource and replacing templatized variables in that file with
+ * replacement values that are passed into this method.
+ * The {@link ClassLoader} is used to obtain the plugin descriptor template resource, but
+ * it is assumed to be a file on the file system.
+ *
+ * @param resourceName the name of the plugin descriptor template resource as accessible by the class loader
+ * @param replacementValues map with keys of template replacement variable names with their replacement values
+ * @return the archive itself
+ * @throws IllegalArgumentException if resourceName or replacementValues is null
+ */
+ T setPluginDescriptorFromTemplate(String resourceName, Map<String, String> replacementValues)
+ throws IllegalArgumentException;
+
+ /**
* Sets the plugin descriptor using the resource name. The {@link ClassLoader} is
* used to obtain the resource.
*
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java
new file mode 100644
index 0000000..518d5da
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java
@@ -0,0 +1,105 @@
+package org.rhq.core.pc.measurement;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.TargetsContainer;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.arquillian.testng.Arquillian;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+
+import org.rhq.core.clientapi.server.discovery.InventoryReport;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.pc.PluginContainer;
+import org.rhq.core.pc.inventory.ResourceContainer;
+import org.rhq.plugins.test.SingleResourceDiscoveryComponent;
+import org.rhq.plugins.test.measurement.BZ834019ResourceComponent;
+import org.rhq.test.arquillian.AfterDiscovery;
+import org.rhq.test.arquillian.BeforeDiscovery;
+import org.rhq.test.arquillian.FakeServerInventory;
+import org.rhq.test.arquillian.MockingServerServices;
+import org.rhq.test.arquillian.ResourceComponentInstances;
+import org.rhq.test.arquillian.ResourceContainers;
+import org.rhq.test.arquillian.RunDiscovery;
+import org.rhq.test.shrinkwrap.RhqAgentPluginArchive;
+
+/**
+ * Test for BZ 834019.
+ */
+@RunDiscovery
+public class LateMeasurementRescheduleTest extends Arquillian {
+
+ @Deployment(name = "SingleMetricPlugin")
+ @TargetsContainer("connected-pc-with-metric-collection")
+ public static RhqAgentPluginArchive getTestPlugin() {
+ RhqAgentPluginArchive pluginJar = ShrinkWrap
+ .create(RhqAgentPluginArchive.class, "single-metric-plugin-1.0.jar");
+ HashMap<String, String> replacements = new HashMap<String, String>();
+ replacements.put("@@@discovery@@@", SingleResourceDiscoveryComponent.class.getName());
+ replacements.put("@@@class@@@", BZ834019ResourceComponent.class.getName());
+ return pluginJar.setPluginDescriptorFromTemplate("single-metric-rhq-plugin.xml", replacements).addClasses(
+ SingleResourceDiscoveryComponent.class, BZ834019ResourceComponent.class);
+ }
+
+ @ArquillianResource
+ private PluginContainer pluginContainer;
+
+ @ArquillianResource
+ public MockingServerServices serverServices;
+
+ private FakeServerInventory fakeServerInventory;
+ private FakeServerInventory.CompleteDiscoveryChecker discoveryCompleteChecker;
+
+ @ResourceContainers(plugin = "SingleMetricPlugin", resourceType = "SingleMetricServer")
+ private Set<ResourceContainer> containers;
+
+ @ResourceComponentInstances(plugin = "SingleMetricPlugin", resourceType = "SingleMetricServer")
+ private Set<BZ834019ResourceComponent> components;
+
+ @BeforeDiscovery(testMethods = "testBZ834019")
+ public void resetServerServices() throws Exception {
+ serverServices.resetMocks();
+ fakeServerInventory = new FakeServerInventory();
+ discoveryCompleteChecker = fakeServerInventory.createAsyncDiscoveryCompletionChecker(1);
+
+ // autoimport everything
+ when(serverServices.getDiscoveryServerService().mergeInventoryReport(any(InventoryReport.class))).then(
+ fakeServerInventory.mergeInventoryReport(InventoryStatus.COMMITTED));
+
+ // set up the metric schedules using the metric metadata to determine default intervals and enablement
+ when(serverServices.getDiscoveryServerService().postProcessNewlyCommittedResources(any(Set.class))).then(
+ fakeServerInventory.postProcessNewlyCommittedResources());
+ }
+
+ @AfterDiscovery
+ public void waitForAsyncDiscoveries() throws Exception {
+ if (discoveryCompleteChecker != null) {
+ discoveryCompleteChecker.waitForDiscoveryComplete(10000);
+ }
+ }
+
+ @Test(groups = "pc.itest.bz834019", priority = 20)
+ public void testBZ834019() throws Exception {
+ Assert.assertNotNull(pluginContainer);
+ Assert.assertTrue(pluginContainer.isStarted());
+
+ // make sure we have the resource container
+ Assert.assertEquals(containers.size(), 1, "missing container");
+
+ // make sure we have the resource component
+ Assert.assertEquals(components.size(), 1, "missing component");
+
+ assert containers.iterator().next().getResource().getInventoryStatus() == InventoryStatus.COMMITTED;
+
+ BZ834019ResourceComponent server = this.components.iterator().next();
+
+ // TODO do things to test BZ 834019
+ }
+}
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
index 8435114..d94e32f 100644
--- a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
@@ -19,7 +19,7 @@ import org.rhq.core.clientapi.server.discovery.InventoryReport;
import org.rhq.core.domain.resource.InventoryStatus;
import org.rhq.core.pc.PluginContainer;
import org.rhq.core.pc.inventory.ResourceContainer;
-import org.rhq.plugins.test.measurement.BZ821058DiscoveryComponent;
+import org.rhq.plugins.test.SingleResourceDiscoveryComponent;
import org.rhq.plugins.test.measurement.BZ821058ResourceComponent;
import org.rhq.test.arquillian.AfterDiscovery;
import org.rhq.test.arquillian.BeforeDiscovery;
@@ -40,8 +40,8 @@ public class ReadOnlyScheduleSetTest extends Arquillian {
@TargetsContainer("connected-pc-with-metric-collection")
public static RhqAgentPluginArchive getTestPlugin() {
RhqAgentPluginArchive pluginJar = ShrinkWrap.create(RhqAgentPluginArchive.class, "bz821058-plugin-1.0.jar");
- return pluginJar.setPluginDescriptor("bz821058-rhq-plugin.xml").addClasses(BZ821058DiscoveryComponent.class,
- BZ821058ResourceComponent.class);
+ return pluginJar.setPluginDescriptor("bz821058-rhq-plugin.xml").addClasses(
+ SingleResourceDiscoveryComponent.class, BZ821058ResourceComponent.class);
}
@ArquillianResource
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/SingleResourceDiscoveryComponent.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/SingleResourceDiscoveryComponent.java
new file mode 100644
index 0000000..fde1f91
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/SingleResourceDiscoveryComponent.java
@@ -0,0 +1,30 @@
+package org.rhq.plugins.test;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+
+public class SingleResourceDiscoveryComponent implements ResourceDiscoveryComponent<ResourceComponent<?>> {
+ @Override
+ public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<ResourceComponent<?>> context)
+ throws InvalidPluginConfigurationException, Exception {
+
+ HashSet<DiscoveredResourceDetails> details = new HashSet<DiscoveredResourceDetails>(1);
+ ResourceType rt = context.getResourceType();
+ String key = "SingleResourceKey";
+ String name = "SingleResourceName";
+ String version = "1";
+ Configuration pc = context.getDefaultPluginConfiguration();
+ DiscoveredResourceDetails resource = new DiscoveredResourceDetails(rt, key, name, version, null, pc, null);
+ details.add(resource);
+
+ return details;
+ }
+}
\ No newline at end of file
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ821058DiscoveryComponent.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ821058DiscoveryComponent.java
deleted file mode 100644
index b9f49a4..0000000
--- a/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ821058DiscoveryComponent.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.plugins.test.measurement;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.resource.ResourceType;
-import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
-import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
-import org.rhq.core.pluginapi.inventory.ResourceComponent;
-import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
-import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
-
-public class BZ821058DiscoveryComponent implements ResourceDiscoveryComponent<ResourceComponent<?>> {
-
- @Override
- public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<ResourceComponent<?>> context)
- throws InvalidPluginConfigurationException, Exception {
-
- HashSet<DiscoveredResourceDetails> details = new HashSet<DiscoveredResourceDetails>(1);
- ResourceType rt = context.getResourceType();
- String key = "bz821058";
- String name = "bz821058";
- String version = "1";
- Configuration pc = context.getDefaultPluginConfiguration();
- DiscoveredResourceDetails resource = new DiscoveredResourceDetails(rt, key, name, version, null, pc, null);
- details.add(resource);
-
- return details;
- }
-
-}
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java
new file mode 100644
index 0000000..6a3a93d
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java
@@ -0,0 +1,38 @@
+package org.rhq.plugins.test.measurement;
+
+import java.util.Iterator;
+import java.util.Set;
+
+import org.rhq.core.domain.measurement.AvailabilityType;
+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.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+
+public class BZ834019ResourceComponent implements ResourceComponent<ResourceComponent<?>>, MeasurementFacet {
+
+ @Override
+ public AvailabilityType getAvailability() {
+ return AvailabilityType.UP;
+ }
+
+ @Override
+ public void start(ResourceContext<ResourceComponent<?>> context) throws Exception {
+ }
+
+ @Override
+ public void stop() {
+ }
+
+ @Override
+ public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
+ // TODO: do things to test BZ 834019
+ for (Iterator<MeasurementScheduleRequest> i = metrics.iterator(); i.hasNext();) {
+ MeasurementScheduleRequest metric = i.next();
+ report.addData(new MeasurementDataNumeric(metric, new Double(1.0)));
+ }
+ return;
+ }
+}
\ No newline at end of file
diff --git a/modules/core/plugin-container-itest/src/test/resources/arquillian.xml b/modules/core/plugin-container-itest/src/test/resources/arquillian.xml
index 92968b2..964e07e 100644
--- a/modules/core/plugin-container-itest/src/test/resources/arquillian.xml
+++ b/modules/core/plugin-container-itest/src/test/resources/arquillian.xml
@@ -10,6 +10,7 @@
<property name="insideAgent">true</property>
<property name="startManagementBean">false</property>
<property name="measurementCollectionInitialDelay">10</property> <!-- start collecting metrics after 10s -->
+ <property name="measurementCollectionThreadPoolSize">1</property> <!-- make testing easier by only having one thread collect -->
</configuration>
</container>
diff --git a/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml b/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml
index 730a656..c6adda6 100644
--- a/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml
+++ b/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml
@@ -3,15 +3,14 @@
<plugin name="bz821058Plugin"
displayName="Plugin to test BZ 821058"
description="This will help test that measurement facet is given a read-only schedule set."
- package="org.rhq.plugins.test.measurement"
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="BZ821058Server"
- discovery="BZ821058DiscoveryComponent"
- class="BZ821058ResourceComponent">
+ discovery="org.rhq.plugins.test.SingleResourceDiscoveryComponent"
+ class="org.rhq.plugins.test.measurement.BZ821058ResourceComponent">
<metric property="metric1"
dataType="measurement"
diff --git a/modules/core/plugin-container-itest/src/test/resources/single-metric-rhq-plugin.xml b/modules/core/plugin-container-itest/src/test/resources/single-metric-rhq-plugin.xml
new file mode 100644
index 0000000..d67fafd
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/resources/single-metric-rhq-plugin.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<plugin name="SingleMetricPlugin"
+ displayName="Plugin that has a single server with a single enabled metric."
+ description="This will help test measurement collections by providing a server with an enabled metric."
+ 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="SingleMetricServer"
+ discovery="@@@discovery@@@"
+ class="@@@class@@@">
+ <metric property="metric1"
+ dataType="measurement"
+ defaultOn="true"
+ displayType="summary"
+ defaultInterval="30000" />
+ </server>
+</plugin>
+
commit cd6c2fa4ce4f128f80145438499dbfc1223fac42
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Jun 29 17:45:46 2012 -0400
[BZ 834019] the actual code fix to push out the new rescheduled metric - will later be checking in test code to help test this
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java
index ac13b06..e9303b4 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java
@@ -88,7 +88,7 @@ public class MeasurementCollectorRunner implements Callable<MeasurementReport>,
}
}
- this.measurementManager.reschedule(requests);
+ this.measurementManager.reschedule(requests, 31000L); // BZ 834019 - go to the next collection interval plus 31s to skew it
return report;
}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java
index dc7d0ca..33895aa 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java
@@ -526,11 +526,31 @@ public class MeasurementManager extends AgentService implements MeasurementAgent
return nextScheduledSet;
}
+ /**
+ * Reschedules the given measurement schedules so the next collection occurs in the future.
+ * The next collection will be pushed out by the number of seconds of the schedule's collection
+ * interval.
+ *
+ * @param scheduledMeasurementInfos the schedules to reschedule
+ */
public synchronized void reschedule(Set<ScheduledMeasurementInfo> scheduledMeasurementInfos) {
+ reschedule(scheduledMeasurementInfos, 0);
+ }
+
+ /**
+ * Reschedules the given measurement schedules so the next collection occurs in the future.
+ * The next collection will be pushed out by the number of seconds of the schedule's collection
+ * interval plus (or minus) the given adjustment (which is provided in milliseconds).
+ *
+ * @param scheduledMeasurementInfos the schedules to reschedule
+ * @param adjustment the number of milliseconds to adjust the next collection time. If 0, the
+ * next collection time will be the number of seconds in the future as indicated
+ * by the schedule's interval.
+ */
+ public synchronized void reschedule(Set<ScheduledMeasurementInfo> scheduledMeasurementInfos, long adjustment) {
for (ScheduledMeasurementInfo scheduledMeasurement : scheduledMeasurementInfos) {
- // Iterate to next collection time
scheduledMeasurement.setNextCollection(scheduledMeasurement.getNextCollection()
- + scheduledMeasurement.getInterval());
+ + scheduledMeasurement.getInterval() + adjustment);
this.scheduledRequests.offer(scheduledMeasurement);
}
}
commit 00c0ee04c4f78b893cbd2b727c587ae76d1cc2f0
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Fri Jun 29 17:35:18 2012 -0400
i)fix problem in resource key ii)up the discovery lag for loadUpdateTemplatedResourceConfiguration to try to fix invalid resource ids
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java
index 05ca0eb..7be0689 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java
@@ -491,7 +491,7 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
ResourceType hostControllerType = new ResourceType("JBossAS7 Host Controller", PLUGIN_NAME,
ResourceCategory.SERVER, null);
Resource hostController = getResourceByTypeAndKey(platform, hostControllerType,
- "/tmp/jboss-as-6.0.0.GA/domain");
+ "/tmp/jboss-as-6.0.0/domain");
//profile=full-ha
ResourceType profileType = new ResourceType("Profile", PLUGIN_NAME, ResourceCategory.SERVICE, null);
String key = PROFILE;
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java
index fe05def..908faff 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java
@@ -58,7 +58,7 @@ public class TemplatedResourcesTest extends AbstractJBossAS7PluginTest {
assertNotNull(platform);
assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
- Thread.sleep(20 * 1000L);
+ Thread.sleep(40 * 1000L);
}
@Test(priority = 11)
commit 7281ff782f83461ae81560adf82b83d3e08bf1db
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Fri Jun 29 11:14:18 2012 -0400
-moved domain test into domain group and package
-added longer sleep to TemplatedResource test to attempt to fix test run failures.
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java
new file mode 100644
index 0000000..05ca0eb
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java
@@ -0,0 +1,675 @@
+/*
+ * 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.modules.plugins.jbossas7.itest.domain;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Set;
+
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.JsonProcessingException;
+import org.codehaus.jackson.map.DeserializationConfig;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.testng.annotations.Test;
+
+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.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.Property;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.resource.CreateResourceStatus;
+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.ResourceType;
+import org.rhq.core.pc.configuration.ConfigurationManager;
+import org.rhq.core.pc.inventory.InventoryManager;
+import org.rhq.modules.plugins.jbossas7.ASConnection;
+import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent;
+import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent.Value;
+import org.rhq.modules.plugins.jbossas7.itest.AbstractJBossAS7PluginTest;
+import org.rhq.modules.plugins.jbossas7.itest.standalone.StandaloneServerComponentTest;
+import org.rhq.modules.plugins.jbossas7.json.Address;
+import org.rhq.modules.plugins.jbossas7.json.Operation;
+import org.rhq.modules.plugins.jbossas7.json.Result;
+import org.rhq.test.arquillian.RunDiscovery;
+
+/**
+ * Test exercising the subsystem=security/SecurityDomain/[Authentication(Classic|Jaspi),
+ * Authorization, Mapping, Audit, Acl,
+ * Identity-Trust]
+ * @author Simeon Pinder
+ */
+@Test(groups = { "integration", "pc", "domain" }, singleThreaded = true)
+public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
+
+ private static ASConnection con = null;
+ private static ObjectMapper mapper = null;
+
+ private static String TEST_DOMAIN = "testDomain";
+ private static String SECURITY_RESOURCE_TYPE = "Security";
+ private static String SECURITY_RESOURCE_KEY = "subsystem=security";
+ private static String SECURITY_DOMAIN_RESOURCE_KEY = "security-domain";
+ private static String PROFILE = "profile=full-ha";
+ private static String SECURITY_DOMAIN_RESOURCE_TYPE = "Security Domain";
+ private static String AUTH_CLASSIC_RESOURCE_TYPE = "Authentication (Classic)";
+ private static String AUTH_CLASSIC_RESOURCE_KEY = "authentication=classic";
+
+ private static Resource securityResource = null;
+
+ protected static String DC_HOST = System.getProperty("jboss.domain.bindAddress");
+ protected static int DC_HTTP_PORT = Integer.valueOf(System.getProperty("jboss.domain.httpManagementPort"));
+ protected static String DC_USER = AbstractJBossAS7PluginTest.MANAGEMENT_USERNAME;
+ protected static String DC_PASS = AbstractJBossAS7PluginTest.MANAGEMENT_PASSWORD;
+
+ ASConnection getASConnection() {
+ ASConnection connection = new ASConnection(DC_HOST, DC_HTTP_PORT, DC_USER, DC_PASS);
+ return connection;
+ }
+
+ public static final ResourceType RESOURCE_TYPE = new ResourceType(SECURITY_RESOURCE_TYPE, PLUGIN_NAME,
+ ResourceCategory.SERVICE, null);
+ private static final String RESOURCE_KEY = SECURITY_RESOURCE_KEY;
+ private static Resource testSecurityDomain = null;
+ private String testSecurityDomainKey = null;
+ private ConfigurationManager testConfigurationManager = null;
+
+ //Define some shared and reusable content
+ static HashMap<String, String> jsonMap = new HashMap<String, String>();
+ static {
+ jsonMap
+ .put(
+ "login-modules",
+ "[{\"flag\":\"required\", \"code\":\"Ldap\", \"module-options\":{\"bindDn\":\"uid=ldapSecureUser,ou=People,dc=redat,dc=com\", \"bindPw\":\"test126\", \"allowEmptyPasswords\":\"true\"}}]");
+ jsonMap
+ .put(
+ "policy-modules",
+ "[{\"flag\":\"requisite\", \"code\":\"LdapExtended\", \"module-options\":{\"policy\":\"module\", \"policy1\":\"module1\"}}]");
+ jsonMap
+ .put("mapping-modules",
+ "[{\"code\":\"Test\", \"type\":\"attribute\", \"module-options\":{\"mapping\":\"module\", \"mapping1\":\"module1\"}}]");
+ jsonMap.put("provider-modules",
+ "[{\"code\":\"Providers\", \"module-options\":{\"provider\":\"module\", \"provider1\":\"module1\"}}]");
+ jsonMap
+ .put("acl-modules",
+ "[{\"flag\":\"sufficient\", \"code\":\"ACL\", \"module-options\":{\"acl\":\"module\", \"acl1\":\"module1\"}}]");
+ jsonMap
+ .put("trust-modules",
+ "[{\"flag\":\"optional\", \"code\":\"TRUST\", \"module-options\":{\"trust\":\"module\", \"trust1\":\"module1\"}}]");
+ }
+
+ /* This first discovery is only so that we can leverage existing code to install the management user needed
+ * in next test.
+ */
+ @Test(priority = 10, groups = "discovery")
+ @RunDiscovery(discoverServices = true, discoverServers = true)
+ public void firstDiscovery() throws Exception {
+ Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
+ assertNotNull(platform);
+ assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
+
+ //now install mgmt users.
+ System.out.println("------ * Duplicating discovery for SecurityModule testing....");
+ installManagementUsers();
+ }
+
+ /** This method mass loads all the supported Module Option Types(Excluding authentication=jaspi, cannot co-exist with
+ * authentication=classic) into a single SecurityDomain. This is done as
+ * -i)creating all of the related hierarchy of types needed to exercise N Module Options Types and their associated
+ * Module Options instances would take too long to setup(N creates would signal N discovery runs before test could complete).
+ * -ii)setting the priority of this method lower than the discovery method means that we'll get all the same types in much
+ * less time.
+ *
+ * @throws Exception
+ */
+ @Test(priority = 11)
+ public void loadStandardModuleOptionTypes() throws Exception {
+ mapper = new ObjectMapper();
+ mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ //Adjust discovery depth to support deeper hierarchy depth of Module Option elements
+ setMaxDiscoveryDepthOverride(12);
+
+ //create new Security Domain
+ Address destination = new Address(PROFILE);
+ destination.addSegment(SECURITY_RESOURCE_KEY);
+ String securityDomainId = TEST_DOMAIN + "2";
+ destination.addSegment(SECURITY_DOMAIN_RESOURCE_KEY + "=" + securityDomainId);
+
+ ASConnection connection = getASConnection();
+ Result result = new Result();
+ Operation op = null;
+ //delete old one if present to setup clean slate
+ op = new Operation("remove", destination);
+ result = connection.execute(op);
+
+ //build/rebuild hierarchy
+ op = new Operation("add", destination);
+ result = connection.execute(op);
+ assert result.getOutcome().equals("success") : "Add of Security Domain has failed: "
+ + result.getFailureDescription();
+
+ //Ex. profile=standalone-ha,subsystem=security,security-domain
+ String addressPrefix = PROFILE + "," + SECURITY_RESOURCE_KEY + "," + SECURITY_DOMAIN_RESOURCE_KEY;
+
+ //loop over standard types and add base details for all of them to security domain
+ String address = "";
+ for (String attribute : jsonMap.keySet()) {
+ if (attribute.equals("policy-modules")) {
+ address = addressPrefix + "=" + securityDomainId + ",authorization=classic";
+ } else if (attribute.equals("acl-modules")) {
+ address = addressPrefix + "=" + securityDomainId + ",acl=classic";
+ } else if (attribute.equals("mapping-modules")) {
+ address = addressPrefix + "=" + securityDomainId + ",mapping=classic";
+ } else if (attribute.equals("trust-modules")) {
+ address = addressPrefix + "=" + securityDomainId + ",identity-trust=classic";
+ } else if (attribute.equals("provider-modules")) {
+ address = addressPrefix + "=" + securityDomainId + ",audit=classic";
+ } else if (attribute.equals("login-modules")) {
+ address = addressPrefix + "=" + securityDomainId + ",authentication=classic";
+ } else {
+ assert false : "An unknown attribute '" + attribute
+ + "' was found. Is there a new type to be supported?";
+ }
+ //build the operation to add the component
+ ////Load json map into ModuleOptionType
+ List<Value> moduleTypeValue = new ArrayList<Value>();
+ try {
+ // loading jsonMap contents for Ex. 'login-module'
+ JsonNode node = mapper.readTree(jsonMap.get(attribute));
+ Object obj = mapper.treeToValue(node, Object.class);
+ result.setResult(obj);
+ result.setOutcome("success");
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ //populate the Value component complete with module Options.
+ moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+ ModuleOptionsComponent.loadModuleOptionType(attribute));
+ op = ModuleOptionsComponent.createAddModuleOptionTypeOperation(new Address(address), attribute,
+ moduleTypeValue);
+ //submit the command
+ result = connection.execute(op);
+ }
+ }
+
+ /** Runs the second discovery run to load all the new types added.
+ *
+ * @throws Exception
+ */
+ @Test(priority = 12, groups = "discovery")
+ @RunDiscovery(discoverServices = true, discoverServers = true)
+ public void secondDiscovery() throws Exception {
+ Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
+ assertNotNull(platform);
+ assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
+
+ //Have thread sleep longer to discover deeper resource types.
+ //spinder 6/29/12: up this number if the resources are not being discovered.
+ Thread.sleep(180 * 1000L); // delay so that PC gets a chance to scan for resources
+ }
+
+ /** This test method exercises a number of things:
+ * - that the security-domain children loaded have been created successfully
+ * - that all of the supported Module Option Type children(excluding 'authentication=jaspi') have been
+ * discovered as AS7 types successfully.
+ * - that the correct child attribute was specified for each type //Ex. acl=classic -> acl-modules
+ * -
+ *
+ * @throws Exception
+ */
+ @Test(priority = 13)
+ public void testDiscoveredSecurityNodes() throws Exception {
+ //lazy-load configurationManager
+ if (testConfigurationManager == null) {
+ testConfigurationManager = this.pluginContainer.getConfigurationManager();
+ testConfigurationManager = pluginContainer.getConfigurationManager();
+ testConfigurationManager.initialize();
+ Thread.sleep(20 * 1000L);
+ }
+ //iterate through list of nodes and make sure they've all been discovered
+ ////Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,acl=classic
+ String attribute = null;
+ for (String jsonKey : jsonMap.keySet()) {
+ //Ex. policy-modules
+ attribute = jsonKey;
+ //spinder 6/26/12: Temporarily disable until figure out why NPE happens only for this type?
+ if (attribute.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
+ break;//
+ }
+ //Ex. name=acl-modules
+ //check the configuration for the Module Option Type Ex. 'Acl (Profile)' Resource. Should be able to verify components
+ Resource moduleOptionsTypeResource = getModuleOptionTypeResource(attribute);
+ //assert non-zero id returned
+ assert moduleOptionsTypeResource.getId() > 0 : "The resource was not properly initialized. Expected id >0 but got:"
+ + moduleOptionsTypeResource.getId();
+
+ //Now request the resource complete with resource config
+ Configuration loadedConfiguration = testConfigurationManager
+ .loadResourceConfiguration(moduleOptionsTypeResource.getId());
+ String code = null;
+ String type = null;
+ String flag = null;
+ //populate the associated attributes if it's supported.
+ for (String key : loadedConfiguration.getAllProperties().keySet()) {
+ Property property = loadedConfiguration.getAllProperties().get(key);
+ if (key.equals("code")) {
+ code = ((PropertySimple) property).getStringValue();
+ } else if (key.equals("flag")) {
+ flag = ((PropertySimple) property).getStringValue();
+ } else {//Ex. type.
+ type = ((PropertySimple) property).getStringValue();
+ }
+ }
+
+ //retrieve module options as well.
+ String jsonContent = jsonMap.get(attribute);
+ Result result = new Result();
+ try {
+ // loading jsonMap contents for Ex. 'login-module'
+ JsonNode node = mapper.readTree(jsonContent);
+ Object obj = mapper.treeToValue(node, Object.class);
+ result.setResult(obj);
+ result.setOutcome("success");
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ assert false;
+ } catch (IOException e) {
+ e.printStackTrace();
+ assert false;
+ }
+
+ //populate the Value component complete with module Options.
+ List<Value> moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+ ModuleOptionsComponent.loadModuleOptionType(attribute));
+ Value moduleOptionType = moduleTypeValue.get(0);
+ //Ex. retrieve the acl-modules component and assert values.
+ //always test 'code'
+ assert moduleOptionType.getCode().equals(code) : "Module Option 'code' value is not correct. Expected '"
+ + code + "' but was '" + moduleOptionType.getCode() + "'";
+ if (attribute.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
+ assert moduleOptionType.getType().equals(type) : "Mapping Module 'type' value is not correct. Expected '"
+ + type + "' but was '" + moduleOptionType.getType() + "'";
+ } else if (!attribute.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {//Audit has no second parameter
+ assert moduleOptionType.getFlag().equals(flag) : "Provider Module 'flag' value is not correct. Expected '"
+ + flag + "' but was '" + moduleOptionType.getFlag() + "'";
+ }
+
+ //Retrieve Module Options and test
+ //Ex. Module Options for (Acl Modules - Profile)
+ Resource moduleOptionsResource = getModuleOptionsResource(moduleOptionsTypeResource, attribute);
+ //assert non-zero id returned
+ assert moduleOptionsResource.getId() > 0 : "The resource was not properly initialized. Expected id > 0 but got:"
+ + moduleOptionsResource.getId();
+ //fetch configuration for module options
+ //Now request the resource complete with resource config
+ Configuration loadedOptionsConfiguration = testConfigurationManager
+ .loadResourceConfiguration(moduleOptionsResource.getId());
+ for (String key : loadedOptionsConfiguration.getAllProperties().keySet()) {
+ //retrieve the open map of Module Options
+ PropertyMap map = ((PropertyMap) loadedOptionsConfiguration.getAllProperties().get(key));
+ LinkedHashMap<String, Object> options = moduleOptionType.getOptions();
+ for (String optionKey : map.getMap().keySet()) {
+ PropertySimple property = (PropertySimple) map.getMap().get(optionKey);
+ //test the key
+ assert options.containsKey(optionKey) : "Unable to find expected option key '" + optionKey
+ + "'. Check hierarchy.";
+ //now the value.
+ String value = String.valueOf(options.get(optionKey));
+ assert value.equals(property.getStringValue()) : "Unable to find expected Module Option mapping. Key '"
+ + optionKey
+ + "' did not map to expected value '"
+ + value
+ + "' but was '"
+ + property.getStringValue() + "'.";
+ }
+ }
+ }
+ }
+
+ @Test(priority = 14)
+ public void testCreateSecurityDomain() throws Exception {
+ //get the root security resource
+ securityResource = getResource();
+
+ //plugin config
+ Configuration createPlugConfig = new Configuration();
+ createPlugConfig.put(new PropertySimple("path", SECURITY_DOMAIN_RESOURCE_KEY += "=" + TEST_DOMAIN));
+
+ //resource config
+ Configuration createResConfig = new Configuration();
+ createResConfig.put(new PropertySimple("name", TEST_DOMAIN));
+
+ CreateResourceRequest request = new CreateResourceRequest();
+ request.setParentResourceId(securityResource.getId());
+ request.setPluginConfiguration(createPlugConfig);
+ request.setPluginName(PLUGIN_NAME);
+ request.setResourceConfiguration(createResConfig);
+ request.setResourceName(TEST_DOMAIN);
+ request.setResourceTypeName(SECURITY_DOMAIN_RESOURCE_TYPE);
+
+ CreateResourceResponse response = pluginContainer.getResourceFactoryManager().executeCreateResourceImmediately(
+ request);
+
+ assert response.getStatus() == CreateResourceStatus.SUCCESS : "The Security Domain creation failed with an error mesasge: "
+ + response.getErrorMessage();
+ }
+
+ @Test(priority = 15)
+ public void testAuthenticationClassic() throws Exception {
+ //get the root security resource
+ securityResource = getResource();
+
+ //find TEST_DOMAIN 'security-domain'
+ Resource securityDomain = null;
+ Set<Resource> childResources = securityResource.getChildResources();
+ for (Resource r : childResources) {
+ if (r.getName().indexOf(TEST_DOMAIN) > -1) {
+ securityDomain = r;
+ }
+ }
+
+ //plugin config
+ Configuration createPlugConfig = new Configuration();
+ createPlugConfig.put(new PropertySimple("path", AUTH_CLASSIC_RESOURCE_KEY));
+
+ //resource config
+ Configuration createResConfig = new Configuration();
+ createResConfig.put(new PropertySimple("code", "Ldap"));
+ createResConfig.put(new PropertySimple("flag", "requisite"));
+
+ CreateResourceRequest request = new CreateResourceRequest();
+ request.setParentResourceId(securityDomain.getId());
+ request.setPluginConfiguration(createPlugConfig);
+ request.setPluginName(PLUGIN_NAME);
+ request.setResourceConfiguration(createResConfig);
+ request.setResourceName("Test - notUsed.");
+
+ request.setResourceTypeName(AUTH_CLASSIC_RESOURCE_TYPE);
+
+ CreateResourceResponse response = pluginContainer.getResourceFactoryManager().executeCreateResourceImmediately(
+ request);
+
+ assert response.getStatus() == CreateResourceStatus.SUCCESS : "The 'Authentication (Classic)' node creation failed with an error mesasge: "
+ + response.getErrorMessage();
+ }
+
+ @Test(priority = 16)
+ public void testDeleteSecurityDomain() throws Exception {
+ //get the root security resource
+ securityResource = getResource();
+ Resource found = null;
+ Set<Resource> childResources = securityResource.getChildResources();
+ for (Resource r : childResources) {
+ if (r.getName().indexOf(TEST_DOMAIN) > -1) {
+ found = r;
+ }
+ }
+
+ //plugin config
+ Configuration deletePlugConfig = new Configuration();
+ deletePlugConfig.put(new PropertySimple("path", SECURITY_DOMAIN_RESOURCE_KEY += "=" + TEST_DOMAIN));
+
+ //resource config
+ Configuration deleteResConfig = new Configuration();
+ deleteResConfig.put(new PropertySimple("name", TEST_DOMAIN));
+
+ DeleteResourceRequest request = new DeleteResourceRequest();
+ if (found != null) {
+ request.setResourceId(found.getId());
+ }
+ DeleteResourceResponse response = pluginContainer.getResourceFactoryManager().executeDeleteResourceImmediately(
+ request);
+
+ assert response.getStatus() == DeleteResourceStatus.SUCCESS : "The Security Domain deletion failed with an error mesasge: "
+ + response.getErrorMessage();
+ }
+
+ // public static void main(String[] args) {
+ // SecurityModuleOptionsTest setup = new SecurityModuleOptionsTest();
+ // try {
+ // setup.loadStandardModuleOptionTypes();
+ // } catch (Exception e) {
+ // e.printStackTrace();
+ // }
+ // }
+
+ private Resource getResource() {
+
+ InventoryManager im = pluginContainer.getInventoryManager();
+ Resource platform = im.getPlatform();
+ Resource server = getResourceByTypeAndKey(platform, StandaloneServerComponentTest.RESOURCE_TYPE,
+ StandaloneServerComponentTest.RESOURCE_KEY);
+ Resource bindings = getResourceByTypeAndKey(server, RESOURCE_TYPE, RESOURCE_KEY);
+ return bindings;
+ }
+
+ /** Automates hierarchy creation for Module Option type resources and their parents
+ *
+ * @param optionAttributeType
+ * @return
+ */
+ private Resource getModuleOptionTypeResource(String optionAttributeType) {
+ Resource moduleOptionResource = null;
+ String securityDomainId = SECURITY_DOMAIN_RESOURCE_KEY + "=" + TEST_DOMAIN + "2";
+ if (testSecurityDomain == null) {
+ InventoryManager im = pluginContainer.getInventoryManager();
+ Resource platform = im.getPlatform();
+ //host controller
+ ResourceType hostControllerType = new ResourceType("JBossAS7 Host Controller", PLUGIN_NAME,
+ ResourceCategory.SERVER, null);
+ Resource hostController = getResourceByTypeAndKey(platform, hostControllerType,
+ "/tmp/jboss-as-6.0.0.GA/domain");
+ //profile=full-ha
+ ResourceType profileType = new ResourceType("Profile", PLUGIN_NAME, ResourceCategory.SERVICE, null);
+ String key = PROFILE;
+ Resource profile = getResourceByTypeAndKey(hostController, profileType, key);
+
+ //Security (Profile)
+ ResourceType securityType = new ResourceType("Security (Profile)", PLUGIN_NAME, ResourceCategory.SERVICE,
+ null);
+ key += "," + SECURITY_RESOURCE_KEY;
+ Resource security = getResourceByTypeAndKey(profile, securityType, key);
+
+ //Security Domain (Profile)
+ ResourceType domainType = new ResourceType("Security Domain (Profile)", PLUGIN_NAME,
+ ResourceCategory.SERVICE, null);
+ key += "," + securityDomainId;
+ testSecurityDomainKey = key;
+ testSecurityDomain = getResourceByTypeAndKey(security, domainType, key);
+ }
+
+ //acl=classic
+ String descriptorName = "";
+ String moduleAttribute = "";
+ //acl
+ if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Acl.getAttribute())) {
+ descriptorName = "ACL (Profile)";
+ moduleAttribute = "acl=classic";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {
+ descriptorName = "Audit (Profile)";
+ moduleAttribute = "audit=classic";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
+ descriptorName = "Authentication (Classic - Profile)";
+ moduleAttribute = "authentication=classic";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authorization.getAttribute())) {
+ descriptorName = "Authorization (Profile)";
+ moduleAttribute = "authorization=classic";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.IdentityTrust.getAttribute())) {
+ descriptorName = "Identity Trust (Profile)";
+ moduleAttribute = "identity-trust=classic";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
+ descriptorName = "Mapping (Profile)";
+ moduleAttribute = "mapping=classic";
+ }
+ //Build the right Module Option Type. Ex. ACL (Profile), etc.
+ ResourceType moduleOptionType = new ResourceType(descriptorName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
+ ConfigurationDefinition cdef = new ConfigurationDefinition(descriptorName, null);
+ moduleOptionType.setResourceConfigurationDefinition(cdef);
+ //Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,identity-trust=classic
+ String moduleOptionTypeKey = testSecurityDomainKey += "," + moduleAttribute;
+
+ if (!testSecurityDomainKey.endsWith(securityDomainId)) {
+ moduleOptionTypeKey = testSecurityDomainKey.substring(0, testSecurityDomainKey.indexOf(securityDomainId)
+ + securityDomainId.length())
+ + "," + moduleAttribute;
+ }
+
+ moduleOptionResource = getResourceByTypeAndKey(testSecurityDomain, moduleOptionType, moduleOptionTypeKey);
+
+ return moduleOptionResource;
+ }
+
+ /** Automates hierarchy creation for Module Option type resources and their parents
+ *
+ * @param optionAttributeType
+ * @return
+ */
+ private Resource getModuleOptionsResource(Resource parent, String optionAttributeType) {
+ Resource moduleOptionsResource = null;
+ String descriptorName = "";
+ String moduleAttribute = "";
+ String moduleOptionsDescriptor = "";
+ if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Acl.getAttribute())) {
+ // descriptorName = "ACL Modules (Profile)";
+ descriptorName = "Acl Modules (Profile)";
+ moduleAttribute = "acl=classic";
+ moduleOptionsDescriptor = "Module Options (Acl - Profile)";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {
+ descriptorName = "Provider Modules (Profile)";
+ moduleAttribute = "audit=classic";
+ moduleOptionsDescriptor = "Module Options (Provider Modules - Profile)";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
+ descriptorName = "Login Modules (Classic - Profile)";
+ moduleAttribute = "authentication=classic";
+ moduleOptionsDescriptor = "Module Options (Classic - Profile)";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authorization.getAttribute())) {
+ descriptorName = "Authorization Modules (Profile)";
+ moduleAttribute = "authorization=classic";
+ moduleOptionsDescriptor = "Module Options (Authorization - Profile)";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.IdentityTrust.getAttribute())) {
+ descriptorName = "Identity Trust Modules (Profile)";
+ moduleAttribute = "identity-trust=classic";
+ moduleOptionsDescriptor = "Module Options (Identity Trust - Profile)";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
+ descriptorName = "Mapping Modules (Profile)";
+ moduleAttribute = "mapping=classic";
+ moduleOptionsDescriptor = "Module Options (Mapping - Profile)";
+ }
+ //Build the right Module Option Type. Ex. ACL Modules (Profile), etc.
+ ResourceType modulesType = new ResourceType(descriptorName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
+ //Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,acl=classic,acl-modules:0
+ String sharedRoot = "profile=full-ha,subsystem=security,security-domain=testDomain2";
+ String moduleOptionTypeKey = sharedRoot += "," + moduleAttribute + ","
+ + optionAttributeType + ":0";
+ //Ex. Module Options Type children [ACL Modules (Profile),etc.]
+ Resource modulesInstance = getResourceByTypeAndKey(parent, modulesType, moduleOptionTypeKey);
+
+ //Module Options
+ ResourceType moduleOptionsType = new ResourceType(moduleOptionsDescriptor, PLUGIN_NAME,
+ ResourceCategory.SERVICE, null);
+ moduleOptionsResource = getResourceByTypeAndKey(modulesInstance, moduleOptionsType, moduleOptionTypeKey
+ + ",module-options");
+
+ return moduleOptionsResource;
+ }
+
+ private Resource getResource(Resource parentResource, String pluginDescriptorTypeName, String resourceKey) {
+ Resource resource = null;
+ if (((parentResource != null) & (pluginDescriptorTypeName != null) & (resourceKey != null))
+ & (((!pluginDescriptorTypeName.isEmpty()) & (!resourceKey.isEmpty())))) {
+ ResourceType resourceType = buildResourceType(pluginDescriptorTypeName);
+ resource = getResourceByTypeAndKey(parentResource, resourceType, resourceKey);
+ }
+ return resource;
+ }
+
+ private ResourceType buildResourceType(String pluginTypeName) {
+ ResourceType created = null;
+ if ((pluginTypeName != null) && (!pluginTypeName.isEmpty())) {
+ created = new ResourceType(pluginTypeName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
+ }
+ return created;
+ }
+
+ /** For each operation
+ * - will write verbose json and operation details to system.out if verboseOutput = true;
+ * - will execute the operation against running server if execute = true.
+ *
+ * @param op
+ * @param execute
+ * @param verboseOutput
+ * @return
+ */
+ public static Result exerciseOperation(Operation op, boolean execute, boolean verboseOutput) {
+ //display operation as AS7 plugin will build it
+ if (verboseOutput) {
+ System.out.println("\tOperation is:" + op);
+ }
+
+ String jsonToSend = "";
+ try {
+ jsonToSend = mapper.defaultPrettyPrintingWriter().writeValueAsString(op);
+ } catch (JsonGenerationException e) {
+ e.printStackTrace();
+ } catch (JsonMappingException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ //As generated by jackson mapper
+ if (verboseOutput) {
+ System.out.println("@@@@ OUTBOUND JSON#\n" + jsonToSend + "#");
+ }
+
+ //Execute the operation
+ Result result = new Result();
+ if (execute) {
+ result = con.execute(op);
+ } else {
+ if (verboseOutput) {
+ System.out.println("**** NOTE: Execution disabled . NOT exercising write-attribute operation. **** ");
+ }
+ }
+ if (verboseOutput) {
+ //result wrapper details
+ System.out.println("\tResult:" + result);
+ //detailed results
+ System.out.println("\tValue:" + result.getResult());
+ System.out.println("-----------------------------------------------------\n");
+ }
+ return result;
+ }
+}
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
deleted file mode 100644
index 452fdfb..0000000
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
+++ /dev/null
@@ -1,674 +0,0 @@
-/*
- * 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.modules.plugins.jbossas7.itest.standalone;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Set;
-
-import org.codehaus.jackson.JsonGenerationException;
-import org.codehaus.jackson.JsonNode;
-import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.map.DeserializationConfig;
-import org.codehaus.jackson.map.JsonMappingException;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.testng.annotations.Test;
-
-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.domain.configuration.Configuration;
-import org.rhq.core.domain.configuration.Property;
-import org.rhq.core.domain.configuration.PropertyMap;
-import org.rhq.core.domain.configuration.PropertySimple;
-import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
-import org.rhq.core.domain.resource.CreateResourceStatus;
-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.ResourceType;
-import org.rhq.core.pc.configuration.ConfigurationManager;
-import org.rhq.core.pc.inventory.InventoryManager;
-import org.rhq.modules.plugins.jbossas7.ASConnection;
-import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent;
-import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent.Value;
-import org.rhq.modules.plugins.jbossas7.itest.AbstractJBossAS7PluginTest;
-import org.rhq.modules.plugins.jbossas7.json.Address;
-import org.rhq.modules.plugins.jbossas7.json.Operation;
-import org.rhq.modules.plugins.jbossas7.json.Result;
-import org.rhq.test.arquillian.RunDiscovery;
-
-/**
- * Test exercising the subsystem=security/SecurityDomain/[Authentication(Classic|Jaspi),
- * Authorization, Mapping, Audit, Acl,
- * Identity-Trust]
- * @author Simeon Pinder
- */
-@Test(groups = { "integration", "pc", "standalone" }, singleThreaded = true)
-public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
-
- private static ASConnection con = null;
- private static ObjectMapper mapper = null;
-
- private static String TEST_DOMAIN = "testDomain";
- private static String SECURITY_RESOURCE_TYPE = "Security";
- private static String SECURITY_RESOURCE_KEY = "subsystem=security";
- private static String SECURITY_DOMAIN_RESOURCE_KEY = "security-domain";
- private static String PROFILE = "profile=full-ha";
- private static String SECURITY_DOMAIN_RESOURCE_TYPE = "Security Domain";
- private static String AUTH_CLASSIC_RESOURCE_TYPE = "Authentication (Classic)";
- private static String AUTH_CLASSIC_RESOURCE_KEY = "authentication=classic";
-
- private static Resource securityResource = null;
-
- protected static String DC_HOST = System.getProperty("jboss.domain.bindAddress");
- protected static int DC_HTTP_PORT = Integer.valueOf(System.getProperty("jboss.domain.httpManagementPort"));
- protected static String DC_USER = AbstractJBossAS7PluginTest.MANAGEMENT_USERNAME;
- protected static String DC_PASS = AbstractJBossAS7PluginTest.MANAGEMENT_PASSWORD;
-
- ASConnection getASConnection() {
- ASConnection connection = new ASConnection(DC_HOST, DC_HTTP_PORT, DC_USER, DC_PASS);
- return connection;
- }
-
- public static final ResourceType RESOURCE_TYPE = new ResourceType(SECURITY_RESOURCE_TYPE, PLUGIN_NAME,
- ResourceCategory.SERVICE, null);
- private static final String RESOURCE_KEY = SECURITY_RESOURCE_KEY;
- private static Resource testSecurityDomain = null;
- private String testSecurityDomainKey = null;
- private ConfigurationManager testConfigurationManager = null;
-
- //Define some shared and reusable content
- static HashMap<String, String> jsonMap = new HashMap<String, String>();
- static {
- jsonMap
- .put(
- "login-modules",
- "[{\"flag\":\"required\", \"code\":\"Ldap\", \"module-options\":{\"bindDn\":\"uid=ldapSecureUser,ou=People,dc=redat,dc=com\", \"bindPw\":\"test126\", \"allowEmptyPasswords\":\"true\"}}]");
- jsonMap
- .put(
- "policy-modules",
- "[{\"flag\":\"requisite\", \"code\":\"LdapExtended\", \"module-options\":{\"policy\":\"module\", \"policy1\":\"module1\"}}]");
- jsonMap
- .put("mapping-modules",
- "[{\"code\":\"Test\", \"type\":\"attribute\", \"module-options\":{\"mapping\":\"module\", \"mapping1\":\"module1\"}}]");
- jsonMap.put("provider-modules",
- "[{\"code\":\"Providers\", \"module-options\":{\"provider\":\"module\", \"provider1\":\"module1\"}}]");
- jsonMap
- .put("acl-modules",
- "[{\"flag\":\"sufficient\", \"code\":\"ACL\", \"module-options\":{\"acl\":\"module\", \"acl1\":\"module1\"}}]");
- jsonMap
- .put("trust-modules",
- "[{\"flag\":\"optional\", \"code\":\"TRUST\", \"module-options\":{\"trust\":\"module\", \"trust1\":\"module1\"}}]");
- }
-
- /* This first discovery is only so that we can leverage existing code to install the management user needed
- * in next test.
- */
- @Test(priority = 10, groups = "discovery")
- @RunDiscovery(discoverServices = true, discoverServers = true)
- public void firstDiscovery() throws Exception {
- Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
- assertNotNull(platform);
- assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
-
- //now install mgmt users.
- System.out.println("------ * Duplicating discovery for SecurityModule testing....");
- installManagementUsers();
- }
-
- /** This method mass loads all the supported Module Option Types(Excluding authentication=jaspi, cannot co-exist with
- * authentication=classic) into a single SecurityDomain. This is done as
- * -i)creating all of the related hierarchy of types needed to exercise N Module Options Types and their associated
- * Module Options instances would take too long to setup(N creates would signal N discovery runs before test could complete).
- * -ii)setting the priority of this method lower than the discovery method means that we'll get all the same types in much
- * less time.
- *
- * @throws Exception
- */
- @Test(priority = 11)
- public void loadStandardModuleOptionTypes() throws Exception {
- mapper = new ObjectMapper();
- mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
-
- //Adjust discovery depth to support deeper hierarchy depth of Module Option elements
- setMaxDiscoveryDepthOverride(12);
-
- //create new Security Domain
- Address destination = new Address(PROFILE);
- destination.addSegment(SECURITY_RESOURCE_KEY);
- String securityDomainId = TEST_DOMAIN + "2";
- destination.addSegment(SECURITY_DOMAIN_RESOURCE_KEY + "=" + securityDomainId);
-
- ASConnection connection = getASConnection();
- Result result = new Result();
- Operation op = null;
- //delete old one if present to setup clean slate
- op = new Operation("remove", destination);
- result = connection.execute(op);
-
- //build/rebuild hierarchy
- op = new Operation("add", destination);
- result = connection.execute(op);
- assert result.getOutcome().equals("success") : "Add of Security Domain has failed: "
- + result.getFailureDescription();
-
- //Ex. profile=standalone-ha,subsystem=security,security-domain
- String addressPrefix = PROFILE + "," + SECURITY_RESOURCE_KEY + "," + SECURITY_DOMAIN_RESOURCE_KEY;
-
- //loop over standard types and add base details for all of them to security domain
- String address = "";
- for (String attribute : jsonMap.keySet()) {
- if (attribute.equals("policy-modules")) {
- address = addressPrefix + "=" + securityDomainId + ",authorization=classic";
- } else if (attribute.equals("acl-modules")) {
- address = addressPrefix + "=" + securityDomainId + ",acl=classic";
- } else if (attribute.equals("mapping-modules")) {
- address = addressPrefix + "=" + securityDomainId + ",mapping=classic";
- } else if (attribute.equals("trust-modules")) {
- address = addressPrefix + "=" + securityDomainId + ",identity-trust=classic";
- } else if (attribute.equals("provider-modules")) {
- address = addressPrefix + "=" + securityDomainId + ",audit=classic";
- } else if (attribute.equals("login-modules")) {
- address = addressPrefix + "=" + securityDomainId + ",authentication=classic";
- } else {
- assert false : "An unknown attribute '" + attribute
- + "' was found. Is there a new type to be supported?";
- }
- //build the operation to add the component
- ////Load json map into ModuleOptionType
- List<Value> moduleTypeValue = new ArrayList<Value>();
- try {
- // loading jsonMap contents for Ex. 'login-module'
- JsonNode node = mapper.readTree(jsonMap.get(attribute));
- Object obj = mapper.treeToValue(node, Object.class);
- result.setResult(obj);
- result.setOutcome("success");
- } catch (JsonProcessingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- //populate the Value component complete with module Options.
- moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
- ModuleOptionsComponent.loadModuleOptionType(attribute));
- op = ModuleOptionsComponent.createAddModuleOptionTypeOperation(new Address(address), attribute,
- moduleTypeValue);
- //submit the command
- result = connection.execute(op);
- }
- }
-
- /** Runs the second discovery run to load all the new types added.
- *
- * @throws Exception
- */
- @Test(priority = 12, groups = "discovery")
- @RunDiscovery(discoverServices = true, discoverServers = true)
- public void secondDiscovery() throws Exception {
- Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
- assertNotNull(platform);
- assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
-
- //Have thread sleep longer to discover deeper resource types.
- //spinder 6/29/12: up this number if the resources are not being discovered.
- Thread.sleep(180 * 1000L); // delay so that PC gets a chance to scan for resources
- }
-
- /** This test method exercises a number of things:
- * - that the security-domain children loaded have been created successfully
- * - that all of the supported Module Option Type children(excluding 'authentication=jaspi') have been
- * discovered as AS7 types successfully.
- * - that the correct child attribute was specified for each type //Ex. acl=classic -> acl-modules
- * -
- *
- * @throws Exception
- */
- @Test(priority = 13)
- public void testDiscoveredSecurityNodes() throws Exception {
- //lazy-load configurationManager
- if (testConfigurationManager == null) {
- testConfigurationManager = this.pluginContainer.getConfigurationManager();
- testConfigurationManager = pluginContainer.getConfigurationManager();
- testConfigurationManager.initialize();
- Thread.sleep(20 * 1000L);
- }
- //iterate through list of nodes and make sure they've all been discovered
- ////Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,acl=classic
- String attribute = null;
- for (String jsonKey : jsonMap.keySet()) {
- //Ex. policy-modules
- attribute = jsonKey;
- //spinder 6/26/12: Temporarily disable until figure out why NPE happens only for this type?
- if (attribute.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
- break;//
- }
- //Ex. name=acl-modules
- //check the configuration for the Module Option Type Ex. 'Acl (Profile)' Resource. Should be able to verify components
- Resource moduleOptionsTypeResource = getModuleOptionTypeResource(attribute);
- //assert non-zero id returned
- assert moduleOptionsTypeResource.getId() > 0 : "The resource was not properly initialized. Expected id >0 but got:"
- + moduleOptionsTypeResource.getId();
-
- //Now request the resource complete with resource config
- Configuration loadedConfiguration = testConfigurationManager
- .loadResourceConfiguration(moduleOptionsTypeResource.getId());
- String code = null;
- String type = null;
- String flag = null;
- //populate the associated attributes if it's supported.
- for (String key : loadedConfiguration.getAllProperties().keySet()) {
- Property property = loadedConfiguration.getAllProperties().get(key);
- if (key.equals("code")) {
- code = ((PropertySimple) property).getStringValue();
- } else if (key.equals("flag")) {
- flag = ((PropertySimple) property).getStringValue();
- } else {//Ex. type.
- type = ((PropertySimple) property).getStringValue();
- }
- }
-
- //retrieve module options as well.
- String jsonContent = jsonMap.get(attribute);
- Result result = new Result();
- try {
- // loading jsonMap contents for Ex. 'login-module'
- JsonNode node = mapper.readTree(jsonContent);
- Object obj = mapper.treeToValue(node, Object.class);
- result.setResult(obj);
- result.setOutcome("success");
- } catch (JsonProcessingException e) {
- e.printStackTrace();
- assert false;
- } catch (IOException e) {
- e.printStackTrace();
- assert false;
- }
-
- //populate the Value component complete with module Options.
- List<Value> moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
- ModuleOptionsComponent.loadModuleOptionType(attribute));
- Value moduleOptionType = moduleTypeValue.get(0);
- //Ex. retrieve the acl-modules component and assert values.
- //always test 'code'
- assert moduleOptionType.getCode().equals(code) : "Module Option 'code' value is not correct. Expected '"
- + code + "' but was '" + moduleOptionType.getCode() + "'";
- if (attribute.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
- assert moduleOptionType.getType().equals(type) : "Mapping Module 'type' value is not correct. Expected '"
- + type + "' but was '" + moduleOptionType.getType() + "'";
- } else if (!attribute.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {//Audit has no second parameter
- assert moduleOptionType.getFlag().equals(flag) : "Provider Module 'flag' value is not correct. Expected '"
- + flag + "' but was '" + moduleOptionType.getFlag() + "'";
- }
-
- //Retrieve Module Options and test
- //Ex. Module Options for (Acl Modules - Profile)
- Resource moduleOptionsResource = getModuleOptionsResource(moduleOptionsTypeResource, attribute);
- //assert non-zero id returned
- assert moduleOptionsResource.getId() > 0 : "The resource was not properly initialized. Expected id > 0 but got:"
- + moduleOptionsResource.getId();
- //fetch configuration for module options
- //Now request the resource complete with resource config
- Configuration loadedOptionsConfiguration = testConfigurationManager
- .loadResourceConfiguration(moduleOptionsResource.getId());
- for (String key : loadedOptionsConfiguration.getAllProperties().keySet()) {
- //retrieve the open map of Module Options
- PropertyMap map = ((PropertyMap) loadedOptionsConfiguration.getAllProperties().get(key));
- LinkedHashMap<String, Object> options = moduleOptionType.getOptions();
- for (String optionKey : map.getMap().keySet()) {
- PropertySimple property = (PropertySimple) map.getMap().get(optionKey);
- //test the key
- assert options.containsKey(optionKey) : "Unable to find expected option key '" + optionKey
- + "'. Check hierarchy.";
- //now the value.
- String value = String.valueOf(options.get(optionKey));
- assert value.equals(property.getStringValue()) : "Unable to find expected Module Option mapping. Key '"
- + optionKey
- + "' did not map to expected value '"
- + value
- + "' but was '"
- + property.getStringValue() + "'.";
- }
- }
- }
- }
-
- @Test(priority = 14)
- public void testCreateSecurityDomain() throws Exception {
- //get the root security resource
- securityResource = getResource();
-
- //plugin config
- Configuration createPlugConfig = new Configuration();
- createPlugConfig.put(new PropertySimple("path", SECURITY_DOMAIN_RESOURCE_KEY += "=" + TEST_DOMAIN));
-
- //resource config
- Configuration createResConfig = new Configuration();
- createResConfig.put(new PropertySimple("name", TEST_DOMAIN));
-
- CreateResourceRequest request = new CreateResourceRequest();
- request.setParentResourceId(securityResource.getId());
- request.setPluginConfiguration(createPlugConfig);
- request.setPluginName(PLUGIN_NAME);
- request.setResourceConfiguration(createResConfig);
- request.setResourceName(TEST_DOMAIN);
- request.setResourceTypeName(SECURITY_DOMAIN_RESOURCE_TYPE);
-
- CreateResourceResponse response = pluginContainer.getResourceFactoryManager().executeCreateResourceImmediately(
- request);
-
- assert response.getStatus() == CreateResourceStatus.SUCCESS : "The Security Domain creation failed with an error mesasge: "
- + response.getErrorMessage();
- }
-
- @Test(priority = 15)
- public void testAuthenticationClassic() throws Exception {
- //get the root security resource
- securityResource = getResource();
-
- //find TEST_DOMAIN 'security-domain'
- Resource securityDomain = null;
- Set<Resource> childResources = securityResource.getChildResources();
- for (Resource r : childResources) {
- if (r.getName().indexOf(TEST_DOMAIN) > -1) {
- securityDomain = r;
- }
- }
-
- //plugin config
- Configuration createPlugConfig = new Configuration();
- createPlugConfig.put(new PropertySimple("path", AUTH_CLASSIC_RESOURCE_KEY));
-
- //resource config
- Configuration createResConfig = new Configuration();
- createResConfig.put(new PropertySimple("code", "Ldap"));
- createResConfig.put(new PropertySimple("flag", "requisite"));
-
- CreateResourceRequest request = new CreateResourceRequest();
- request.setParentResourceId(securityDomain.getId());
- request.setPluginConfiguration(createPlugConfig);
- request.setPluginName(PLUGIN_NAME);
- request.setResourceConfiguration(createResConfig);
- request.setResourceName("Test - notUsed.");
-
- request.setResourceTypeName(AUTH_CLASSIC_RESOURCE_TYPE);
-
- CreateResourceResponse response = pluginContainer.getResourceFactoryManager().executeCreateResourceImmediately(
- request);
-
- assert response.getStatus() == CreateResourceStatus.SUCCESS : "The 'Authentication (Classic)' node creation failed with an error mesasge: "
- + response.getErrorMessage();
- }
-
- @Test(priority = 16)
- public void testDeleteSecurityDomain() throws Exception {
- //get the root security resource
- securityResource = getResource();
- Resource found = null;
- Set<Resource> childResources = securityResource.getChildResources();
- for (Resource r : childResources) {
- if (r.getName().indexOf(TEST_DOMAIN) > -1) {
- found = r;
- }
- }
-
- //plugin config
- Configuration deletePlugConfig = new Configuration();
- deletePlugConfig.put(new PropertySimple("path", SECURITY_DOMAIN_RESOURCE_KEY += "=" + TEST_DOMAIN));
-
- //resource config
- Configuration deleteResConfig = new Configuration();
- deleteResConfig.put(new PropertySimple("name", TEST_DOMAIN));
-
- DeleteResourceRequest request = new DeleteResourceRequest();
- if (found != null) {
- request.setResourceId(found.getId());
- }
- DeleteResourceResponse response = pluginContainer.getResourceFactoryManager().executeDeleteResourceImmediately(
- request);
-
- assert response.getStatus() == DeleteResourceStatus.SUCCESS : "The Security Domain deletion failed with an error mesasge: "
- + response.getErrorMessage();
- }
-
- // public static void main(String[] args) {
- // SecurityModuleOptionsTest setup = new SecurityModuleOptionsTest();
- // try {
- // setup.loadStandardModuleOptionTypes();
- // } catch (Exception e) {
- // e.printStackTrace();
- // }
- // }
-
- private Resource getResource() {
-
- InventoryManager im = pluginContainer.getInventoryManager();
- Resource platform = im.getPlatform();
- Resource server = getResourceByTypeAndKey(platform, StandaloneServerComponentTest.RESOURCE_TYPE,
- StandaloneServerComponentTest.RESOURCE_KEY);
- Resource bindings = getResourceByTypeAndKey(server, RESOURCE_TYPE, RESOURCE_KEY);
- return bindings;
- }
-
- /** Automates hierarchy creation for Module Option type resources and their parents
- *
- * @param optionAttributeType
- * @return
- */
- private Resource getModuleOptionTypeResource(String optionAttributeType) {
- Resource moduleOptionResource = null;
- String securityDomainId = SECURITY_DOMAIN_RESOURCE_KEY + "=" + TEST_DOMAIN + "2";
- if (testSecurityDomain == null) {
- InventoryManager im = pluginContainer.getInventoryManager();
- Resource platform = im.getPlatform();
- //host controller
- ResourceType hostControllerType = new ResourceType("JBossAS7 Host Controller", PLUGIN_NAME,
- ResourceCategory.SERVER, null);
- Resource hostController = getResourceByTypeAndKey(platform, hostControllerType,
- "/tmp/jboss-as-6.0.0.GA/domain");
- //profile=full-ha
- ResourceType profileType = new ResourceType("Profile", PLUGIN_NAME, ResourceCategory.SERVICE, null);
- String key = PROFILE;
- Resource profile = getResourceByTypeAndKey(hostController, profileType, key);
-
- //Security (Profile)
- ResourceType securityType = new ResourceType("Security (Profile)", PLUGIN_NAME, ResourceCategory.SERVICE,
- null);
- key += "," + SECURITY_RESOURCE_KEY;
- Resource security = getResourceByTypeAndKey(profile, securityType, key);
-
- //Security Domain (Profile)
- ResourceType domainType = new ResourceType("Security Domain (Profile)", PLUGIN_NAME,
- ResourceCategory.SERVICE, null);
- key += "," + securityDomainId;
- testSecurityDomainKey = key;
- testSecurityDomain = getResourceByTypeAndKey(security, domainType, key);
- }
-
- //acl=classic
- String descriptorName = "";
- String moduleAttribute = "";
- //acl
- if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Acl.getAttribute())) {
- descriptorName = "ACL (Profile)";
- moduleAttribute = "acl=classic";
- } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {
- descriptorName = "Audit (Profile)";
- moduleAttribute = "audit=classic";
- } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
- descriptorName = "Authentication (Classic - Profile)";
- moduleAttribute = "authentication=classic";
- } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authorization.getAttribute())) {
- descriptorName = "Authorization (Profile)";
- moduleAttribute = "authorization=classic";
- } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.IdentityTrust.getAttribute())) {
- descriptorName = "Identity Trust (Profile)";
- moduleAttribute = "identity-trust=classic";
- } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
- descriptorName = "Mapping (Profile)";
- moduleAttribute = "mapping=classic";
- }
- //Build the right Module Option Type. Ex. ACL (Profile), etc.
- ResourceType moduleOptionType = new ResourceType(descriptorName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
- ConfigurationDefinition cdef = new ConfigurationDefinition(descriptorName, null);
- moduleOptionType.setResourceConfigurationDefinition(cdef);
- //Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,identity-trust=classic
- String moduleOptionTypeKey = testSecurityDomainKey += "," + moduleAttribute;
-
- if (!testSecurityDomainKey.endsWith(securityDomainId)) {
- moduleOptionTypeKey = testSecurityDomainKey.substring(0, testSecurityDomainKey.indexOf(securityDomainId)
- + securityDomainId.length())
- + "," + moduleAttribute;
- }
-
- moduleOptionResource = getResourceByTypeAndKey(testSecurityDomain, moduleOptionType, moduleOptionTypeKey);
-
- return moduleOptionResource;
- }
-
- /** Automates hierarchy creation for Module Option type resources and their parents
- *
- * @param optionAttributeType
- * @return
- */
- private Resource getModuleOptionsResource(Resource parent, String optionAttributeType) {
- Resource moduleOptionsResource = null;
- String descriptorName = "";
- String moduleAttribute = "";
- String moduleOptionsDescriptor = "";
- if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Acl.getAttribute())) {
- // descriptorName = "ACL Modules (Profile)";
- descriptorName = "Acl Modules (Profile)";
- moduleAttribute = "acl=classic";
- moduleOptionsDescriptor = "Module Options (Acl - Profile)";
- } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {
- descriptorName = "Provider Modules (Profile)";
- moduleAttribute = "audit=classic";
- moduleOptionsDescriptor = "Module Options (Provider Modules - Profile)";
- } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
- descriptorName = "Login Modules (Classic - Profile)";
- moduleAttribute = "authentication=classic";
- moduleOptionsDescriptor = "Module Options (Classic - Profile)";
- } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authorization.getAttribute())) {
- descriptorName = "Authorization Modules (Profile)";
- moduleAttribute = "authorization=classic";
- moduleOptionsDescriptor = "Module Options (Authorization - Profile)";
- } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.IdentityTrust.getAttribute())) {
- descriptorName = "Identity Trust Modules (Profile)";
- moduleAttribute = "identity-trust=classic";
- moduleOptionsDescriptor = "Module Options (Identity Trust - Profile)";
- } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
- descriptorName = "Mapping Modules (Profile)";
- moduleAttribute = "mapping=classic";
- moduleOptionsDescriptor = "Module Options (Mapping - Profile)";
- }
- //Build the right Module Option Type. Ex. ACL Modules (Profile), etc.
- ResourceType modulesType = new ResourceType(descriptorName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
- //Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,acl=classic,acl-modules:0
- String sharedRoot = "profile=full-ha,subsystem=security,security-domain=testDomain2";
- String moduleOptionTypeKey = sharedRoot += "," + moduleAttribute + ","
- + optionAttributeType + ":0";
- //Ex. Module Options Type children [ACL Modules (Profile),etc.]
- Resource modulesInstance = getResourceByTypeAndKey(parent, modulesType, moduleOptionTypeKey);
-
- //Module Options
- ResourceType moduleOptionsType = new ResourceType(moduleOptionsDescriptor, PLUGIN_NAME,
- ResourceCategory.SERVICE, null);
- moduleOptionsResource = getResourceByTypeAndKey(modulesInstance, moduleOptionsType, moduleOptionTypeKey
- + ",module-options");
-
- return moduleOptionsResource;
- }
-
- private Resource getResource(Resource parentResource, String pluginDescriptorTypeName, String resourceKey) {
- Resource resource = null;
- if (((parentResource != null) & (pluginDescriptorTypeName != null) & (resourceKey != null))
- & (((!pluginDescriptorTypeName.isEmpty()) & (!resourceKey.isEmpty())))) {
- ResourceType resourceType = buildResourceType(pluginDescriptorTypeName);
- resource = getResourceByTypeAndKey(parentResource, resourceType, resourceKey);
- }
- return resource;
- }
-
- private ResourceType buildResourceType(String pluginTypeName) {
- ResourceType created = null;
- if ((pluginTypeName != null) && (!pluginTypeName.isEmpty())) {
- created = new ResourceType(pluginTypeName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
- }
- return created;
- }
-
- /** For each operation
- * - will write verbose json and operation details to system.out if verboseOutput = true;
- * - will execute the operation against running server if execute = true.
- *
- * @param op
- * @param execute
- * @param verboseOutput
- * @return
- */
- public static Result exerciseOperation(Operation op, boolean execute, boolean verboseOutput) {
- //display operation as AS7 plugin will build it
- if (verboseOutput) {
- System.out.println("\tOperation is:" + op);
- }
-
- String jsonToSend = "";
- try {
- jsonToSend = mapper.defaultPrettyPrintingWriter().writeValueAsString(op);
- } catch (JsonGenerationException e) {
- e.printStackTrace();
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- //As generated by jackson mapper
- if (verboseOutput) {
- System.out.println("@@@@ OUTBOUND JSON#\n" + jsonToSend + "#");
- }
-
- //Execute the operation
- Result result = new Result();
- if (execute) {
- result = con.execute(op);
- } else {
- if (verboseOutput) {
- System.out.println("**** NOTE: Execution disabled . NOT exercising write-attribute operation. **** ");
- }
- }
- if (verboseOutput) {
- //result wrapper details
- System.out.println("\tResult:" + result);
- //detailed results
- System.out.println("\tValue:" + result.getResult());
- System.out.println("-----------------------------------------------------\n");
- }
- return result;
- }
-}
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java
index 5d64977..fe05def 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java
@@ -73,7 +73,7 @@ public class TemplatedResourcesTest extends AbstractJBossAS7PluginTest {
StandaloneServerComponentTest.RESOURCE_KEY);
inventoryManager.activateResource(server, platformContainer, false);
- Thread.sleep(20 * 1000L);
+ Thread.sleep(30 * 1000L);
for (ResourceData resourceData : testResourceData) {
ResourceType resourceType = new ResourceType(resourceData.resourceTypeName, PLUGIN_NAME,
@@ -100,6 +100,7 @@ public class TemplatedResourcesTest extends AbstractJBossAS7PluginTest {
for (Resource resourceUnderTest : foundResources) {
log.info(foundResources);
+ assert resourceUnderTest.getId() > 0 : "Resource not properly initialized. Id = 0. Try extending sleep after discovery.";
Configuration resourceUnderTestConfig = configurationManager
.loadResourceConfiguration(resourceUnderTest.getId());
commit 89fa0d623ae733febad51a61774782447bb07c41
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Fri Jun 29 09:30:20 2012 -0400
Fix problem with test Resource discovery and cleaned up names and properties.
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
index e3f88af..452fdfb 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
@@ -24,12 +24,15 @@ import static org.testng.Assert.assertNotNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
+import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.DeserializationConfig;
+import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.testng.annotations.Test;
@@ -39,6 +42,7 @@ import org.rhq.core.clientapi.agent.inventory.DeleteResourceRequest;
import org.rhq.core.clientapi.agent.inventory.DeleteResourceResponse;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.Property;
+import org.rhq.core.domain.configuration.PropertyMap;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.resource.CreateResourceStatus;
@@ -67,27 +71,24 @@ import org.rhq.test.arquillian.RunDiscovery;
@Test(groups = { "integration", "pc", "standalone" }, singleThreaded = true)
public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
- private static String user = "rhqadmin";
- private static String pass = "as7";
- private static String host = "localhost";
private static ASConnection con = null;
private static ObjectMapper mapper = null;
- private ModuleOptionsComponent moc = null;
private static String TEST_DOMAIN = "testDomain";
- private static Resource securityResource = null;
private static String SECURITY_RESOURCE_TYPE = "Security";
private static String SECURITY_RESOURCE_KEY = "subsystem=security";
- private static String SECURITY_DOMAIN_RESOURCE_TYPE = "Security Domain";
private static String SECURITY_DOMAIN_RESOURCE_KEY = "security-domain";
+ private static String PROFILE = "profile=full-ha";
+ private static String SECURITY_DOMAIN_RESOURCE_TYPE = "Security Domain";
private static String AUTH_CLASSIC_RESOURCE_TYPE = "Authentication (Classic)";
private static String AUTH_CLASSIC_RESOURCE_KEY = "authentication=classic";
- private static String PROFILE = "profile=full-ha";
- protected static final String DC_HOST = System.getProperty("jboss.domain.bindAddress");
- protected static final int DC_HTTP_PORT = Integer.valueOf(System.getProperty("jboss.domain.httpManagementPort"));
- protected static final String DC_USER = AbstractJBossAS7PluginTest.MANAGEMENT_USERNAME;
- protected static final String DC_PASS = AbstractJBossAS7PluginTest.MANAGEMENT_PASSWORD;
+ private static Resource securityResource = null;
+
+ protected static String DC_HOST = System.getProperty("jboss.domain.bindAddress");
+ protected static int DC_HTTP_PORT = Integer.valueOf(System.getProperty("jboss.domain.httpManagementPort"));
+ protected static String DC_USER = AbstractJBossAS7PluginTest.MANAGEMENT_USERNAME;
+ protected static String DC_PASS = AbstractJBossAS7PluginTest.MANAGEMENT_PASSWORD;
ASConnection getASConnection() {
ASConnection connection = new ASConnection(DC_HOST, DC_HTTP_PORT, DC_USER, DC_PASS);
@@ -125,6 +126,21 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
"[{\"flag\":\"optional\", \"code\":\"TRUST\", \"module-options\":{\"trust\":\"module\", \"trust1\":\"module1\"}}]");
}
+ /* This first discovery is only so that we can leverage existing code to install the management user needed
+ * in next test.
+ */
+ @Test(priority = 10, groups = "discovery")
+ @RunDiscovery(discoverServices = true, discoverServers = true)
+ public void firstDiscovery() throws Exception {
+ Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
+ assertNotNull(platform);
+ assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
+
+ //now install mgmt users.
+ System.out.println("------ * Duplicating discovery for SecurityModule testing....");
+ installManagementUsers();
+ }
+
/** This method mass loads all the supported Module Option Types(Excluding authentication=jaspi, cannot co-exist with
* authentication=classic) into a single SecurityDomain. This is done as
* -i)creating all of the related hierarchy of types needed to exercise N Module Options Types and their associated
@@ -134,13 +150,13 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
*
* @throws Exception
*/
- @Test(priority = 10)
- public void testLoadStandardModuleOptionTypes() throws Exception {
+ @Test(priority = 11)
+ public void loadStandardModuleOptionTypes() throws Exception {
mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//Adjust discovery depth to support deeper hierarchy depth of Module Option elements
- setMaxDiscoveryDepthOverride(10);
+ setMaxDiscoveryDepthOverride(12);
//create new Security Domain
Address destination = new Address(PROFILE);
@@ -150,13 +166,16 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
ASConnection connection = getASConnection();
Result result = new Result();
+ Operation op = null;
//delete old one if present to setup clean slate
- Operation op = new Operation("remove", destination);
+ op = new Operation("remove", destination);
result = connection.execute(op);
//build/rebuild hierarchy
op = new Operation("add", destination);
result = connection.execute(op);
+ assert result.getOutcome().equals("success") : "Add of Security Domain has failed: "
+ + result.getFailureDescription();
//Ex. profile=standalone-ha,subsystem=security,security-domain
String addressPrefix = PROFILE + "," + SECURITY_RESOURCE_KEY + "," + SECURITY_DOMAIN_RESOURCE_KEY;
@@ -205,15 +224,20 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
}
}
- @Test(priority = 11, groups = "discovery")
+ /** Runs the second discovery run to load all the new types added.
+ *
+ * @throws Exception
+ */
+ @Test(priority = 12, groups = "discovery")
@RunDiscovery(discoverServices = true, discoverServers = true)
- public void initialDiscovery() throws Exception {
+ public void secondDiscovery() throws Exception {
Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
assertNotNull(platform);
assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
- //Have thread sleep longer to discover deeper resource types.
- Thread.sleep(120 * 1000L); // delay so that PC gets a chance to scan for resources
+ //Have thread sleep longer to discover deeper resource types.
+ //spinder 6/29/12: up this number if the resources are not being discovered.
+ Thread.sleep(180 * 1000L); // delay so that PC gets a chance to scan for resources
}
/** This test method exercises a number of things:
@@ -225,7 +249,7 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
*
* @throws Exception
*/
- @Test(priority = 12)
+ @Test(priority = 13)
public void testDiscoveredSecurityNodes() throws Exception {
//lazy-load configurationManager
if (testConfigurationManager == null) {
@@ -246,13 +270,14 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
}
//Ex. name=acl-modules
//check the configuration for the Module Option Type Ex. 'Acl (Profile)' Resource. Should be able to verify components
- Resource aclResource = getModuleOptionResourceResource(attribute);
+ Resource moduleOptionsTypeResource = getModuleOptionTypeResource(attribute);
//assert non-zero id returned
- assert aclResource.getId() > 0 : "The resource was not properly initialized. Expected id >0 but got:"
- + aclResource.getId();
+ assert moduleOptionsTypeResource.getId() > 0 : "The resource was not properly initialized. Expected id >0 but got:"
+ + moduleOptionsTypeResource.getId();
//Now request the resource complete with resource config
- Configuration loadedConfiguration = testConfigurationManager.loadResourceConfiguration(aclResource.getId());
+ Configuration loadedConfiguration = testConfigurationManager
+ .loadResourceConfiguration(moduleOptionsTypeResource.getId());
String code = null;
String type = null;
String flag = null;
@@ -300,11 +325,40 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
assert moduleOptionType.getFlag().equals(flag) : "Provider Module 'flag' value is not correct. Expected '"
+ flag + "' but was '" + moduleOptionType.getFlag() + "'";
}
+
+ //Retrieve Module Options and test
+ //Ex. Module Options for (Acl Modules - Profile)
+ Resource moduleOptionsResource = getModuleOptionsResource(moduleOptionsTypeResource, attribute);
+ //assert non-zero id returned
+ assert moduleOptionsResource.getId() > 0 : "The resource was not properly initialized. Expected id > 0 but got:"
+ + moduleOptionsResource.getId();
+ //fetch configuration for module options
+ //Now request the resource complete with resource config
+ Configuration loadedOptionsConfiguration = testConfigurationManager
+ .loadResourceConfiguration(moduleOptionsResource.getId());
+ for (String key : loadedOptionsConfiguration.getAllProperties().keySet()) {
+ //retrieve the open map of Module Options
+ PropertyMap map = ((PropertyMap) loadedOptionsConfiguration.getAllProperties().get(key));
+ LinkedHashMap<String, Object> options = moduleOptionType.getOptions();
+ for (String optionKey : map.getMap().keySet()) {
+ PropertySimple property = (PropertySimple) map.getMap().get(optionKey);
+ //test the key
+ assert options.containsKey(optionKey) : "Unable to find expected option key '" + optionKey
+ + "'. Check hierarchy.";
+ //now the value.
+ String value = String.valueOf(options.get(optionKey));
+ assert value.equals(property.getStringValue()) : "Unable to find expected Module Option mapping. Key '"
+ + optionKey
+ + "' did not map to expected value '"
+ + value
+ + "' but was '"
+ + property.getStringValue() + "'.";
+ }
+ }
}
- //TODO spinder 6-26-12: retrieve the Module Options and test them too.
}
- @Test(priority = 13)
+ @Test(priority = 14)
public void testCreateSecurityDomain() throws Exception {
//get the root security resource
securityResource = getResource();
@@ -332,7 +386,7 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
+ response.getErrorMessage();
}
- @Test(priority = 14)
+ @Test(priority = 15)
public void testAuthenticationClassic() throws Exception {
//get the root security resource
securityResource = getResource();
@@ -371,7 +425,7 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
+ response.getErrorMessage();
}
- @Test(priority = 15)
+ @Test(priority = 16)
public void testDeleteSecurityDomain() throws Exception {
//get the root security resource
securityResource = getResource();
@@ -405,7 +459,7 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
// public static void main(String[] args) {
// SecurityModuleOptionsTest setup = new SecurityModuleOptionsTest();
// try {
- // setup.testLoadStandardModuleOptionTypes();
+ // setup.loadStandardModuleOptionTypes();
// } catch (Exception e) {
// e.printStackTrace();
// }
@@ -421,12 +475,12 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
return bindings;
}
- /** Automates
+ /** Automates hierarchy creation for Module Option type resources and their parents
*
* @param optionAttributeType
* @return
*/
- private Resource getModuleOptionResourceResource(String optionAttributeType) {
+ private Resource getModuleOptionTypeResource(String optionAttributeType) {
Resource moduleOptionResource = null;
String securityDomainId = SECURITY_DOMAIN_RESOURCE_KEY + "=" + TEST_DOMAIN + "2";
if (testSecurityDomain == null) {
@@ -497,6 +551,60 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
return moduleOptionResource;
}
+ /** Automates hierarchy creation for Module Option type resources and their parents
+ *
+ * @param optionAttributeType
+ * @return
+ */
+ private Resource getModuleOptionsResource(Resource parent, String optionAttributeType) {
+ Resource moduleOptionsResource = null;
+ String descriptorName = "";
+ String moduleAttribute = "";
+ String moduleOptionsDescriptor = "";
+ if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Acl.getAttribute())) {
+ // descriptorName = "ACL Modules (Profile)";
+ descriptorName = "Acl Modules (Profile)";
+ moduleAttribute = "acl=classic";
+ moduleOptionsDescriptor = "Module Options (Acl - Profile)";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {
+ descriptorName = "Provider Modules (Profile)";
+ moduleAttribute = "audit=classic";
+ moduleOptionsDescriptor = "Module Options (Provider Modules - Profile)";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
+ descriptorName = "Login Modules (Classic - Profile)";
+ moduleAttribute = "authentication=classic";
+ moduleOptionsDescriptor = "Module Options (Classic - Profile)";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authorization.getAttribute())) {
+ descriptorName = "Authorization Modules (Profile)";
+ moduleAttribute = "authorization=classic";
+ moduleOptionsDescriptor = "Module Options (Authorization - Profile)";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.IdentityTrust.getAttribute())) {
+ descriptorName = "Identity Trust Modules (Profile)";
+ moduleAttribute = "identity-trust=classic";
+ moduleOptionsDescriptor = "Module Options (Identity Trust - Profile)";
+ } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
+ descriptorName = "Mapping Modules (Profile)";
+ moduleAttribute = "mapping=classic";
+ moduleOptionsDescriptor = "Module Options (Mapping - Profile)";
+ }
+ //Build the right Module Option Type. Ex. ACL Modules (Profile), etc.
+ ResourceType modulesType = new ResourceType(descriptorName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
+ //Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,acl=classic,acl-modules:0
+ String sharedRoot = "profile=full-ha,subsystem=security,security-domain=testDomain2";
+ String moduleOptionTypeKey = sharedRoot += "," + moduleAttribute + ","
+ + optionAttributeType + ":0";
+ //Ex. Module Options Type children [ACL Modules (Profile),etc.]
+ Resource modulesInstance = getResourceByTypeAndKey(parent, modulesType, moduleOptionTypeKey);
+
+ //Module Options
+ ResourceType moduleOptionsType = new ResourceType(moduleOptionsDescriptor, PLUGIN_NAME,
+ ResourceCategory.SERVICE, null);
+ moduleOptionsResource = getResourceByTypeAndKey(modulesInstance, moduleOptionsType, moduleOptionTypeKey
+ + ",module-options");
+
+ return moduleOptionsResource;
+ }
+
private Resource getResource(Resource parentResource, String pluginDescriptorTypeName, String resourceKey) {
Resource resource = null;
if (((parentResource != null) & (pluginDescriptorTypeName != null) & (resourceKey != null))
@@ -515,288 +623,52 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
return created;
}
- //##################################################################
- // /**The test reads the existing property values, deserializes them and writes the same
- // * contents back out to a running instance for all known ModuleOptionTypes.
- // *
- // * @throws Exception
- // */
- // public void testPopulateModuleOptionsAndTypes() throws Exception {
- //
- // //as7 node details.
- // String securityDomainId = "testDomain";
- // //TODO: spinder 6-6-12: this cannot run as a standalone itest until JIRA https://issues.jboss.org/browse/AS7-4951
- // // is addressed as there is no way to automate setup of the information being tested.
- // String address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
- // boolean verboseOutput = true;
- // boolean executeOperation = true;
- // for (ModuleOptionType t : ModuleOptionType.values()) {
- // String attribute = t.getAttribute();
- // if (verboseOutput) {
- // System.out.println("======= Running with ModuleOptionType:" + t + " attribute:" + attribute + ":");
- // }
- // if (attribute.equals("policy-modules")) {
- // address = "subsystem=security,security-domain=" + securityDomainId + ",authorization=classic";
- // } else if (attribute.equals("acl-modules")) {
- // address = "subsystem=security,security-domain=" + securityDomainId + ",acl=classic";
- // } else if (attribute.equals("mapping-modules")) {
- // address = "subsystem=security,security-domain=" + securityDomainId + ",mapping=classic";
- // } else if (attribute.equals("trust-modules")) {
- // address = "subsystem=security,security-domain=" + securityDomainId + ",identity-trust=classic";
- // } else if (attribute.equals("provider-modules")) {
- // address = "subsystem=security,security-domain=" + securityDomainId + ",audit=classic";
- // } else if (attribute.equals("login-modules")) {
- // address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
- // } else {
- // assert false : "An unknown attribute '" + attribute
- // + "' was found. Is there a new type to be supported?";
- // }
- //
- // //test operation- read property always available.
- // Operation op = null;
- //
- // //read the login-modules attribute
- // op = new ReadAttribute(new Address(address), attribute);
- // Result result = exerciseOperation(op, true, verboseOutput);
- // assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
- // + result.getFailureDescription();
- // //extract current results
- // Object rawResult = result.getResult();
- // assert rawResult != null : "Read of attribute'" + attribute + "' from address '" + address
- // + "' has returned no value. Are those values in the model?";
- //
- // List<Value> list2 = new ArrayList<Value>();
- // //populate the Value component complete with module Options.
- // list2 = moc.populateSecurityDomainModuleOptions(result,
- // ModuleOptionsComponent.loadModuleOptionType(attribute));
- // if (verboseOutput) {
- // if (rawResult != null) {
- // System.out.println("Raw Result is:" + rawResult + " and of type:" + rawResult.getClass());
- // } else {
- // System.out.println("Read of attribute'" + attribute + "' from address '" + address
- // + "' has returned no value. Are those values in the model?");
- // }
- // }
- // //write the login-modules attribute
- // op = new WriteAttribute(new Address(address));
- // op.addAdditionalProperty("name", attribute);//attribute to execute on
- // op.addAdditionalProperty("value", list2);
- //
- // //Now test the operation
- // result = exerciseOperation(op, executeOperation, verboseOutput);
- // assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
- // + "' failed to write the resource.." + result.getFailureDescription();
- //
- // //read the login-modules attribute
- // op = new ReadAttribute(new Address(address), attribute);
- // result = exerciseOperation(op, true, verboseOutput);
- // assert (result.isSuccess() == true) : "The operation '" + op + "' failed to read the resource."
- // + result.getFailureDescription();
- // }
- // if (verboseOutput) {
- // System.out.println("Successfully detected,read and wrote out attribute values for:");
- // for (ModuleOptionType type : ModuleOptionType.values()) {
- // System.out.println("\n" + type.ordinal() + " " + type.name());
- // }
- // }
- // }
- //
- // /**Attempts to create a new Authentication node(authentication=classic) with a
- // * 'login-modules' attribute complete with 'code':'Ldap' and 'flag':'required'
- // * and some sample 'module-options' values.
- // *
- // */
- // @Test(enabled = true)
- // public void testCreateSecurityDomainChildLoginModules() {
- // boolean execute = true;
- // boolean verboseOutput = false;
- // String address = "subsystem=security,security-domain=testDomain3,authentication=classic";
- // String attribute = ModuleOptionType.Authentication.getAttribute();
- //
- // //test operation- read property always available.
- // Operation op = null;
- //
- // //read the login-modules attribute
- // op = new ReadAttribute(new Address(address), attribute);
- // Result result = exerciseOperation(op, execute, verboseOutput);
- // assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
- // + result.getFailureDescription();
- //
- // //extract current results
- // Object rawResult = result.getResult();
- //
- // //#### Have to create new content for the new node.
- // List<Value> moduleTypeValue = new ArrayList<Value>();
- // try {
- // // loading 'login-module'
- // JsonNode node = mapper.readTree(jsonMap.get(attribute));
- // result.setResult(mapper.treeToValue(node, Object.class));
- // } catch (JsonProcessingException e) {
- // e.printStackTrace();
- // } catch (IOException e) {
- // e.printStackTrace();
- // }
- //
- // //populate the Value component complete with module Options.
- // moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
- // ModuleOptionsComponent.loadModuleOptionType(attribute));
- //
- // //add the login-modules attribute
- // op = ModuleOptionsComponent
- // .createAddModuleOptionTypeOperation(new Address(address), attribute, moduleTypeValue);
- //
- // result = exerciseOperation(op, execute, verboseOutput);
- // assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
- // + "' failed to write the resource.." + result.getFailureDescription();
- //
- // //read the login-modules attribute
- // op = new ReadAttribute(new Address(address), attribute);
- // result = exerciseOperation(op, execute, verboseOutput);
- // assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
- // + result.getFailureDescription();
- //
- // //exercise values retrieved from read
- // List<Value> serverResponse = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
- // ModuleOptionsComponent.loadModuleOptionType(attribute));
- // Value serverState = serverResponse.get(0);
- // assert serverState.getFlag().equals("required") : "Incorrect state retrieved for 'flag'. Expected 'required'.";
- // assert serverState.getCode().equals("Ldap") : "Incorrect state retrieved for 'code'. Expected 'Ldap'.";
- // LinkedHashMap<String, Object> options = serverState.getOptions();
- // assert options.size() == 3 : "Invalid number of module options returned. Expected 3.";
- // int found = 0;
- // for (String key : options.keySet()) {
- // if (key.equals("bindPw")) {
- // assert "test126".equals(options.get(key)) : "Module option value not correct for key '" + key + "'.";
- // found++;
- // } else if (key.equals("bindDn")) {
- // assert "uid=ldapSecureUser,ou=People,dc=redat,dc=com".equals(options.get(key)) : "Module option value not correct for key '"
- // + key + "'.";
- // found++;
- // } else if (key.equals("allowEmptyPasswords")) {
- // assert "true".equals(options.get(key)) : "Module option value not correct for key '" + key + "'.";
- // found++;
- // }
- // }
- // assert found == 3 : "All module options were not loaded.";
- //
- // //remove the original node to reset for next run.
- // op = new Remove(new Address(address));
- // result = exerciseOperation(op, execute, verboseOutput);
- // assert result.isSuccess() == true : "The operation '" + op + "' failed to remove the resource."
- // + result.getFailureDescription();
- // }
- //
- // /** For each operation
- // * - will write verbose json and operation details to system.out if verboseOutput = true;
- // * - will execute the operation against running server if execute = true.
- // *
- // * @param op
- // * @param execute
- // * @param verboseOutput
- // * @return
- // */
- // public static Result exerciseOperation(Operation op, boolean execute, boolean verboseOutput) {
- // //display operation as AS7 plugin will build it
- // if (verboseOutput) {
- // System.out.println("\tOperation is:" + op);
- // }
- //
- // String jsonToSend = "";
- // try {
- // jsonToSend = mapper.defaultPrettyPrintingWriter().writeValueAsString(op);
- // } catch (JsonGenerationException e) {
- // e.printStackTrace();
- // } catch (JsonMappingException e) {
- // e.printStackTrace();
- // } catch (IOException e) {
- // e.printStackTrace();
- // }
- // //As generated by jackson mapper
- // if (verboseOutput) {
- // System.out.println("@@@@ OUTBOUND JSON#\n" + jsonToSend + "#");
- // }
- //
- // //Execute the operation
- // Result result = new Result();
- // if (execute) {
- // result = con.execute(op);
- // } else {
- // if (verboseOutput) {
- // System.out.println("**** NOTE: Execution disabled . NOT exercising write-attribute operation. **** ");
- // }
- // }
- // if (verboseOutput) {
- // //result wrapper details
- // System.out.println("\tResult:" + result);
- // //detailed results
- // System.out.println("\tValue:" + result.getResult());
- // System.out.println("-----------------------------------------------------\n");
- // }
- // return result;
- // }
- //
- // @Test(priority = 10, groups = "discovery")
- // public void initialSetup() throws Exception {
- // String securityDomainId = TEST_DOMAIN + "1";
- // Result result = null;
- // Operation op = null;
- //
- // //create the initial securityDomain
- // op = new Operation("add", new Address("subsystem=security,security-domain=" + securityDomainId));
- // ASConnection connection = getASConnection();
- // con = connection;
- // mapper = new ObjectMapper();
- // mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
- //
- // moc = new ModuleOptionsComponent();
- // result = connection.execute(op);
- // System.out.println("#### Op is:" + op);
- // System.out.println("#### Result is:" + result);
- //
- // //iterate over jsonMap
- // for (String key : jsonMap.keySet()) {
- // String attribute = key;
- // String address = "";
- // if (attribute.equals("policy-modules")) {
- // address = "subsystem=security,security-domain=" + securityDomainId + ",authorization=classic";
- // } else if (attribute.equals("acl-modules")) {
- // address = "subsystem=security,security-domain=" + securityDomainId + ",acl=classic";
- // } else if (attribute.equals("mapping-modules")) {
- // address = "subsystem=security,security-domain=" + securityDomainId + ",mapping=classic";
- // } else if (attribute.equals("trust-modules")) {
- // address = "subsystem=security,security-domain=" + securityDomainId + ",identity-trust=classic";
- // } else if (attribute.equals("provider-modules")) {
- // address = "subsystem=security,security-domain=" + securityDomainId + ",audit=classic";
- // } else if (attribute.equals("login-modules")) {
- // address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
- // } else {
- // assert false : "An unknown attribute '" + attribute
- // + "' was found. Is there a new type to be supported?";
- // }
- // //#### Have to create new content for the new node.
- // List<Value> moduleTypeValue = new ArrayList<Value>();
- //
- // try {
- // // loading 'login-module'
- // JsonNode node = mapper.readTree(jsonMap.get(attribute));
- // result.setResult(mapper.treeToValue(node, Object.class));
- // } catch (JsonProcessingException e) {
- // e.printStackTrace();
- // } catch (IOException e) {
- // e.printStackTrace();
- // }
- //
- // //populate the Value component complete with module Options.
- // moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
- // ModuleOptionsComponent.loadModuleOptionType(attribute));
- //
- // //add the login-modules attribute
- // op = ModuleOptionsComponent.createAddModuleOptionTypeOperation(new Address(address), attribute,
- // moduleTypeValue);
- //
- // result = exerciseOperation(op, true, true);
- // assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
- // + "' failed to write the resource.." + result.getFailureDescription();
- // }
- // }
+ /** For each operation
+ * - will write verbose json and operation details to system.out if verboseOutput = true;
+ * - will execute the operation against running server if execute = true.
+ *
+ * @param op
+ * @param execute
+ * @param verboseOutput
+ * @return
+ */
+ public static Result exerciseOperation(Operation op, boolean execute, boolean verboseOutput) {
+ //display operation as AS7 plugin will build it
+ if (verboseOutput) {
+ System.out.println("\tOperation is:" + op);
+ }
+
+ String jsonToSend = "";
+ try {
+ jsonToSend = mapper.defaultPrettyPrintingWriter().writeValueAsString(op);
+ } catch (JsonGenerationException e) {
+ e.printStackTrace();
+ } catch (JsonMappingException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ //As generated by jackson mapper
+ if (verboseOutput) {
+ System.out.println("@@@@ OUTBOUND JSON#\n" + jsonToSend + "#");
+ }
+
+ //Execute the operation
+ Result result = new Result();
+ if (execute) {
+ result = con.execute(op);
+ } else {
+ if (verboseOutput) {
+ System.out.println("**** NOTE: Execution disabled . NOT exercising write-attribute operation. **** ");
+ }
+ }
+ if (verboseOutput) {
+ //result wrapper details
+ System.out.println("\tResult:" + result);
+ //detailed results
+ System.out.println("\tValue:" + result.getResult());
+ System.out.println("-----------------------------------------------------\n");
+ }
+ return result;
+ }
}
commit 76a9b14a24bf361f6916203c133500a77d98da73
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Jun 20 15:29:43 2012 +0200
Rename the method to be more descriptive.
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
index e350302..384a6e0 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
@@ -81,7 +81,7 @@ public class LocalClient implements RhqFacade {
Object proxy = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
- return getProxy(getLocalSLSB(manager), manager.remote());
+ return getScriptingProxy(getLocalSLSB(manager), manager);
}
});
@@ -112,8 +112,8 @@ public class LocalClient implements RhqFacade {
return remoteApiIface.cast(proxy);
}
- private <T> T getProxy(Object slsb, Class<T> iface) {
- RhqManager manager = RhqManager.forInterface(iface);
+ private Object getScriptingProxy(Object slsb, RhqManager manager) {
+ Class<?> iface = manager.remote();
Class<?> simplified = null;
@@ -128,7 +128,7 @@ public class LocalClient implements RhqFacade {
Object proxy = Proxy.newProxyInstance(iface.getClassLoader(), new Class<?>[] { simplified },
new LocalClientProxy(slsb, this, manager));
- return iface.cast(proxy);
+ return proxy;
}
private Object getLocalSLSB(RhqManager manager) {
commit 56d3bb7e5f2b3ec81138841058edebe9a6bc1ac2
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Jun 20 15:29:15 2012 +0200
CLI code completion should now be language independent.
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index 9811d2a..5d1af69 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@ -40,9 +40,6 @@ import java.util.Map;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
-import gnu.getopt.Getopt;
-import gnu.getopt.LongOpt;
-
import jline.ArgumentCompletor;
import jline.Completor;
import jline.ConsoleReader;
@@ -56,7 +53,11 @@ import org.rhq.core.domain.auth.Subject;
import org.rhq.enterprise.client.commands.ClientCommand;
import org.rhq.enterprise.client.commands.ScriptCommand;
import org.rhq.enterprise.client.script.CommandLineParseException;
+import org.rhq.enterprise.client.utility.CLIMetadataProvider;
+import org.rhq.enterprise.client.utility.CodeCompletionCompletorWrapper;
+import org.rhq.enterprise.client.utility.DummyCodeCompletion;
import org.rhq.enterprise.clientapi.RemoteClient;
+import org.rhq.scripting.CodeCompletion;
/**
* @author Greg Hinkle
@@ -100,7 +101,7 @@ public class ClientMain {
// The subject that will be used to carry out all requested actions
private Subject subject;
- private InteractiveJavascriptCompletor serviceCompletor;
+ private CodeCompletion codeCompletion;
private boolean interactiveMode = true;
@@ -199,12 +200,9 @@ public class ClientMain {
sc.initClient(this);
}
- private void initServiceCompletor() {
- this.serviceCompletor.setContext(getScriptEngine().getContext());
-
- if (remoteClient != null) {
- this.serviceCompletor.setServices(remoteClient.getScriptingAPI());
- }
+ private void initCodeCompletion() {
+ this.codeCompletion.setScriptContext(getScriptEngine().getContext());
+ this.codeCompletion.setMetadataProvider(new CLIMetadataProvider());
}
public ClientMain() {
@@ -233,12 +231,19 @@ public class ClientMain {
Completor helpCompletor = new ArgumentCompletor(new Completor[] { new SimpleCompletor("help"),
new SimpleCompletor(commands.keySet().toArray(new String[commands.size()])) });
- this.serviceCompletor = new InteractiveJavascriptCompletor(consoleReader);
- consoleReader.addCompletor(new MultiCompletor(new Completor[] { serviceCompletor, helpCompletor,
+ this.codeCompletion = ScriptEngineFactory.getCodeCompletion(getLanguage());
+ if (codeCompletion == null) {
+ //the language module for this language doesn't support code completion
+ //let's provide a dummy one.
+ codeCompletion = new DummyCodeCompletion();
+ }
+
+ initCodeCompletion();
+
+ consoleReader.addCompletor(new MultiCompletor(new Completor[] {
+ new CodeCompletionCompletorWrapper(codeCompletion, outputWriter), helpCompletor,
commandCompletor }));
- initServiceCompletor();
-
// enable pagination
consoleReader.setUsePagination(true);
}
@@ -375,7 +380,7 @@ public class ClientMain {
} else {
boolean result = commands.get("exec").execute(this, args);
if (loggedIn()) {
- this.serviceCompletor.setContext(getScriptEngine().getContext());
+ this.codeCompletion.setScriptContext(getScriptEngine().getContext());
}
return result;
@@ -595,7 +600,7 @@ public class ClientMain {
initScriptCommand();
if (isInteractiveMode()) {
- initServiceCompletor();
+ initCodeCompletion();
}
}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java
deleted file mode 100644
index 0f1b232..0000000
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
- * 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.client;
-
-import java.beans.BeanInfo;
-import java.beans.Introspector;
-import java.beans.MethodDescriptor;
-import java.beans.PropertyDescriptor;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.jws.WebParam;
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-
-import jline.Completor;
-import jline.ConsoleReader;
-
-import org.rhq.core.domain.auth.Subject;
-import org.rhq.enterprise.client.utility.ReflectionUtility;
-import org.rhq.enterprise.clientapi.RemoteClientProxy;
-
-/**
- * A Contextual JavaScript interactive completor. Not perfect, but
- * handles a fair number of cases.
- *
- * @author Greg Hinkle
- */
-public class InteractiveJavascriptCompletor implements Completor {
-
- private Map<String, Object> services;
-
- private ScriptContext context;
-
- private String lastComplete;
-
- // Consecutive times this exact complete has been requested
- private int recomplete;
- private ConsoleReader consoleReader;
-
- private static final Set<String> IGNORED_METHODS;
- static {
- IGNORED_METHODS = new HashSet<String>();
- IGNORED_METHODS.add("newProxyInstance");
- IGNORED_METHODS.add("hashCode");
- IGNORED_METHODS.add("equals");
- IGNORED_METHODS.add("getInvocationHandler");
- IGNORED_METHODS.add("setHandler");
- IGNORED_METHODS.add("isProxyClass");
- IGNORED_METHODS.add("newProxyInstance");
- IGNORED_METHODS.add("getProxyClass");
- IGNORED_METHODS.add("main");
- IGNORED_METHODS.add("handler");
- IGNORED_METHODS.add("init");
- IGNORED_METHODS.add("initChildren");
- IGNORED_METHODS.add("initMeasurements");
- IGNORED_METHODS.add("initOperations");
- }
-
- public InteractiveJavascriptCompletor(ConsoleReader reader) {
- this.consoleReader = reader;
- }
-
- public void setServices(Map<String, Object> services) {
- this.services = services;
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public int complete(String s, int i, @SuppressWarnings("rawtypes") List list) {
- try {
- if (lastComplete != null && lastComplete.equals(s)) {
- recomplete++;
- } else {
- recomplete = 1;
- }
-
- lastComplete = s;
-
- String base = s;
-
- int rootLength = 0;
-
- if (s.indexOf('=') > 0) {
- base = s.substring(s.indexOf("=") + 1).trim();
- rootLength = s.length() - base.length();
- }
-
- String[] call = base.split("\\.");
- if (base.endsWith(".")) {
- String[] argPadded = new String[call.length + 1];
- System.arraycopy(call, 0, argPadded, 0, call.length);
- argPadded[call.length] = "";
- call = argPadded;
- }
-
- if (call.length == 1) {
- Map<String, Object> matches = getContextMatches(call[0]);
- if (matches.size() == 1 && matches.containsKey(call[0]) && !s.endsWith(".")) {
- list.add(".");
- return rootLength + call[0].length() + 1;
-
- } else {
- list.addAll(matches.keySet());
- }
- } else {
- Object rootObject = context.getAttribute(call[0]);
- if (rootObject != null) {
- String theRest = base.substring(call[0].length() + 1, base.length());
- int matchIndex = contextComplete(rootObject, theRest, i, list);
- Collections.sort(list);
- return rootLength + call[0].length() + 1 + matchIndex;
- }
- }
-
- Collections.sort(list);
-
- return (list.size() == 0) ? (-1) : rootLength;
- } catch (Exception e) {
- e.printStackTrace();
- return -1;
- }
- }
-
- /**
- * Base Object can be an object where we're looking for methods on it, or an
- * interface. This recursively works off the completions left to right.
- *
- * Objects can be completed with fields or method calls.
- * method parameters are completed with type matching
- * method result chainings are completed based on declared return types
- *
- * e.g. have a Resource in context as myResource. Original string is
- * "myResource.name". This method would be called with a baseObject ==
- * to myResource and the string "name".
- *
- * Note: this method will not and should not execute methods, but will
- * read field properties to continue chained completions.
- *
- * @param baseObject the context object or class to complete from
- * @param s the relative command string to check
- * @param i
- * @param list
- * @return location of relative completion
- */
- private int contextComplete(Object baseObject, String s, int i, List<String> list) {
- String temp = s.split("\\(", 2)[0];
- if (temp.contains(".")) {
- String[] call = temp.split("\\.", 2);
-
- String next = call[0];
- if (next.contains("(")) {
- next = next.substring(0, next.indexOf("("));
- }
-
- Map<String, List<Object>> matches = getContextMatches(baseObject, next);
- if (!matches.isEmpty()) {
- Object rootObject = matches.get(next).get(0);
- if (rootObject instanceof PropertyDescriptor && !(baseObject instanceof Class)) {
- try {
- rootObject = invoke(baseObject, ((PropertyDescriptor) rootObject).getReadMethod());
- } catch (Exception e) {
- e.printStackTrace();
- }
- } else if (rootObject instanceof Method) {
- rootObject = ((Method) rootObject).getReturnType();
- }
-
- return call[0].length() + 1 + contextComplete(rootObject, call[1], i, list);
- } else {
- return -1;
- }
- } else {
- String[] call = s.split("\\(", 2);
-
- Map<String, List<Object>> matches = getContextMatches(baseObject, call[0]);
-
- if (call.length == 2 && matches.containsKey(call[0])) {
-
- int x = 0;
- for (String key : matches.keySet()) {
-
- List<Object> matchList = matches.get(key);
-
- if (recomplete == 2) {
- List<Method> methods = new ArrayList<Method>();
- for (Object match : matchList) {
- if (match instanceof Method) {
- methods.add((Method) match);
- }
- }
- displaySignatures(baseObject, methods.toArray(new Method[methods.size()]));
- return -1;
- }
-
- for (Object match : matchList) {
-
- if (key.equals(call[0]) && match instanceof Method) {
-
- int result = completeParameters(baseObject, call[1], i, list, (Method) match); // x should be the same for all calls
- if (result > 0) {
- x = result;
- }
- }
- }
- }
- return call[0].length() + 1 + x;
- }
-
- if (matches.size() == 1 && matches.containsKey(call[0])) {
- if (matches.get(call[0]).get(0) instanceof Method) {
- list.add("(" + (((Method) matches.get(call[0]).get(0)).getParameterTypes().length == 0 ? ")" : ""));
- }
- return call[0].length() + 1;
- }
-
- if (recomplete == 2) {
- List<Method> methods = new ArrayList<Method>();
- for (List<Object> matchList : matches.values()) {
- for (Object val : matchList) {
- if (val instanceof Method) {
- methods.add((Method) val);
- }
- }
- }
- displaySignatures(baseObject, methods.toArray(new Method[methods.size()]));
- } else {
- if (matches.size() == 1 && matches.values().iterator().next().get(0) instanceof Method) {
- list.add(matches.keySet().iterator().next()
- + "("
- + ((((Method) matches.values().iterator().next().get(0)).getParameterTypes().length == 0 ? ")"
- : "")));
- } else {
- list.addAll(matches.keySet());
- }
- }
- return 0;
-
- }
- }
-
- private void displaySignatures(Object object, Method... methods) {
- try {
- String start = this.consoleReader.getCursorBuffer().getBuffer().toString();
- while ((this.consoleReader.getCursorBuffer().cursor > 0) && this.consoleReader.backspace()) {
- ;
- }
- this.consoleReader.printNewline();
- this.consoleReader.printNewline();
- String[][] signatures = new String[methods.length][];
- int i = 0;
- for (Method m : methods) {
- signatures[i++] = getSignature(object, m).split(" ", 2);
- }
-
- int maxReturnLength = 0;
- for (String[] sig : signatures) {
- if (sig[0].length() > maxReturnLength)
- maxReturnLength = sig[0].length();
- }
-
- for (String[] sig : signatures) {
- for (i = 0; i < (maxReturnLength - sig[0].length()); i++) {
- this.consoleReader.printString(" ");
- }
-
- this.consoleReader.printString(sig[0]);
- this.consoleReader.printString(" ");
- this.consoleReader.printString(sig[1]);
- this.consoleReader.printNewline();
- }
-
- this.consoleReader.drawLine();
- this.consoleReader.putString(start);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Split apart the parameters to a method call and complete the last parameter. If the last
- * paramater has a valid value close that field with a "," for the next param or a ")" if is
- * the last parameter. Does all machting according to the type of the parameters of the
- * supplied method.
- *
- * @param baseObject
- * @param params
- * @param i
- * @param list
- * @param method
- * @return
- */
- public int completeParameters(Object baseObject, String params, int i, List<String> list, Method method) {
-
- String[] paramList = params.split(",");
-
- Class<?>[] c = method.getParameterTypes();
-
- String lastParam = paramList[paramList.length - 1];
- int paramIndex = paramList.length - 1;
- if (params.trim().endsWith(",")) {
- lastParam = "";
- paramIndex++;
- }
-
- int baseLength = 0;
-
- for (int x = 0; x < paramIndex; x++) {
- Object paramFound = context.getAttribute(paramList[x]);
-
- if (paramFound != null && !c[x].isAssignableFrom(paramFound.getClass())) {
- return -1;
- }
- baseLength += paramList[x].length() + 1;
- }
-
- if (paramIndex >= c.length) {
- if (params.endsWith(")")) {
- return -1;
- } else {
- list.add(params + ")");
- return (params + ")").length();
- }
- } else {
-
- if (baseObject instanceof Map && method.getName().equals("get") && method.getParameterTypes().length == 1) {
- //unused Class<?> keyType = method.getParameterTypes()[0];
- for (Object key : ((Map<?, ?>) baseObject).keySet()) {
- String lookupChoice = "\'" + String.valueOf(key) + "\'";
- if (lookupChoice.startsWith(lastParam)) {
- list.add(lookupChoice);
- }
- }
- if (list.size() == 1) {
- list.set(0, list.get(0) + ")");
- }
-
- } else {
- Class<?> parameterType = c[paramIndex];
-
- Map<String, Object> matches = getContextMatches(lastParam, parameterType);
-
- if (matches.size() == 1 && matches.containsKey(lastParam)) {
-
- list.add(paramIndex == c.length - 1 ? ")" : ",");
- return baseLength + lastParam.length();
- } else {
- list.addAll(matches.keySet());
- }
- }
-
- return baseLength;
- }
- }
-
- private Map<String, Object> getContextMatches(String start) {
- Map<String, Object> found = new HashMap<String, Object>();
- if (context != null) {
- for (Integer scope : context.getScopes()) {
- Bindings bindings = context.getBindings(scope);
- for (String var : bindings.keySet()) {
- if (var.startsWith(start)) {
- found.put(var, bindings.get(var));
- }
- }
- }
- }
- if (services != null) {
- for (String var : services.keySet()) {
- if (var.startsWith(start)) {
- found.put(var, services.get(var));
- }
- }
- }
- return found;
- }
-
- /**
- * Look through all available contexts to find bindings that both start with
- * the supplied start and match the typeFilter.
- * @param start
- * @param typeFilter
- * @return
- */
- private Map<String, Object> getContextMatches(String start, Class<?> typeFilter) {
- Map<String, Object> found = new HashMap<String, Object>();
- if (context != null) {
- for (int scope : context.getScopes()) {
- Bindings bindings = context.getBindings(scope);
- for (String var : bindings.keySet()) {
- if (var.startsWith(start)) {
-
- if ((bindings.get(var) != null && typeFilter.isAssignableFrom(bindings.get(var).getClass()))
- || recomplete == 3) {
- found.put(var, bindings.get(var));
- }
- }
- }
- }
-
- if (typeFilter.isEnum()) {
- for (Object ec : typeFilter.getEnumConstants()) {
- Enum<?> e = (Enum<?>) ec;
- String code = typeFilter.getSimpleName() + "." + e.name();
- if (code.startsWith(start)) {
- found.put(typeFilter.getSimpleName() + "." + e.name(), e);
- }
- }
- }
- }
- return found;
- }
-
- private Map<String, List<Object>> getContextMatches(Object baseObject, String start) {
- Map<String, List<Object>> found = new HashMap<String, List<Object>>();
-
- Class<?> baseObjectClass = null;
- if (baseObject instanceof Class) {
- baseObjectClass = (Class<?>) baseObject;
- } else {
- baseObjectClass = baseObject.getClass();
- }
-
- try {
- if (baseObjectClass.equals(Void.TYPE))
- return found;
-
- BeanInfo info = null;
- if (baseObjectClass.isInterface() || baseObjectClass.equals(Object.class)) {
- info = Introspector.getBeanInfo(baseObjectClass);
- } else {
- info = Introspector.getBeanInfo(baseObjectClass, Object.class);
- }
-
- Set<Method> methodsCovered = new HashSet<Method>();
-
- PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
- for (PropertyDescriptor desc : descriptors) {
- if (desc.getName().startsWith(start) && (!IGNORED_METHODS.contains(desc.getName()))) {
-
- List<Object> list = found.get(desc.getName());
- if (list == null) {
- list = new ArrayList<Object>();
- found.put(desc.getName(), list);
- }
- list.add(desc);
-
- methodsCovered.add(desc.getReadMethod());
- methodsCovered.add(desc.getWriteMethod());
- }
- }
-
- MethodDescriptor[] methods = info.getMethodDescriptors();
- for (MethodDescriptor desc : methods) {
- if (desc.getName().startsWith(start) && !methodsCovered.contains(desc.getMethod())
- && !desc.getName().startsWith("_d") && !IGNORED_METHODS.contains(desc.getName())) {
-
- Method m = desc.getMethod();
- boolean isProxy = isProxyMethod(baseObject, m);
- Class<?>[] parameters = m.getParameterTypes();
- boolean startsWithSubject = ((parameters.length > 0) && parameters[0].equals(Subject.class));
- if ((isProxy && startsWithSubject) || !startsWithSubject) {
-
- List<Object> list = found.get(desc.getName());
- if (list == null) {
- list = new ArrayList<Object>();
- found.put(desc.getName(), list);
- }
- list.add(m);
- }
- }
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- return found;
- }
-
- private static String getSignature(Object object, Method m) {
-
- // If its our service proxy lookup the original interface that has the annotations
- if (isProxyMethod(object, m)) {
- Class<?>[] params = m.getParameterTypes();
- Class<?>[] newParams = new Class[params.length + 1];
- System.arraycopy(params, 0, newParams, 1, params.length);
- newParams[0] = Subject.class;
-
- try {
- m =
- ((RemoteClientProxy) Proxy.getInvocationHandler(object)).getRemoteInterface().getDeclaredMethod(
- m.getName(), newParams);
- } catch (NoSuchMethodException nsme) {
- //
- }
- }
-
- StringBuilder buf = new StringBuilder();
- Type[] params = m.getGenericParameterTypes();
- Annotation[][] annotations = m.getParameterAnnotations();
- int i = 0;
-
- buf.append(ReflectionUtility.getSimpleTypeString(m.getGenericReturnType()));
- buf.append(" ");
-
- buf.append(m.getName());
- buf.append("(");
- boolean first = true;
- for (Type type : params) {
- if (i == 0 && type.equals(Subject.class)) {
- i++;
- continue;
- }
- if (!first) {
- buf.append(", ");
- } else {
- first = false;
- }
-
- String name = null;
-
- if (annotations != null && annotations.length >= i) {
- Annotation[] as = annotations[i];
- for (Annotation a : as) {
- if (a instanceof WebParam) {
- name = ReflectionUtility.getSimpleTypeString(type) + " " + ((WebParam) a).name();
- }
- }
- }
-
- if (name == null) {
- name = ReflectionUtility.getSimpleTypeString(type);
- }
-
- buf.append(name);
-
- i++;
- }
- buf.append(")");
- return buf.toString();
- }
-
- private static boolean isProxyMethod(Object object, Method m) {
-
- boolean result = false;
- if (object instanceof Proxy) {
- if (Proxy.getInvocationHandler(object) instanceof RemoteClientProxy) {
- try {
- m =
- ((RemoteClientProxy) Proxy.getInvocationHandler(object)).getRemoteInterface()
- .getDeclaredMethod(m.getName(), m.getParameterTypes());
- } catch (NoSuchMethodException e) {
- result = true;
- }
- }
- }
- return result;
- }
-
- public ScriptContext getContext() {
- return context;
- }
-
- public void setContext(ScriptContext context) {
- this.context = context;
- }
-
- private static Object invoke(Object o, Method m) throws IllegalAccessException, InvocationTargetException {
- boolean access = m.isAccessible();
- m.setAccessible(true);
- try {
- return m.invoke(o);
- } finally {
- m.setAccessible(access);
- }
- }
-}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java
new file mode 100644
index 0000000..ff98b5c
--- /dev/null
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java
@@ -0,0 +1,72 @@
+/*
+ * 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.client.utility;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+
+import javax.jws.WebParam;
+
+import org.rhq.scripting.MetadataProvider;
+
+/**
+ * @author Lukas Krejci
+ */
+public class CLIMetadataProvider implements MetadataProvider {
+
+ @Override
+ public String getParameterName(Method method, int parameterIndex) {
+ String name = null;
+
+ Annotation[][] paramAnnotations = method.getParameterAnnotations();
+
+ if (paramAnnotations.length > parameterIndex) {
+ Annotation[] annotations = paramAnnotations[parameterIndex];
+ for (Annotation a : annotations) {
+ if (a instanceof WebParam) {
+ name = ((WebParam) a).name();
+ break;
+ }
+ }
+ }
+
+ return name;
+ }
+
+ @Override
+ public String getDocumentation(Class<?> clazz) {
+ // TODO it'd be fantastic if we could do this, wouldn't it?
+ return null;
+ }
+
+ @Override
+ public String getDocumentation(Method method) {
+ // TODO it'd be fantastic if we could do this, wouldn't it?
+ return null;
+ }
+
+ @Override
+ public String getTypeName(Type type, boolean fullNames) {
+ return ReflectionUtility.getTypeString(type, fullNames);
+ }
+
+}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java
new file mode 100644
index 0000000..8f2570c
--- /dev/null
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java
@@ -0,0 +1,24 @@
+package org.rhq.enterprise.client.utility;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+import jline.Completor;
+
+import org.rhq.scripting.CodeCompletion;
+
+public class CodeCompletionCompletorWrapper implements Completor {
+
+ private CodeCompletion completion;
+ private PrintWriter output;
+
+ public CodeCompletionCompletorWrapper(CodeCompletion completion, PrintWriter output) {
+ this.completion = completion;
+ this.output = output;
+ }
+
+ @Override
+ public int complete(String buffer, int cursor, List candidates) {
+ return completion.complete(output, buffer, cursor, candidates);
+ }
+}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/DummyCodeCompletion.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/DummyCodeCompletion.java
new file mode 100644
index 0000000..2c28a4f
--- /dev/null
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/DummyCodeCompletion.java
@@ -0,0 +1,50 @@
+/*
+ * 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.client.utility;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+import javax.script.ScriptContext;
+
+import org.rhq.scripting.CodeCompletion;
+import org.rhq.scripting.MetadataProvider;
+
+/**
+ * @author Lukas Krejci
+ *
+ */
+public class DummyCodeCompletion implements CodeCompletion {
+
+ @Override
+ public void setScriptContext(ScriptContext scriptContext) {
+ }
+
+ @Override
+ public void setMetadataProvider(MetadataProvider metadataProvider) {
+ }
+
+ @Override
+ public int complete(PrintWriter output, String context, int cursorPosition, List candidates) {
+ return cursorPosition;
+ }
+
+}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ReflectionUtility.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ReflectionUtility.java
index c5c2f08..3bcb1cc 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ReflectionUtility.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ReflectionUtility.java
@@ -18,10 +18,10 @@
*/
package org.rhq.enterprise.client.utility;
-import java.lang.reflect.Type;
+import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
-import java.lang.reflect.GenericArrayType;
import java.lang.reflect.WildcardType;
/**
@@ -32,6 +32,10 @@ public class ReflectionUtility {
public static String getSimpleTypeString(Type type) {
+ return getTypeString(type, false);
+ }
+
+ public static String getTypeString(Type type, boolean fullNames) {
if (type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) type;
Type[] typeArguments = pType.getActualTypeArguments();
@@ -43,26 +47,29 @@ public class ReflectionUtility {
typeArgString += ",";
}
- typeArgString += getSimpleTypeString(typeArgument);
+ typeArgString += getTypeString(typeArgument, fullNames);
}
- return getSimpleTypeString(pType.getRawType()) + "<" + typeArgString + ">";
-
+ return getTypeString(pType.getRawType(), fullNames) + "<" + typeArgString + ">";
} else if (type instanceof TypeVariable) {
- TypeVariable vType = (TypeVariable) type;
- return vType.getClass().getSimpleName();
+ TypeVariable<?> vType = (TypeVariable<?>) type;
+ return getName(vType.getClass(), fullNames);
} else if (type instanceof GenericArrayType) {
GenericArrayType aType = (GenericArrayType) type;
- return aType.getClass().getSimpleName() + "[" + getSimpleTypeString(aType.getGenericComponentType()) + "]";
+ return getName(aType.getClass(), fullNames) + "["
+ + getTypeString(aType.getGenericComponentType(), fullNames) + "]";
} else if (type instanceof WildcardType) {
- return ((WildcardType)type).toString();
+ return ((WildcardType) type).toString();
} else {
if (type == null) {
return "";
} else {
- return ((Class)type).getSimpleName();
+ return getName((Class<?>) type, fullNames);
}
}
}
+ private static String getName(Class<?> cls, boolean fullName) {
+ return fullName ? cls.getName() : cls.getSimpleName();
+ }
}
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 d1df7f5..36eb060 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
@@ -38,6 +38,9 @@ import java.util.Set;
import javax.script.Bindings;
import javax.script.ScriptContext;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
import org.rhq.scripting.CodeCompletion;
import org.rhq.scripting.MetadataProvider;
@@ -50,7 +53,8 @@ import org.rhq.scripting.MetadataProvider;
*/
public class JavascriptCompletor implements CodeCompletion {
- private static final String SUBJECT_CLASS_NAME = "org.rhq.core.domain.auth.Subject";
+ private static final Log LOG = LogFactory.getLog(JavascriptCompletor.class);
+
private ScriptContext context;
private MetadataProvider metadataProvider;
@@ -473,26 +477,21 @@ public class JavascriptCompletor implements CodeCompletion {
&& !desc.getName().startsWith("_d") && !IGNORED_METHODS.contains(desc.getName())) {
Method m = desc.getMethod();
- //TODO THIS IS SO WRONG - the methods are there but we just "forget" to
- //to mention them to the user.
- boolean isProxy = isProxyMethod(baseObject, m);
- Class<?>[] parameters = m.getParameterTypes();
- boolean startsWithSubject = ((parameters.length > 0) && isSubjectClass(parameters[0]));
- if ((isProxy && startsWithSubject) || !startsWithSubject) {
-
- List<Object> list = found.get(desc.getName());
- if (list == null) {
- list = new ArrayList<Object>();
- found.put(desc.getName(), list);
- }
- list.add(m);
+
+ List<Object> list = found.get(desc.getName());
+ if (list == null) {
+ list = new ArrayList<Object>();
+ found.put(desc.getName(), list);
}
+ list.add(m);
}
}
} catch (Exception e) {
+ LOG.info("Failure during code completion", e);
e.printStackTrace(output);
}
+
return found;
}
@@ -529,26 +528,6 @@ public class JavascriptCompletor implements CodeCompletion {
return buf.toString();
}
- private static boolean isProxyMethod(Object object, Method m) {
- // TODO this has to be changed - we have the MetaDataProvider which should be able
- // to provide enough info so that the completors don't have to go through these hoops.
- return false;
-
- // boolean result = false;
- // if (object instanceof Proxy) {
- // if (Proxy.getInvocationHandler(object) instanceof RemoteClientProxy) {
- // try {
- // m =
- // ((RemoteClientProxy) Proxy.getInvocationHandler(object)).getRemoteInterface()
- // .getDeclaredMethod(m.getName(), m.getParameterTypes());
- // } catch (NoSuchMethodException e) {
- // result = true;
- // }
- // }
- // }
- // return result;
- }
-
@Override
public void setScriptContext(ScriptContext context) {
this.context = context;
@@ -563,16 +542,4 @@ public class JavascriptCompletor implements CodeCompletion {
m.setAccessible(access);
}
}
-
- private boolean isSubjectClass(Class<?> cls) {
- while (cls != null) {
- if (SUBJECT_CLASS_NAME.equals(cls.getName())) {
- return true;
- }
-
- cls = cls.getSuperclass();
- }
-
- return false;
- }
}
commit c7cd0fa0318df8039f0864dd2faf3b2d67d4aaef
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Jun 20 15:23:53 2012 +0200
The simplified interfaces no longer inherit from the remote interfaces.
They just provide the same (or simplified) methods.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
index 8407206..d6835a0 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
@@ -47,31 +47,29 @@ public class InterfaceSimplifier {
public static Class<?> simplify(Class<?> intf) {
try {
- ClassPool cp = ClassPool.getDefault();
+ ClassPool classPool = ClassPool.getDefault();
String simplifiedName = getSimplifiedName(intf);
LOG.debug("Simplifying " + intf + " (simplified interface name: " + simplifiedName + ")...");
try {
- CtClass cached = cp.get(simplifiedName);
- return Class.forName(simplifiedName, false, cp.getClassLoader());
+ @SuppressWarnings("unused")
+ CtClass cached = classPool.get(simplifiedName);
+ return Class.forName(simplifiedName, false, classPool.getClassLoader());
} catch (NotFoundException e) {
// ok... load it
} catch (ClassNotFoundException e) {
- LOG.debug("Class [" + simplifiedName + "] not found - cause: " + e);
+ LOG.debug("Class [" + simplifiedName + "] not found - cause: " + e, e);
}
- CtClass cc = cp.get(intf.getName());
+ CtClass originalClass = classPool.get(intf.getName());
- CtClass cz = cp.getAndRename(intf.getName(), simplifiedName);
- // CtClass cz = cp.makeInterface(simpleName, cc);
+ CtClass newClass = classPool.makeInterface(simplifiedName);
- cz.defrost();
+ newClass.defrost();
- cz.setSuperclass(cc);
-
- CtMethod[] methods = cc.getMethods();
+ CtMethod[] methods = originalClass.getMethods();
for (CtMethod originalMethod : methods) {
@@ -81,10 +79,10 @@ public class InterfaceSimplifier {
CtClass[] simpleParams = new CtClass[params.length - 1];
System.arraycopy(params, 1, simpleParams, 0, params.length - 1);
- cz.defrost();
+ newClass.defrost();
CtMethod newMethod = CtNewMethod.abstractMethod(originalMethod.getReturnType(), originalMethod
- .getName(), simpleParams, null, cz);
+.getName(), simpleParams, null, newClass);
ParameterAnnotationsAttribute originalAnnotationsAttribute = (ParameterAnnotationsAttribute) originalMethod
.getMethodInfo().getAttribute(ParameterAnnotationsAttribute.visibleTag);
@@ -111,11 +109,11 @@ public class InterfaceSimplifier {
}
- cz.addMethod(newMethod);
+ newClass.addMethod(newMethod);
}
}
- return cz.toClass();
+ return newClass.toClass();
} catch (NotFoundException e) {
LOG.debug("Failed to simplify " + intf + " - cause: " + e);
diff --git a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
index eac3705..2236923 100644
--- a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
+++ b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
@@ -33,14 +33,13 @@ import javax.naming.spi.InitialContextFactory;
import org.jmock.Expectations;
import org.jmock.api.Invocation;
import org.jmock.lib.action.CustomAction;
+import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.rhq.bindings.client.RhqManager;
import org.rhq.core.domain.auth.Subject;
import org.rhq.enterprise.client.LocalClient;
-import org.rhq.enterprise.server.alert.AlertManagerLocal;
-import org.rhq.enterprise.server.alert.AlertManagerRemote;
import org.rhq.test.JMockTest;
/**
@@ -67,13 +66,6 @@ public class LocalClientTest extends JMockTest {
@Test
public void testResilienceAgainstContextClassloaders() throws Exception {
CONTEXT_MOCK_FOR_TEST = context.mock(Context.class);
- final AlertManagerRemote alertManagerMock = (AlertManagerRemote) Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] { AlertManagerRemote.class, AlertManagerLocal.class }, new InvocationHandler() {
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- return null;
- }
-
- });
context.checking(new Expectations() {{
allowing(CONTEXT_MOCK_FOR_TEST).lookup(with(any(String.class)));
@@ -122,8 +114,14 @@ public class LocalClientTest extends JMockTest {
//this call creates the proxy and is theoretically prone to the context classloader
Object am = lc.getScriptingAPI().get("AlertManager");
- //check that both the original and simplified methods exist on the returned object
- am.getClass().getMethod("deleteAlerts", new Class<?>[] { Subject.class, int[].class });
+ //check that only the simplified method exists on the returned object
+ try {
+ am.getClass().getMethod("deleteAlerts", new Class<?>[] { Subject.class, int[].class });
+ Assert.fail("The original remote interface method should not be available on the scripting API proxy.");
+ } catch (NoSuchMethodException e) {
+ //expected
+ }
+
am.getClass().getMethod("deleteAlerts", new Class<?>[] { int[].class });
} finally {
Thread.currentThread().setContextClassLoader(origCl);
commit 32a6fdd2b88f8711c1d1c14763e8230a62a8eb91
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Jun 20 15:21:44 2012 +0200
Fixing the local client tests and some leftover compilation errors in
the code after the RhqFacade refactoring.
diff --git a/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/AbstractPerspectiveResourceUIBean.java b/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/AbstractPerspectiveResourceUIBean.java
index 74f7ab8..f13e087 100644
--- a/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/AbstractPerspectiveResourceUIBean.java
+++ b/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/AbstractPerspectiveResourceUIBean.java
@@ -2,7 +2,9 @@ package org.rhq.enterprise.server.perspective;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.jboss.seam.annotations.web.RequestParameter;
+
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.resource.Resource;
@@ -37,7 +39,7 @@ public class AbstractPerspectiveResourceUIBean extends AbstractPerspectiveUIBean
Subject subject = this.perspectiveClient.getSubject();
// ***NOTE***: The javassist.NotFoundException stack traces that are logged by this call can be ignored.
- ResourceManagerRemote resourceManager = remoteClient.getResourceManager();
+ ResourceManagerRemote resourceManager = remoteClient.getProxy(ResourceManagerRemote.class);
ResourceCriteria resourceCriteria = new ResourceCriteria();
resourceCriteria.addFilterId(this.rhqResourceId);
PageList<Resource> resources = resourceManager.findResourcesByCriteria(subject, resourceCriteria);
diff --git a/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/PerspectiveClientUIBean.java b/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/PerspectiveClientUIBean.java
index 77d8f24..d73431a 100644
--- a/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/PerspectiveClientUIBean.java
+++ b/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/PerspectiveClientUIBean.java
@@ -87,7 +87,7 @@ public class PerspectiveClientUIBean {
if (subject == null) {
RemoteClient remoteClient = getRemoteClient();
// ***NOTE***: The javassist.NotFoundException stack traces that are logged by this call can be ignored.
- SubjectManagerRemote subjectManager = remoteClient.getSubjectManager();
+ SubjectManagerRemote subjectManager = remoteClient.getProxy(SubjectManagerRemote.class);
if (this.rhqSessionId != null) {
log.info("Retrieving subject for user [" + getUsername() + "] and sessionId [" + this.rhqSessionId
+ "]...");
diff --git a/modules/enterprise/server/client-api/pom.xml b/modules/enterprise/server/client-api/pom.xml
index 81b559c..91682fa 100644
--- a/modules/enterprise/server/client-api/pom.xml
+++ b/modules/enterprise/server/client-api/pom.xml
@@ -46,7 +46,15 @@
<artifactId>test-utils</artifactId>
<version>${project.version}</version>
<scope>test</scope>
- </dependency>
+ </dependency>
+
+ <!-- Needed for the successful creation of the fake SLSB impls in the LocalClient test. -->
+ <dependency>
+ <groupId>org.opensymphony.quartz</groupId>
+ <artifactId>quartz</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
</dependencies>
<profiles>
diff --git a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
index e9bd928..eac3705 100644
--- a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
+++ b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
@@ -31,9 +31,12 @@ import javax.naming.NamingException;
import javax.naming.spi.InitialContextFactory;
import org.jmock.Expectations;
+import org.jmock.api.Invocation;
+import org.jmock.lib.action.CustomAction;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
+import org.rhq.bindings.client.RhqManager;
import org.rhq.core.domain.auth.Subject;
import org.rhq.enterprise.client.LocalClient;
import org.rhq.enterprise.server.alert.AlertManagerLocal;
@@ -74,7 +77,36 @@ public class LocalClientTest extends JMockTest {
context.checking(new Expectations() {{
allowing(CONTEXT_MOCK_FOR_TEST).lookup(with(any(String.class)));
- will(returnValue(alertManagerMock));
+ will(new CustomAction("Fake JNDI lookup") {
+
+ @Override
+ public Object invoke(Invocation invocation) throws Throwable {
+ //the JNDI name is "rhq/<BEAN_NAME>/local"
+ String jndiName = (String) invocation.getParameter(0);
+
+ String beanName = jndiName.substring(jndiName.indexOf('/') + 1, jndiName.lastIndexOf('/'));
+
+ String managerName = beanName.substring(0, beanName.length() - "Bean".length());
+
+ //we basically need to define a mock implementation of both the local and remote
+ //interface here - as if it were a proper SLSB.
+ RhqManager manager = Enum.valueOf(RhqManager.class, managerName);
+ Class<?> remoteIface = manager.remote();
+
+ String localIfaceName = remoteIface.getName().substring(0,
+ remoteIface.getName().length() - "Remote".length())
+ + "Local";
+ Class<?> localIface = Class.forName(localIfaceName);
+
+ return Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] { localIface,
+ remoteIface }, new InvocationHandler() {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ return null;
+ }
+ });
+ }
+ });
allowing(CONTEXT_MOCK_FOR_TEST).close();
}});
commit 910d79257e03273a2f43465c41e9690373630ccd
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Jun 20 12:25:57 2012 +0200
Resolve the initializer using the ScriptEngine.NAME parameter rather than
the language name - this is in line with how the different language support
modules identify themselves.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
index df78b41..fbaf1a7 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
@@ -216,7 +216,9 @@ public class ScriptEngineFactory {
return;
}
- ScriptEngineInitializer initializer = getInitializer(scriptEngine.getFactory().getLanguageName());
+ ScriptEngineInitializer initializer = getInitializer((String) scriptEngine.getFactory().getParameter(
+ ScriptEngine.NAME));
+
try {
BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass(), Object.class);
MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors();
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
index db22068..2742970 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
@@ -32,6 +32,8 @@ public interface ScriptEngineProvider {
/**
* @return the scripting language understood by this provider.
+ * This must return the same string as <code>ScriptEngine.getFactory().getParameter(ScriptEngine.NAME)</code>
+ * of the script engine that this provider provides (through the initializer).
*/
@NotNull
String getSupportedLanguage();
commit cdf864db43dc1c9908bdf157dd1eb283e05f5b14
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Jun 20 12:22:41 2012 +0200
Removing all the get*Manager() methods on the RhqFacade and replacing it
with one generic getProxy(Class) method. This method returns a proxy of
the original remote API interface (i.e. the interface is NOT simplified).
The getManagers() method returns a map of manager proxies where
the interfaces ARE simplified.
This is in preparation for making the simplified interfaces NOT implement
the original remote APIs so that we have greater freedom in what can be done
with the API and also make code completion significantly more clean and
simple.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
index 05e6a09..812b4ae 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
@@ -120,7 +120,7 @@ public class StandardBindings extends HashMap<String, Object> {
put(SCRIPT_UTIL, new ScriptUtil(rhqFacade));
if (rhqFacade != null) {
- managers = rhqFacade.getManagers();
+ managers = rhqFacade.getScriptingAPI();
put(SUBJECT, rhqFacade.getSubject());
put(PROXY_FACTORY, new ResourceClientFactory(rhqFacade, output));
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
index ef46bb2..bd37131 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
@@ -50,23 +50,31 @@ public abstract class AbstractRhqFacadeProxy<T extends RhqFacade> implements Inv
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- Class<?>[] params = method.getParameterTypes();
-
+ Class<?>[] interfaces = method.getDeclaringClass().getInterfaces();
+ Class<?> originalClass;
+ if (interfaces != null && interfaces.length > 0) {
+ originalClass = interfaces[0];
+ } else {
+ originalClass = method.getDeclaringClass();
+ }
+
try {
- Class<?>[] interfaces = method.getDeclaringClass().getInterfaces();
-
- Class<?> originalClass;
- if (interfaces != null && interfaces.length > 0) {
- originalClass = interfaces[0];
- } else {
- originalClass = method.getDeclaringClass();
- }
-
// See if this method really exists or if its a simplified set of parameters
originalClass.getMethod(method.getName(), method.getParameterTypes());
-
- } catch (Exception e) {
+ } catch (NoSuchMethodException e) {
// If this was not in the original interface it must've been added in the Simplifier... add back the subject argument
+ Class<?>[] origParams = method.getParameterTypes();
+ Class<?>[] params = new Class<?>[origParams.length + 1];
+ params[0] = Subject.class;
+ System.arraycopy(method.getParameterTypes(), 0, params, 1, origParams.length);
+
+ try {
+ method = originalClass.getMethod(method.getName(), params);
+ } catch (NoSuchMethodException e2) {
+ throw new IllegalArgumentException("Method " + method + " doesn't seem to be present on the interface "
+ + originalClass + " neither in its original or simplified form.");
+ }
+
int numArgs = (null == args) ? 0 : args.length;
Object[] newArgs = new Object[numArgs + 1];
if (numArgs > 0) {
@@ -74,17 +82,9 @@ public abstract class AbstractRhqFacadeProxy<T extends RhqFacade> implements Inv
}
newArgs[0] = getRhqFacade().getSubject();
args = newArgs;
-
- int numParams = (null == params) ? 0 : params.length;
- Class<?>[] newParams = new Class[numParams + 1];
- if (numParams > 0) {
- System.arraycopy(params, 0, newParams, 1, numParams);
- }
- newParams[0] = Subject.class;
- params = newParams;
}
- return doInvoke(proxy, method, params, args);
+ return doInvoke(proxy, method, args);
}
/**
@@ -93,10 +93,9 @@ public abstract class AbstractRhqFacadeProxy<T extends RhqFacade> implements Inv
*
* @param proxy the proxy the method is executing on
* @param originalMethod the original method
- * @param argTypes the de-simplified argument types
* @param args the de-simplified argumens
* @return the result of the invocation
* @throws Throwable if invocation throws an error
*/
- protected abstract Object doInvoke(Object proxy, Method originalMethod, Class<?>[] argTypes, Object[] args) throws Throwable;
+ protected abstract Object doInvoke(Object proxy, Method originalMethod, Object[] args) throws Throwable;
}
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
index ff39171..10ee612 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
@@ -67,7 +67,12 @@ import org.rhq.core.domain.util.PageOrdering;
import org.rhq.core.domain.util.Summary;
import org.rhq.core.server.MeasurementConverter;
import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
import org.rhq.enterprise.server.content.ContentManagerRemote;
+import org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote;
+import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote;
+import org.rhq.enterprise.server.operation.OperationManagerRemote;
+import org.rhq.enterprise.server.resource.ResourceManagerRemote;
import org.rhq.enterprise.server.resource.ResourceTypeNotFoundException;
/**
@@ -199,7 +204,8 @@ public class ResourceClientProxy {
public void init() {
- this.resource = remoteClient.getResourceManager().getResource(remoteClient.getSubject(), resourceId);
+ this.resource = remoteClient.getProxy(ResourceManagerRemote.class).getResource(remoteClient.getSubject(),
+ resourceId);
// Lazy init children, not here
initMeasurements();
@@ -217,10 +223,11 @@ public class ResourceClientProxy {
}
private void initConfigDefs() {
- this.resourceConfigurationDefinition = remoteClient.getConfigurationManager()
+ ConfigurationManagerRemote configurationManager = remoteClient.getProxy(ConfigurationManagerRemote.class);
+ this.resourceConfigurationDefinition = configurationManager
.getResourceConfigurationDefinitionWithTemplatesForResourceType(remoteClient.getSubject(),
resource.getResourceType().getId());
- this.pluginConfigurationDefinition = remoteClient.getConfigurationManager()
+ this.pluginConfigurationDefinition = configurationManager
.getPluginConfigurationDefinitionForResourceType(remoteClient.getSubject(),
resource.getResourceType().getId());
}
@@ -228,7 +235,7 @@ public class ResourceClientProxy {
private void initChildren() {
ResourceCriteria criteria = new ResourceCriteria();
criteria.addFilterParentResourceId(resourceId);
- PageList<Resource> childResources = remoteClient.getResourceManager().findResourcesByCriteria(
+ PageList<Resource> childResources = remoteClient.getProxy(ResourceManagerRemote.class).findResourcesByCriteria(
remoteClient.getSubject(), criteria);
for (Resource child : childResources) {
@@ -242,7 +249,7 @@ public class ResourceClientProxy {
// criteria.addFilterResourceTypeName(resource.getResourceType().getName());
// criteria.setStrict(true);
- this.measurementDefinitions = remoteClient.getMeasurementDefinitionManager()
+ this.measurementDefinitions = remoteClient.getProxy(MeasurementDefinitionManagerRemote.class)
.findMeasurementDefinitionsByCriteria(remoteClient.getSubject(), criteria);
this.measurementMap = new HashMap<String, Measurement>();
@@ -263,7 +270,8 @@ public class ResourceClientProxy {
criteria.fetchParametersConfigurationDefinition(true);
criteria.fetchResultsConfigurationDefinition(true);
- this.operationDefinitions = remoteClient.getOperationManager().findOperationDefinitionsByCriteria(
+ this.operationDefinitions = remoteClient.getProxy(OperationManagerRemote.class)
+ .findOperationDefinitionsByCriteria(
remoteClient.getSubject(), criteria);
for (OperationDefinition def : operationDefinitions) {
@@ -274,7 +282,7 @@ public class ResourceClientProxy {
}
private void initContent() {
- ContentManagerRemote contentManager = remoteClient.getContentManager();
+ ContentManagerRemote contentManager = remoteClient.getProxy(ContentManagerRemote.class);
List<PackageType> types = null;
try {
types = contentManager.findPackageTypes(remoteClient.getSubject(), resource.getResourceType().getName(),
@@ -302,7 +310,7 @@ public class ResourceClientProxy {
}
public List<PackageVersion> getInstalledPackages() {
- ContentManagerRemote contentManager = remoteClient.getContentManager();
+ ContentManagerRemote contentManager = remoteClient.getProxy(ContentManagerRemote.class);
PackageVersionCriteria criteria = new PackageVersionCriteria();
criteria.addFilterResourceId(resourceId);
@@ -359,7 +367,7 @@ public class ResourceClientProxy {
public Object getValue() {
try {
- Set<MeasurementData> d = remoteClient.getMeasurementDataManager().findLiveData(
+ Set<MeasurementData> d = remoteClient.getProxy(MeasurementDataManagerRemote.class).findLiveData(
remoteClient.getSubject(), resourceId, new int[] { definition.getId() });
MeasurementData data = d.iterator().next();
return data.getValue();
@@ -404,7 +412,9 @@ public class ResourceClientProxy {
Configuration parameters = ConfigurationClassBuilder.translateParametersToConfig(definition
.getParametersConfigurationDefinition(), args);
- ResourceOperationSchedule schedule = remoteClient.getOperationManager().scheduleResourceOperation(
+ OperationManagerRemote operationManager = remoteClient.getProxy(OperationManagerRemote.class);
+
+ ResourceOperationSchedule schedule = operationManager.scheduleResourceOperation(
remoteClient.getSubject(), resourceId, definition.getName(), 0, 0, 0, 30000, parameters,
"Executed from commandline");
@@ -421,7 +431,7 @@ public class ResourceClientProxy {
ResourceOperationHistory history = null;
while (history == null && retries-- > 0) {
Thread.sleep(1000);
- PageList<ResourceOperationHistory> histories = remoteClient.getOperationManager()
+ PageList<ResourceOperationHistory> histories = operationManager
.findResourceOperationHistoriesByCriteria(remoteClient.getSubject(), criteria);
if (histories.size() > 0 && histories.get(0).getStatus() != OperationRequestStatus.INPROGRESS) {
history = histories.get(0);
@@ -459,7 +469,8 @@ public class ResourceClientProxy {
public Configuration getPluginConfiguration() {
if (!LazyLoadScenario.isShouldLoad())
return null;
- return remoteClient.getConfigurationManager().getPluginConfiguration(remoteClient.getSubject(),
+ return remoteClient.getProxy(ConfigurationManagerRemote.class).getPluginConfiguration(
+ remoteClient.getSubject(),
resourceClientProxy.resourceId);
}
@@ -468,8 +479,8 @@ public class ResourceClientProxy {
}
public PluginConfigurationUpdate updatePluginConfiguration(Configuration configuration) {
- PluginConfigurationUpdate update =
- remoteClient.getConfigurationManager().updatePluginConfiguration(
+ PluginConfigurationUpdate update = remoteClient.getProxy(ConfigurationManagerRemote.class)
+ .updatePluginConfiguration(
remoteClient.getSubject(),
resourceClientProxy.getId(),
configuration);
@@ -481,7 +492,8 @@ public class ResourceClientProxy {
if (!LazyLoadScenario.isShouldLoad())
return null;
- return remoteClient.getConfigurationManager().getResourceConfiguration(remoteClient.getSubject(),
+ return remoteClient.getProxy(ConfigurationManagerRemote.class).getResourceConfiguration(
+ remoteClient.getSubject(),
resourceClientProxy.resourceId);
}
@@ -490,8 +502,8 @@ public class ResourceClientProxy {
}
public ResourceConfigurationUpdate updateResourceConfiguration(Configuration configuration) {
- ResourceConfigurationUpdate update =
- remoteClient.getConfigurationManager().updateResourceConfiguration(
+ ResourceConfigurationUpdate update = remoteClient.getProxy(ConfigurationManagerRemote.class)
+ .updateResourceConfiguration(
remoteClient.getSubject(),
resourceClientProxy.getId(),
configuration);
@@ -502,7 +514,8 @@ public class ResourceClientProxy {
public InstalledPackage getBackingContent() {
- return remoteClient.getContentManager().getBackingPackageForResource(remoteClient.getSubject(), resourceClientProxy.resourceId);
+ return remoteClient.getProxy(ContentManagerRemote.class).getBackingPackageForResource(
+ remoteClient.getSubject(), resourceClientProxy.resourceId);
}
/**
@@ -538,8 +551,9 @@ public class ResourceClientProxy {
InstalledPackage oldPackage = getBackingContent();
- PackageVersion pv =
- remoteClient.getContentManager().createPackageVersionWithDisplayVersion(
+ ContentManagerRemote contentManager = remoteClient.getProxy(ContentManagerRemote.class);
+
+ PackageVersion pv = contentManager.createPackageVersionWithDisplayVersion(
remoteClient.getSubject(),
oldPackage.getPackageVersion().getGeneralPackage().getName(),
oldPackage.getPackageVersion().getGeneralPackage().getPackageType().getId(),
@@ -548,7 +562,7 @@ public class ResourceClientProxy {
oldPackage.getPackageVersion().getArchitecture().getId(),
fileContents);
- remoteClient.getContentManager().deployPackagesWithNote(
+ contentManager.deployPackagesWithNote(
remoteClient.getSubject(),
new int[] { resourceClientProxy.getId()},
new int[] {pv.getId()},
@@ -564,8 +578,7 @@ public class ResourceClientProxy {
File file = new File(fileName);
- byte[] data =
- remoteClient.getContentManager().getPackageBytes(
+ byte[] data = remoteClient.getProxy(ContentManagerRemote.class).getPackageBytes(
remoteClient.getSubject(), resourceClientProxy.resourceId, installedPackage.getId());
FileOutputStream fos = new FileOutputStream(file);
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
index ca7fa83..b975436 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
@@ -22,35 +22,6 @@ package org.rhq.bindings.client;
import java.util.Map;
import org.rhq.core.domain.auth.Subject;
-import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
-import org.rhq.enterprise.server.alert.AlertManagerRemote;
-import org.rhq.enterprise.server.auth.SubjectManagerRemote;
-import org.rhq.enterprise.server.authz.RoleManagerRemote;
-import org.rhq.enterprise.server.bundle.BundleManagerRemote;
-import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
-import org.rhq.enterprise.server.content.ContentManagerRemote;
-import org.rhq.enterprise.server.content.RepoManagerRemote;
-import org.rhq.enterprise.server.discovery.DiscoveryBossRemote;
-import org.rhq.enterprise.server.drift.DriftManagerRemote;
-import org.rhq.enterprise.server.event.EventManagerRemote;
-import org.rhq.enterprise.server.install.remote.RemoteInstallManagerRemote;
-import org.rhq.enterprise.server.measurement.AvailabilityManagerRemote;
-import org.rhq.enterprise.server.measurement.CallTimeDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementBaselineManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerRemote;
-import org.rhq.enterprise.server.operation.OperationManagerRemote;
-import org.rhq.enterprise.server.report.DataAccessManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceFactoryManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceTypeManagerRemote;
-import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
-import org.rhq.enterprise.server.search.SavedSearchManagerRemote;
-import org.rhq.enterprise.server.support.SupportManagerRemote;
-import org.rhq.enterprise.server.sync.SynchronizationManagerRemote;
-import org.rhq.enterprise.server.system.SystemManagerRemote;
-import org.rhq.enterprise.server.tagging.TagManagerRemote;
/**
* This is an interface through which the script can communicate with RHQ server.
@@ -70,69 +41,22 @@ public interface RhqFacade {
boolean isLoggedIn();
- AlertManagerRemote getAlertManager();
-
- AlertDefinitionManagerRemote getAlertDefinitionManager();
-
- AvailabilityManagerRemote getAvailabilityManager();
-
- BundleManagerRemote getBundleManager();
-
- CallTimeDataManagerRemote getCallTimeDataManager();
-
- RepoManagerRemote getRepoManager();
-
- ConfigurationManagerRemote getConfigurationManager();
-
- ContentManagerRemote getContentManager();
-
- DataAccessManagerRemote getDataAccessManager();
-
- DiscoveryBossRemote getDiscoveryBoss();
-
- DriftManagerRemote getDriftManager();
-
- EventManagerRemote getEventManager();
-
- MeasurementBaselineManagerRemote getMeasurementBaselineManager();
-
- MeasurementDataManagerRemote getMeasurementDataManager();
-
- MeasurementDefinitionManagerRemote getMeasurementDefinitionManager();
-
- MeasurementScheduleManagerRemote getMeasurementScheduleManager();
-
- OperationManagerRemote getOperationManager();
-
- ResourceManagerRemote getResourceManager();
-
- ResourceFactoryManagerRemote getResourceFactoryManager();
-
- ResourceGroupManagerRemote getResourceGroupManager();
-
- ResourceTypeManagerRemote getResourceTypeManager();
-
- RoleManagerRemote getRoleManager();
-
- SavedSearchManagerRemote getSavedSearchManager();
-
- SubjectManagerRemote getSubjectManager();
-
- SupportManagerRemote getSupportManager();
-
- SystemManagerRemote getSystemManager();
-
- RemoteInstallManagerRemote getRemoteInstallManager();
-
- TagManagerRemote getTagManager();
-
- SynchronizationManagerRemote getSynchronizationManager();
-
/**
* This map is constructed using all the elements in the {@link RhqManager} enum which are then proxied
* using this instance.
*
* @return a map of all available proxied managers keyed by their names.
*/
- Map<String, Object> getManagers();
+ Map<String, Object> getScriptingAPI();
+
+ /**
+ * Unlike the {@link #getScriptingAPI()} method that returns objects with modified signatures
+ * meant to be used by the scripting environment, this method provides the access to the "raw"
+ * remote API interface implementation backed by this RHQ facade implementation.
+ *
+ * @param remoteApiIface one of the RHQ's remote API interfaces of which the proxied instance
+ * should be returned
+ * @return the proxy of the remote API interface backed by this facade
+ */
+ <T> T getProxy(Class<T> remoteApiIface);
}
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptAssert.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptAssert.java
index 15ed37c..a268621 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptAssert.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptAssert.java
@@ -245,20 +245,30 @@ public class ScriptAssert {
}
}
- public void assertEquals(Object[] actual, Object[] expected, String msg) {
- if (actual == expected) {
- return;
- }
+ /* These are no longer needed in Rhino 1.7R3, because native javascript arrays implement
+ * the collection interfaces.
+ */
+ /*
+ public void assertEquals(Object[] actual, Object[] expected, String msg) {
+ if (actual == expected) {
+ return;
+ }
- if ((actual == null && expected != null) || (actual != null && expected == null)) {
- if (msg != null) {
- fail(msg);
- } else {
- fail("Arrays not equal: " + Arrays.toString(expected) + " and " + Arrays.toString(actual));
+ if ((actual == null && expected != null) || (actual != null && expected == null)) {
+ if (msg != null) {
+ fail(msg);
+ } else {
+ fail("Arrays not equal: " + Arrays.toString(expected) + " and " + Arrays.toString(actual));
+ }
}
+ assertEquals(Arrays.asList(actual), Arrays.asList(expected), msg);
+ }
+
+ public void assertEquals(Object[] actual, Object[] expected) {
+ assertEquals(actual, expected, null);
}
- assertEquals(Arrays.asList(actual), Arrays.asList(expected), msg);
- }
+
+ */
public void assertEqualsNoOrder(Object[] actual, Object[] expected, String msg) {
if (actual == expected) {
@@ -288,10 +298,6 @@ public class ScriptAssert {
}
}
- public void assertEquals(Object[] actual, Object[] expected) {
- assertEquals(actual, expected, null);
- }
-
public void assertEqualsNoOrder(Object[] actual, Object[] expected) {
assertEqualsNoOrder(actual, expected, null);
}
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptUtil.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptUtil.java
index 6ed095e..bd121e7 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptUtil.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptUtil.java
@@ -43,6 +43,7 @@ import org.rhq.core.domain.operation.bean.ResourceOperationSchedule;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.PageOrdering;
+import org.rhq.enterprise.server.operation.OperationManagerRemote;
import org.rhq.enterprise.server.resource.ResourceManagerRemote;
/**
@@ -74,7 +75,7 @@ public class ScriptUtil {
throw new IllegalStateException("The findResources() method requires a connection to the RHQ server.");
}
- ResourceManagerRemote resourceManager = remoteClient.getResourceManager();
+ ResourceManagerRemote resourceManager = remoteClient.getProxy(ResourceManagerRemote.class);
ResourceCriteria criteria = new ResourceCriteria();
criteria.addFilterName(string);
@@ -166,7 +167,7 @@ public class ScriptUtil {
while(history == null && i < maxIntervals) {
Thread.sleep(intervalDuration);
- PageList<ResourceOperationHistory> histories = remoteClient.getOperationManager()
+ PageList<ResourceOperationHistory> histories = remoteClient.getProxy(OperationManagerRemote.class)
.findResourceOperationHistoriesByCriteria(remoteClient.getSubject(), criteria);
if (histories.size() > 0 && histories.get(0).getStatus() != OperationRequestStatus.INPROGRESS) {
history = histories.get(0);
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java
index a3dcbdc..d42f3e1 100644
--- a/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java
@@ -24,35 +24,6 @@ import java.util.Map;
import org.rhq.bindings.client.RhqFacade;
import org.rhq.core.domain.auth.Subject;
-import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
-import org.rhq.enterprise.server.alert.AlertManagerRemote;
-import org.rhq.enterprise.server.auth.SubjectManagerRemote;
-import org.rhq.enterprise.server.authz.RoleManagerRemote;
-import org.rhq.enterprise.server.bundle.BundleManagerRemote;
-import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
-import org.rhq.enterprise.server.content.ContentManagerRemote;
-import org.rhq.enterprise.server.content.RepoManagerRemote;
-import org.rhq.enterprise.server.discovery.DiscoveryBossRemote;
-import org.rhq.enterprise.server.drift.DriftManagerRemote;
-import org.rhq.enterprise.server.event.EventManagerRemote;
-import org.rhq.enterprise.server.install.remote.RemoteInstallManagerRemote;
-import org.rhq.enterprise.server.measurement.AvailabilityManagerRemote;
-import org.rhq.enterprise.server.measurement.CallTimeDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementBaselineManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerRemote;
-import org.rhq.enterprise.server.operation.OperationManagerRemote;
-import org.rhq.enterprise.server.report.DataAccessManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceFactoryManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceTypeManagerRemote;
-import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
-import org.rhq.enterprise.server.search.SavedSearchManagerRemote;
-import org.rhq.enterprise.server.support.SupportManagerRemote;
-import org.rhq.enterprise.server.sync.SynchronizationManagerRemote;
-import org.rhq.enterprise.server.system.SystemManagerRemote;
-import org.rhq.enterprise.server.tagging.TagManagerRemote;
public class FakeRhqFacade implements RhqFacade {
@@ -71,127 +42,13 @@ public class FakeRhqFacade implements RhqFacade {
public boolean isLoggedIn() {
return false;
}
-
- public AlertManagerRemote getAlertManager() {
- return null;
- }
-
- public AlertDefinitionManagerRemote getAlertDefinitionManager() {
- return null;
- }
-
- public AvailabilityManagerRemote getAvailabilityManager() {
- return null;
- }
-
- public BundleManagerRemote getBundleManager() {
- return null;
- }
-
- public CallTimeDataManagerRemote getCallTimeDataManager() {
- return null;
- }
-
- public RepoManagerRemote getRepoManager() {
- return null;
- }
-
- public ConfigurationManagerRemote getConfigurationManager() {
- return null;
- }
-
- public ContentManagerRemote getContentManager() {
- return null;
- }
-
- public DataAccessManagerRemote getDataAccessManager() {
- return null;
- }
-
- public DiscoveryBossRemote getDiscoveryBoss() {
- return null;
- }
-
- public EventManagerRemote getEventManager() {
- return null;
- }
-
- public MeasurementBaselineManagerRemote getMeasurementBaselineManager() {
- return null;
- }
-
- public MeasurementDataManagerRemote getMeasurementDataManager() {
- return null;
- }
-
- public MeasurementDefinitionManagerRemote getMeasurementDefinitionManager() {
- return null;
- }
-
- public MeasurementScheduleManagerRemote getMeasurementScheduleManager() {
- return null;
- }
-
- public OperationManagerRemote getOperationManager() {
- return null;
- }
-
- public ResourceManagerRemote getResourceManager() {
- return null;
- }
-
- public ResourceFactoryManagerRemote getResourceFactoryManager() {
- return null;
- }
-
- public ResourceGroupManagerRemote getResourceGroupManager() {
- return null;
- }
-
- public ResourceTypeManagerRemote getResourceTypeManager() {
- return null;
- }
-
- public RoleManagerRemote getRoleManager() {
- return null;
- }
-
- public SavedSearchManagerRemote getSavedSearchManager() {
- return null;
- }
-
- public SubjectManagerRemote getSubjectManager() {
- return null;
- }
-
- public SupportManagerRemote getSupportManager() {
- return null;
- }
-
- public SystemManagerRemote getSystemManager() {
- return null;
- }
-
- public RemoteInstallManagerRemote getRemoteInstallManager() {
- return null;
- }
-
- public TagManagerRemote getTagManager() {
- return null;
- }
-
- @Override
- public DriftManagerRemote getDriftManager() {
- return null;
+
+ public Map<String, Object> getScriptingAPI() {
+ return Collections.emptyMap();
}
@Override
- public SynchronizationManagerRemote getSynchronizationManager() {
+ public <T> T getProxy(Class<T> remoteApiIface) {
return null;
}
-
- public Map<String, Object> getManagers() {
- return Collections.emptyMap();
- }
-
}
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java
index 15184c1..c3d5450 100644
--- a/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java
@@ -86,11 +86,13 @@ public class ScriptEngineTest {
}
private ScriptEngine getScriptEngine() throws ScriptException, IOException {
- return ScriptEngineFactory.getScriptEngine("JavaScript", new PackageFinder(Collections.<File>emptyList()), EMPTY_BINDINGS);
+ return ScriptEngineFactory.getScriptEngine("javascript", new PackageFinder(Collections.<File> emptyList()),
+ EMPTY_BINDINGS);
}
private ScriptEngine getSecuredScriptEngine() throws ScriptException, IOException {
- return ScriptEngineFactory.getSecuredScriptEngine("JavaScript", new PackageFinder(Collections.<File>emptyList()), EMPTY_BINDINGS, new StandardScriptPermissions());
+ return ScriptEngineFactory.getSecuredScriptEngine("javascript",
+ new PackageFinder(Collections.<File> emptyList()), EMPTY_BINDINGS, new StandardScriptPermissions());
}
private void assertSecurityExceptionPresent(Throwable t) {
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java
index 8fed153..1d7f657 100644
--- a/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java
@@ -46,8 +46,7 @@ public class ScriptAssertTest {
@BeforeTest
public void verifyScriptEngineIsAvailable() throws Exception {
StandardBindings bindings = new StandardBindings(new PrintWriter(System.out), new FakeRhqFacade());
- engine =
- ScriptEngineFactory.getScriptEngine("JavaScript", new PackageFinder(Collections.<File> emptyList()),
+ engine = ScriptEngineFactory.getScriptEngine("javascript", new PackageFinder(Collections.<File> emptyList()),
bindings);
}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index 4a1ed62..9811d2a 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@ -203,7 +203,7 @@ public class ClientMain {
this.serviceCompletor.setContext(getScriptEngine().getContext());
if (remoteClient != null) {
- this.serviceCompletor.setServices(remoteClient.getManagers());
+ this.serviceCompletor.setServices(remoteClient.getScriptingAPI());
}
}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java
index 4676730..69b3c7a 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java
@@ -61,7 +61,7 @@ public class HelpCommand implements ClientCommand {
tw.setHideRowCount(true);
tw.print(data);
} else if ("api".equals(args[1])) {
- Map<String, Object> services = client.getRemoteClient().getManagers();
+ Map<String, Object> services = client.getRemoteClient().getScriptingAPI();
if (args.length == 2) {
TabularWriter tw = new TabularWriter(client.getPrintWriter(), "API", "Package");
tw.setWidth(client.getConsoleWidth());
diff --git a/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java b/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
index fc59cf3..8cf3ceb 100644
--- a/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
+++ b/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
@@ -1,36 +1,23 @@
package org.rhq.enterprise.client.commands;
-import static java.util.Collections.*;
import static java.util.Arrays.asList;
-import static org.testng.Assert.*;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
-import java.util.Map;
-import java.util.Collections;
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
+
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
import org.testng.annotations.Test;
-import org.rhq.enterprise.client.ClientMain;
-import org.rhq.enterprise.client.commands.ScriptCommand;
-import org.rhq.enterprise.clientapi.RemoteClient;
-import org.rhq.enterprise.server.alert.AlertManagerRemote;
-import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
-import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
-import org.rhq.enterprise.server.content.RepoManagerRemote;
-import org.rhq.enterprise.server.content.ContentManagerRemote;
-import org.rhq.enterprise.server.operation.OperationManagerRemote;
-import org.rhq.enterprise.server.authz.RoleManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceManagerRemote;
-import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
-import org.rhq.enterprise.server.auth.SubjectManagerRemote;
+
import org.rhq.bindings.client.RhqManager;
import org.rhq.bindings.output.TabularWriter;
import org.rhq.bindings.util.ScriptUtil;
import org.rhq.core.domain.auth.Subject;
-
-import javax.script.ScriptEngine;
-import javax.script.ScriptContext;
-import javax.script.Bindings;
+import org.rhq.enterprise.client.ClientMain;
+import org.rhq.enterprise.clientapi.RemoteClient;
public class ScriptCommandTest {
@@ -122,56 +109,6 @@ public class ScriptCommandTest {
public RemoteClientStub(String host, int port) {
super(host, port);
}
-
- @Override
- public AlertManagerRemote getAlertManager() {
- return null;
- }
-
- @Override
- public AlertDefinitionManagerRemote getAlertDefinitionManager() {
- return null;
- }
-
- @Override
- public ConfigurationManagerRemote getConfigurationManager() {
- return null;
- }
-
- @Override
- public RepoManagerRemote getRepoManager() {
- return null;
- }
-
- @Override
- public ContentManagerRemote getContentManager() {
- return null;
- }
-
- @Override
- public OperationManagerRemote getOperationManager() {
- return null;
- }
-
- @Override
- public RoleManagerRemote getRoleManager() {
- return null;
- }
-
- @Override
- public ResourceManagerRemote getResourceManager() {
- return null;
- }
-
- @Override
- public ResourceGroupManagerRemote getResourceGroupManager() {
- return null;
- }
-
- @Override
- public SubjectManagerRemote getSubjectManager() {
- return null;
- }
}
}
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
index 57829b9..4ea3267 100644
--- a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
@@ -19,6 +19,7 @@
package org.rhq.enterprise.clientapi;
import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
@@ -28,44 +29,18 @@ import org.apache.maven.artifact.versioning.ComparableVersion;
import org.jboss.remoting.Client;
import org.jboss.remoting.InvokerLocator;
+import org.jboss.remoting.invocation.NameBasedInvocation;
import org.jboss.remoting.security.SSLSocketBuilder;
import org.jboss.remoting.transport.http.ssl.HTTPSClientInvoker;
import org.rhq.bindings.client.RhqFacade;
import org.rhq.bindings.client.RhqManager;
+import org.rhq.bindings.util.InterfaceSimplifier;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.common.ProductInfo;
import org.rhq.enterprise.communications.util.SecurityUtil;
-import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
-import org.rhq.enterprise.server.alert.AlertManagerRemote;
import org.rhq.enterprise.server.auth.SubjectManagerRemote;
-import org.rhq.enterprise.server.authz.RoleManagerRemote;
-import org.rhq.enterprise.server.bundle.BundleManagerRemote;
-import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
-import org.rhq.enterprise.server.content.ContentManagerRemote;
-import org.rhq.enterprise.server.content.RepoManagerRemote;
-import org.rhq.enterprise.server.discovery.DiscoveryBossRemote;
-import org.rhq.enterprise.server.drift.DriftManagerRemote;
-import org.rhq.enterprise.server.drift.DriftTemplateManagerRemote;
-import org.rhq.enterprise.server.event.EventManagerRemote;
-import org.rhq.enterprise.server.install.remote.RemoteInstallManagerRemote;
-import org.rhq.enterprise.server.measurement.AvailabilityManagerRemote;
-import org.rhq.enterprise.server.measurement.CallTimeDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementBaselineManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerRemote;
-import org.rhq.enterprise.server.operation.OperationManagerRemote;
-import org.rhq.enterprise.server.report.DataAccessManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceFactoryManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceTypeManagerRemote;
-import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
-import org.rhq.enterprise.server.search.SavedSearchManagerRemote;
-import org.rhq.enterprise.server.support.SupportManagerRemote;
-import org.rhq.enterprise.server.sync.SynchronizationManagerRemote;
import org.rhq.enterprise.server.system.SystemManagerRemote;
-import org.rhq.enterprise.server.tagging.TagManagerRemote;
/**
* A remote access client that provides transparent servlet-based proxies to an RHQ Server.
@@ -127,6 +102,29 @@ public class RemoteClient implements RhqFacade {
this.subsystem = subsystem;
}
+ public <T> T remoteInvoke(RhqManager manager, Method method, Class<T> expectedReturnType, Object... parameters)
+ throws Throwable {
+
+ String methodSig = manager.beanName() + ":" + method.getName();
+
+ Class<?>[] paramTypes = method.getParameterTypes();
+ String[] paramSig = new String[paramTypes.length];
+ for (int x = 0; x < paramTypes.length; x++) {
+ paramSig[x] = paramTypes[x].getName();
+ }
+
+ NameBasedInvocation request = new NameBasedInvocation(methodSig, parameters, paramSig);
+
+ Object response = getRemotingClient().invoke(request);
+
+ if (response instanceof Throwable) {
+ throw (Throwable) response;
+ }
+
+ return response == null ? null : expectedReturnType.cast(response);
+
+ }
+
/**
* Connects to the remote server and logs in with the given credentials.
* After successfully executing this, {@link #isLoggedIn()} will be <code>true</code>
@@ -144,7 +142,16 @@ public class RemoteClient implements RhqFacade {
logout();
doConnect();
- this.subject = getSubjectManager().login(user, password);
+ Method loginMethod = SubjectManagerRemote.class.getDeclaredMethod("login", String.class, String.class);
+
+ try {
+ this.subject = remoteInvoke(RhqManager.SubjectManager, loginMethod, Subject.class, user, password);
+ } catch (Exception e) {
+ throw e;
+ } catch (Throwable e) {
+ throw new Exception("Failed to login due to a throwable of type " + e.getClass().getName(), e);
+ }
+
this.loggedIn = true;
return this.subject;
@@ -154,12 +161,16 @@ public class RemoteClient implements RhqFacade {
* Logs out from the server and disconnects this client.
*/
public void logout() {
- try {
- if (this.loggedIn && this.subject != null) {
- getSubjectManager().logout(this.subject);
+ if (this.loggedIn && this.subject != null) {
+ try {
+ Method logoutMethod = SubjectManagerRemote.class.getDeclaredMethod("logout", Subject.class);
+ remoteInvoke(RhqManager.SubjectManager, logoutMethod, Void.class, this.subject);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException(
+ "Couldn't find the logout method on the SubjectManagerRemote interface.", e);
+ } catch (Throwable e) {
+ // just keep going so we can disconnect this client
}
- } catch (Exception e) {
- // just keep going so we can disconnect this client
}
doDisconnect();
@@ -260,145 +271,25 @@ public class RemoteClient implements RhqFacade {
this.transport = transport;
}
- public AlertManagerRemote getAlertManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.AlertManager);
- }
-
- public AlertDefinitionManagerRemote getAlertDefinitionManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.AlertDefinitionManager);
- }
-
- public AvailabilityManagerRemote getAvailabilityManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.AvailabilityManager);
- }
-
- public BundleManagerRemote getBundleManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.BundleManager);
- }
-
- public CallTimeDataManagerRemote getCallTimeDataManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.CallTimeDataManager);
- }
-
- public DriftManagerRemote getDriftManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.DriftManager);
- }
-
- public DriftTemplateManagerRemote getDriftTemplateManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.DriftTemplateManager);
- }
-
- public RepoManagerRemote getRepoManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.RepoManager);
- }
-
- public ConfigurationManagerRemote getConfigurationManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.ConfigurationManager);
- }
-
- public ContentManagerRemote getContentManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.ContentManager);
- }
-
- public DataAccessManagerRemote getDataAccessManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.DataAccessManager);
- }
-
- public DiscoveryBossRemote getDiscoveryBoss() {
- return RemoteClientProxy.getProcessor(this, RhqManager.DiscoveryBoss);
- }
-
- public EventManagerRemote getEventManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.EventManager);
- }
-
- public MeasurementBaselineManagerRemote getMeasurementBaselineManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementBaselineManager);
- }
-
- public MeasurementDataManagerRemote getMeasurementDataManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementDataManager);
- }
-
- public MeasurementDefinitionManagerRemote getMeasurementDefinitionManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementDefinitionManager);
- }
-
- public MeasurementScheduleManagerRemote getMeasurementScheduleManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementScheduleManager);
- }
-
- public OperationManagerRemote getOperationManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.OperationManager);
- }
-
- public ResourceManagerRemote getResourceManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.ResourceManager);
- }
-
- public ResourceFactoryManagerRemote getResourceFactoryManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.ResourceFactoryManager);
- }
-
- public ResourceGroupManagerRemote getResourceGroupManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.ResourceGroupManager);
- }
-
- public ResourceTypeManagerRemote getResourceTypeManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.ResourceTypeManager);
- }
-
- public RoleManagerRemote getRoleManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.RoleManager);
- }
-
- public SavedSearchManagerRemote getSavedSearchManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.SavedSearchManager);
- }
-
- public SubjectManagerRemote getSubjectManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.SubjectManager);
- }
-
- public SupportManagerRemote getSupportManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.SupportManager);
- }
-
- public SystemManagerRemote getSystemManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.SystemManager);
- }
-
- public RemoteInstallManagerRemote getRemoteInstallManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.RemoteInstallManager);
- }
-
- public TagManagerRemote getTagManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.TagManager);
- }
-
- public SynchronizationManagerRemote getSynchronizationManager() {
- return RemoteClientProxy.getProcessor(this, RhqManager.SynchronizationManager);
- }
-
/**
* Returns the map of all remote managers running in the server that this
* client can talk to.
*
* @return Map K=manager name V=remote proxy
*/
- public Map<String, Object> getManagers() {
+ public Map<String, Object> getScriptingAPI() {
if (this.managers == null) {
this.managers = new HashMap<String, Object>();
for (RhqManager manager : RhqManager.values()) {
- try {
- Method m = this.getClass().getMethod("get" + manager.name());
- if (manager.enabled()) {
- this.managers.put(manager.name(), m.invoke(this));
+ if (manager.enabled()) {
+ try {
+ Object proxy = getProcessor(this, manager, true);
+ this.managers.put(manager.name(), proxy);
+ } catch (Throwable e) {
+ LOG.error("Failed to load manager " + manager + " due to missing class.", e);
}
- } catch (Throwable e) {
- LOG.error("Failed to load manager " + manager + " due to missing class.", e);
}
}
}
@@ -407,6 +298,17 @@ public class RemoteClient implements RhqFacade {
}
@Override
+ public <T> T getProxy(Class<T> remoteApiIface) {
+ RhqManager manager = RhqManager.forInterface(remoteApiIface);
+
+ if (manager == null) {
+ throw new IllegalArgumentException("Unknown remote interface " + remoteApiIface);
+ }
+
+ return getProcessor(this, manager, false);
+ }
+
+ @Override
public String toString() {
return this.getClass().getSimpleName() + "[" + "transport=" + transport + ", host=" + host + ", port=" + port
+ ", subsystem=" + subsystem + ", connected=" + connected + ", loggedIn=" + loggedIn + ", subject="
@@ -443,6 +345,20 @@ public class RemoteClient implements RhqFacade {
return (this.serverInfo != null) ? this.serverInfo.getBuildNumber() : null;
}
+ @SuppressWarnings("unchecked")
+ private static <T> T getProcessor(RemoteClient remoteClient, RhqManager manager, boolean simplify) {
+ try {
+ RemoteClientProxy gpc = new RemoteClientProxy(remoteClient, manager);
+
+ Class<?> intf = simplify ? InterfaceSimplifier.simplify(manager.remote()) : manager.remote();
+
+ return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] { intf },
+ gpc);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to get remote connection proxy", e);
+ }
+ }
+
private void doDisconnect() {
try {
if (this.remotingClient != null && this.remotingClient.isConnected()) {
@@ -470,13 +386,21 @@ public class RemoteClient implements RhqFacade {
this.remotingClient.connect();
// make sure the remote server can support this client
- this.serverInfo = getSystemManager().getProductInfo(subject);
try {
+ Method getProductInfoMethod = SystemManagerRemote.class.getDeclaredMethod("getProductInfo", Subject.class);
+
+ this.serverInfo = remoteInvoke(RhqManager.SystemManager, getProductInfoMethod, ProductInfo.class,
+ this.subject);
checkServerSupported(this.serverInfo);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException("Could not find the getProductInfo(Subject) method on the SystemManager.",
+ e);
} catch (Exception e) {
// our client cannot be supported by the server - disconnect and rethrow the exception
doDisconnect();
throw e;
+ } catch (Throwable e) {
+ throw new IllegalStateException("Unknown error occured during connect.", e);
}
}
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java
index 23dea3c..a6b04f1 100644
--- a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java
@@ -19,16 +19,12 @@
package org.rhq.enterprise.clientapi;
import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.jboss.remoting.invocation.NameBasedInvocation;
-
import org.rhq.bindings.client.AbstractRhqFacadeProxy;
import org.rhq.bindings.client.RhqManager;
-import org.rhq.bindings.util.InterfaceSimplifier;
import org.rhq.core.domain.server.ExternalizableStrategy;
/**
@@ -46,24 +42,11 @@ public class RemoteClientProxy extends AbstractRhqFacadeProxy<RemoteClient> {
super(client, manager);
}
+ @Deprecated
public Class<?> getRemoteInterface() {
return this.getManager().remote();
}
- @SuppressWarnings("unchecked")
- public static <T> T getProcessor(RemoteClient remoteClient, RhqManager manager) {
- try {
- RemoteClientProxy gpc = new RemoteClientProxy(remoteClient, manager);
-
- Class<?> intf = InterfaceSimplifier.simplify(manager.remote());
-
- return (T) Proxy
- .newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] { intf }, gpc);
- } catch (Exception e) {
- throw new RuntimeException("Failed to get remote connection proxy", e);
- }
- }
-
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
return super.invoke(proxy, method, args);
@@ -73,29 +56,9 @@ public class RemoteClientProxy extends AbstractRhqFacadeProxy<RemoteClient> {
}
}
- protected Object doInvoke(Object proxy, Method originalMethod, java.lang.Class<?>[] argTypes, Object[] args) throws Throwable {
+ protected Object doInvoke(Object proxy, Method originalMethod, Object[] args) throws Throwable {
ExternalizableStrategy.setStrategy(ExternalizableStrategy.Subsystem.REFLECTIVE_SERIALIZATION);
- String methodName = getManager().beanName() + ":" + originalMethod.getName();
-
- String[] paramSig = createParamSignature(argTypes);
-
- NameBasedInvocation request = new NameBasedInvocation(methodName, args, paramSig);
-
- Object response = getRhqFacade().getRemotingClient().invoke(request);
-
- if (response instanceof Throwable) {
- throw (Throwable) response;
- }
-
- return response;
- }
-
- private String[] createParamSignature(Class<?>[] types) {
- String[] paramSig = new String[types.length];
- for (int x = 0; x < types.length; x++) {
- paramSig[x] = types[x].getName();
- }
- return paramSig;
+ return getRhqFacade().remoteInvoke(getManager(), originalMethod, Object.class, args);
}
}
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
index dbb4424..e350302 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
@@ -19,11 +19,9 @@
package org.rhq.enterprise.client;
-import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
import java.util.HashMap;
import java.util.Map;
@@ -34,36 +32,6 @@ import org.rhq.bindings.client.RhqFacade;
import org.rhq.bindings.client.RhqManager;
import org.rhq.bindings.util.InterfaceSimplifier;
import org.rhq.core.domain.auth.Subject;
-import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
-import org.rhq.enterprise.server.alert.AlertManagerRemote;
-import org.rhq.enterprise.server.auth.SubjectManagerRemote;
-import org.rhq.enterprise.server.authz.RoleManagerRemote;
-import org.rhq.enterprise.server.bundle.BundleManagerRemote;
-import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
-import org.rhq.enterprise.server.content.ContentManagerRemote;
-import org.rhq.enterprise.server.content.RepoManagerRemote;
-import org.rhq.enterprise.server.discovery.DiscoveryBossRemote;
-import org.rhq.enterprise.server.drift.DriftManagerRemote;
-import org.rhq.enterprise.server.drift.DriftTemplateManagerRemote;
-import org.rhq.enterprise.server.event.EventManagerRemote;
-import org.rhq.enterprise.server.install.remote.RemoteInstallManagerRemote;
-import org.rhq.enterprise.server.measurement.AvailabilityManagerRemote;
-import org.rhq.enterprise.server.measurement.CallTimeDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementBaselineManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerRemote;
-import org.rhq.enterprise.server.operation.OperationManagerRemote;
-import org.rhq.enterprise.server.report.DataAccessManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceFactoryManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceTypeManagerRemote;
-import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
-import org.rhq.enterprise.server.search.SavedSearchManagerRemote;
-import org.rhq.enterprise.server.support.SupportManagerRemote;
-import org.rhq.enterprise.server.sync.SynchronizationManagerRemote;
-import org.rhq.enterprise.server.system.SystemManagerRemote;
-import org.rhq.enterprise.server.tagging.TagManagerRemote;
import org.rhq.enterprise.server.util.LookupUtil;
/**
@@ -102,331 +70,46 @@ public class LocalClient implements RhqFacade {
}
@Override
- public AlertManagerRemote getAlertManager() {
- return AccessController.doPrivileged(new PrivilegedAction<AlertManagerRemote>() {
- @Override
- public AlertManagerRemote run() {
- return AccessController.doPrivileged(new PrivilegedAction<AlertManagerRemote>() {
- @Override
- public AlertManagerRemote run() {
- return getProxy(LookupUtil.getAlertManager(), AlertManagerRemote.class);
- }
- });
- }
- });
- }
-
- @Override
- public AlertDefinitionManagerRemote getAlertDefinitionManager() {
- return AccessController.doPrivileged(new PrivilegedAction<AlertDefinitionManagerRemote>() {
- @Override
- public AlertDefinitionManagerRemote run() {
- return getProxy(LookupUtil.getAlertDefinitionManager(), AlertDefinitionManagerRemote.class);
- }
- });
- }
+ public Map<String, Object> getScriptingAPI() {
+ if (managers == null) {
- @Override
- public AvailabilityManagerRemote getAvailabilityManager() {
- return AccessController.doPrivileged(new PrivilegedAction<AvailabilityManagerRemote>() {
- @Override
- public AvailabilityManagerRemote run() {
- return getProxy(LookupUtil.getAvailabilityManager(), AvailabilityManagerRemote.class);
- }
- });
- }
+ managers = new HashMap<String, Object>();
- @Override
- public BundleManagerRemote getBundleManager() {
- return AccessController.doPrivileged(new PrivilegedAction<BundleManagerRemote>() {
- @Override
- public BundleManagerRemote run() {
- return AccessController.doPrivileged(new PrivilegedAction<BundleManagerRemote>() {
- @Override
- public BundleManagerRemote run() {
- return getProxy(LookupUtil.getBundleManager(), BundleManagerRemote.class);
+ for (final RhqManager manager : RhqManager.values()) {
+ if (manager.enabled()) {
+ try {
+ Object proxy = AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ return getProxy(getLocalSLSB(manager), manager.remote());
+ }
+ });
+
+ managers.put(manager.name(), proxy);
+ } catch (Throwable e) {
+ LOG.error("Failed to load manager " + manager + " due to missing class.", e);
}
- });
- }
- });
- }
-
- @Override
- public CallTimeDataManagerRemote getCallTimeDataManager() {
- return AccessController.doPrivileged(new PrivilegedAction<CallTimeDataManagerRemote>() {
- @Override
- public CallTimeDataManagerRemote run() {
- return getProxy(LookupUtil.getCallTimeDataManager(), CallTimeDataManagerRemote.class);
- }
- });
- }
-
- @Override
- public RepoManagerRemote getRepoManager() {
- return AccessController.doPrivileged(new PrivilegedAction<RepoManagerRemote>() {
- @Override
- public RepoManagerRemote run() {
- return getProxy(LookupUtil.getRepoManagerLocal(), RepoManagerRemote.class);
- }
- });
- }
-
- @Override
- public ConfigurationManagerRemote getConfigurationManager() {
- return AccessController.doPrivileged(new PrivilegedAction<ConfigurationManagerRemote>() {
- @Override
- public ConfigurationManagerRemote run() {
- return getProxy(LookupUtil.getConfigurationManager(), ConfigurationManagerRemote.class);
- }
- });
- }
-
- @Override
- public ContentManagerRemote getContentManager() {
- return AccessController.doPrivileged(new PrivilegedAction<ContentManagerRemote>() {
- @Override
- public ContentManagerRemote run() {
- return getProxy(LookupUtil.getContentManager(), ContentManagerRemote.class);
- }
- });
- }
-
- @Override
- public DataAccessManagerRemote getDataAccessManager() {
- return AccessController.doPrivileged(new PrivilegedAction<DataAccessManagerRemote>() {
- @Override
- public DataAccessManagerRemote run() {
- return getProxy(LookupUtil.getDataAccessManager(), DataAccessManagerRemote.class);
- }
- });
- }
-
- @Override
- public DiscoveryBossRemote getDiscoveryBoss() {
- return AccessController.doPrivileged(new PrivilegedAction<DiscoveryBossRemote>() {
- @Override
- public DiscoveryBossRemote run() {
- return getProxy(LookupUtil.getDiscoveryBoss(), DiscoveryBossRemote.class);
- }
- });
- }
-
- @Override
- public DriftManagerRemote getDriftManager() {
- return AccessController.doPrivileged(new PrivilegedAction<DriftManagerRemote>() {
- @Override
- public DriftManagerRemote run() {
- return getProxy(LookupUtil.getDriftManager(), DriftManagerRemote.class);
- }
- });
- }
-
- public DriftTemplateManagerRemote getDriftTemplateManager() {
- return AccessController.doPrivileged(new PrivilegedAction<DriftTemplateManagerRemote>() {
- @Override
- public DriftTemplateManagerRemote run() {
- return getProxy(LookupUtil.getDriftTemplateManager(), DriftTemplateManagerRemote.class);
- }
- });
- }
-
- @Override
- public EventManagerRemote getEventManager() {
- return AccessController.doPrivileged(new PrivilegedAction<EventManagerRemote>() {
- @Override
- public EventManagerRemote run() {
- return getProxy(LookupUtil.getEventManager(), EventManagerRemote.class);
- }
- });
- }
-
- @Override
- public MeasurementBaselineManagerRemote getMeasurementBaselineManager() {
- return AccessController.doPrivileged(new PrivilegedAction<MeasurementBaselineManagerRemote>() {
- @Override
- public MeasurementBaselineManagerRemote run() {
- return getProxy(LookupUtil.getMeasurementBaselineManager(), MeasurementBaselineManagerRemote.class);
- }
- });
- }
-
- @Override
- public MeasurementDataManagerRemote getMeasurementDataManager() {
- return AccessController.doPrivileged(new PrivilegedAction<MeasurementDataManagerRemote>() {
- @Override
- public MeasurementDataManagerRemote run() {
- return getProxy(LookupUtil.getMeasurementDataManager(), MeasurementDataManagerRemote.class);
- }
- });
- }
-
- @Override
- public MeasurementDefinitionManagerRemote getMeasurementDefinitionManager() {
- return AccessController.doPrivileged(new PrivilegedAction<MeasurementDefinitionManagerRemote>() {
- @Override
- public MeasurementDefinitionManagerRemote run() {
- return getProxy(LookupUtil.getMeasurementDefinitionManager(), MeasurementDefinitionManagerRemote.class);
- }
- });
- }
-
- @Override
- public MeasurementScheduleManagerRemote getMeasurementScheduleManager() {
- return AccessController.doPrivileged(new PrivilegedAction<MeasurementScheduleManagerRemote>() {
- @Override
- public MeasurementScheduleManagerRemote run() {
- return getProxy(LookupUtil.getMeasurementScheduleManager(), MeasurementScheduleManagerRemote.class);
- }
- });
- }
-
- @Override
- public OperationManagerRemote getOperationManager() {
- return AccessController.doPrivileged(new PrivilegedAction<OperationManagerRemote>() {
- @Override
- public OperationManagerRemote run() {
- return getProxy(LookupUtil.getOperationManager(), OperationManagerRemote.class);
- }
- });
- }
-
- @Override
- public ResourceManagerRemote getResourceManager() {
- return AccessController.doPrivileged(new PrivilegedAction<ResourceManagerRemote>() {
- @Override
- public ResourceManagerRemote run() {
- return getProxy(LookupUtil.getResourceManager(), ResourceManagerRemote.class);
- }
- });
- }
-
- @Override
- public ResourceFactoryManagerRemote getResourceFactoryManager() {
- return AccessController.doPrivileged(new PrivilegedAction<ResourceFactoryManagerRemote>() {
- @Override
- public ResourceFactoryManagerRemote run() {
- return getProxy(LookupUtil.getResourceFactoryManager(), ResourceFactoryManagerRemote.class);
- }
- });
- }
-
- @Override
- public ResourceGroupManagerRemote getResourceGroupManager() {
- return AccessController.doPrivileged(new PrivilegedAction<ResourceGroupManagerRemote>() {
- @Override
- public ResourceGroupManagerRemote run() {
- return getProxy(LookupUtil.getResourceGroupManager(), ResourceGroupManagerRemote.class);
- }
- });
- }
-
- @Override
- public ResourceTypeManagerRemote getResourceTypeManager() {
- return AccessController.doPrivileged(new PrivilegedAction<ResourceTypeManagerRemote>() {
- @Override
- public ResourceTypeManagerRemote run() {
- return getProxy(LookupUtil.getResourceTypeManager(), ResourceTypeManagerRemote.class);
- }
- });
- }
-
- @Override
- public RoleManagerRemote getRoleManager() {
- return AccessController.doPrivileged(new PrivilegedAction<RoleManagerRemote>() {
- @Override
- public RoleManagerRemote run() {
- return getProxy(LookupUtil.getRoleManager(), RoleManagerRemote.class);
- }
- });
- }
-
- @Override
- public SavedSearchManagerRemote getSavedSearchManager() {
- return AccessController.doPrivileged(new PrivilegedAction<SavedSearchManagerRemote>() {
- @Override
- public SavedSearchManagerRemote run() {
- return getProxy(LookupUtil.getSavedSearchManager(), SavedSearchManagerRemote.class);
- }
- });
- }
-
- @Override
- public SubjectManagerRemote getSubjectManager() {
- return AccessController.doPrivileged(new PrivilegedAction<SubjectManagerRemote>() {
- @Override
- public SubjectManagerRemote run() {
- return getProxy(LookupUtil.getSubjectManager(), SubjectManagerRemote.class);
- }
- });
- }
-
- @Override
- public SupportManagerRemote getSupportManager() {
- return AccessController.doPrivileged(new PrivilegedAction<SupportManagerRemote>() {
- @Override
- public SupportManagerRemote run() {
- return getProxy(LookupUtil.getSupportManager(), SupportManagerRemote.class);
- }
- });
- }
-
- @Override
- public SystemManagerRemote getSystemManager() {
- return AccessController.doPrivileged(new PrivilegedAction<SystemManagerRemote>() {
- @Override
- public SystemManagerRemote run() {
- return getProxy(LookupUtil.getSystemManager(), SystemManagerRemote.class);
- }
- });
- }
-
- @Override
- public RemoteInstallManagerRemote getRemoteInstallManager() {
- return AccessController.doPrivileged(new PrivilegedAction<RemoteInstallManagerRemote>() {
- @Override
- public RemoteInstallManagerRemote run() {
- return getProxy(LookupUtil.getRemoteInstallManager(), RemoteInstallManagerRemote.class);
+ }
}
- });
- }
+ }
- @Override
- public TagManagerRemote getTagManager() {
- return AccessController.doPrivileged(new PrivilegedAction<TagManagerRemote>() {
- @Override
- public TagManagerRemote run() {
- return getProxy(LookupUtil.getTagManager(), TagManagerRemote.class);
- }
- });
+ return managers;
}
@Override
- public SynchronizationManagerRemote getSynchronizationManager() {
- return AccessController.doPrivileged(new PrivilegedAction<SynchronizationManagerRemote>() {
- @Override
- public SynchronizationManagerRemote run() {
- return getProxy(LookupUtil.getSynchronizationManager(), SynchronizationManagerRemote.class);
- }
- });
- }
+ public <T> T getProxy(Class<T> remoteApiIface) {
+ RhqManager manager = RhqManager.forInterface(remoteApiIface);
- @Override
- public Map<String, Object> getManagers() {
- if (managers == null) {
+ if (manager == null) {
+ throw new IllegalArgumentException("Unknown remote interface " + remoteApiIface);
+ }
- managers = new HashMap<String, Object>();
+ Object localSLSB = getLocalSLSB(manager);
- for (RhqManager manager : RhqManager.values()) {
- try {
- Method m = getClass().getMethod("get" + manager.name());
- managers.put(manager.name(), m.invoke(this));
- } catch (Throwable e) {
- LOG.error("Failed to load manager " + manager + " due to missing class.", e);
- }
- }
- }
+ Object proxy = Proxy.newProxyInstance(remoteApiIface.getClassLoader(), new Class<?>[] { remoteApiIface },
+ new LocalClientProxy(localSLSB, this, manager));
- return managers;
+ return remoteApiIface.cast(proxy);
}
private <T> T getProxy(Object slsb, Class<T> iface) {
@@ -442,10 +125,77 @@ public class LocalClient implements RhqFacade {
Thread.currentThread().setContextClassLoader(cl);
}
- Object proxy =
- Proxy.newProxyInstance(iface.getClassLoader(), new Class<?>[] { simplified }, new LocalClientProxy(slsb,
- this, manager));
+ Object proxy = Proxy.newProxyInstance(iface.getClassLoader(), new Class<?>[] { simplified },
+ new LocalClientProxy(slsb, this, manager));
return iface.cast(proxy);
}
+
+ private Object getLocalSLSB(RhqManager manager) {
+ switch (manager) {
+ case AlertDefinitionManager:
+ return LookupUtil.getAlertDefinitionManager();
+ case AlertManager:
+ return LookupUtil.getAlertManager();
+ case AvailabilityManager:
+ return LookupUtil.getAvailabilityManager();
+ case BundleManager:
+ return LookupUtil.getBundleManager();
+ case CallTimeDataManager:
+ return LookupUtil.getCallTimeDataManager();
+ case ConfigurationManager:
+ return LookupUtil.getConfigurationManager();
+ case ContentManager:
+ return LookupUtil.getContentManager();
+ case DataAccessManager:
+ return LookupUtil.getDataAccessManager();
+ case DiscoveryBoss:
+ return LookupUtil.getDiscoveryBoss();
+ case DriftManager:
+ return LookupUtil.getDriftManager();
+ case DriftTemplateManager:
+ return LookupUtil.getDriftTemplateManager();
+ case EventManager:
+ return LookupUtil.getEventManager();
+ case MeasurementBaselineManager:
+ return LookupUtil.getMeasurementBaselineManager();
+ case MeasurementDataManager:
+ return LookupUtil.getMeasurementDataManager();
+ case MeasurementDefinitionManager:
+ return LookupUtil.getMeasurementDefinitionManager();
+ case MeasurementScheduleManager:
+ return LookupUtil.getMeasurementScheduleManager();
+ case OperationManager:
+ return LookupUtil.getOperationManager();
+ case RemoteInstallManager:
+ return LookupUtil.getRemoteInstallManager();
+ case RepoManager:
+ return LookupUtil.getRepoManagerLocal();
+ case ResourceFactoryManager:
+ return LookupUtil.getResourceFactoryManager();
+ case ResourceGroupManager:
+ return LookupUtil.getResourceGroupManager();
+ case ResourceManager:
+ return LookupUtil.getResourceManager();
+ case ResourceTypeManager:
+ return LookupUtil.getResourceTypeManager();
+ case RoleManager:
+ return LookupUtil.getRoleManager();
+ case SavedSearchManager:
+ return LookupUtil.getSavedSearchManager();
+ case SubjectManager:
+ return LookupUtil.getSubjectManager();
+ case SupportManager:
+ return LookupUtil.getSupportManager();
+ case SynchronizationManager:
+ return LookupUtil.getSynchronizationManager();
+ case SystemManager:
+ return LookupUtil.getSystemManager();
+ case TagManager:
+ return LookupUtil.getTagManager();
+ }
+
+ throw new IllegalStateException("LocalClient does not handle the manager: " + manager
+ + ". This is a bug, please report it.");
+ }
}
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
index 67bd5e7..54d20e0 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
@@ -56,9 +56,10 @@ public class LocalClientProxy extends AbstractRhqFacadeProxy<LocalClient> {
}
}
- protected Object doInvoke(Object proxy, Method originalMethod, java.lang.Class<?>[] argTypes, final Object[] args) throws Throwable {
+ protected Object doInvoke(Object proxy, Method originalMethod, final Object[] args) throws Throwable {
try {
- final Method realMethod = localSLSB.getClass().getMethod(originalMethod.getName(), argTypes);
+ final Method realMethod = localSLSB.getClass().getMethod(originalMethod.getName(),
+ originalMethod.getParameterTypes());
//run this through the privileged block to elevate the privs of the script
//the scripts don't have the AllowEjbAccessPermission but this code has
@@ -72,7 +73,9 @@ public class LocalClientProxy extends AbstractRhqFacadeProxy<LocalClient> {
}
});
} catch (NoSuchMethodException e) {
- throw new IllegalArgumentException("Method [" + originalMethod + "] does not have a desimplified counterpart with arguments " + Arrays.asList(argTypes) + ".", e);
+ throw new IllegalArgumentException("Method [" + originalMethod
+ + "] does not have a desimplified counterpart with arguments "
+ + Arrays.asList(originalMethod.getParameterTypes()) + ".", e);
}
};
diff --git a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
index 3b949e3..e9bd928 100644
--- a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
+++ b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
@@ -31,7 +31,6 @@ import javax.naming.NamingException;
import javax.naming.spi.InitialContextFactory;
import org.jmock.Expectations;
-import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@@ -89,7 +88,7 @@ public class LocalClientTest extends JMockTest {
LocalClient lc = new LocalClient(null);
//this call creates the proxy and is theoretically prone to the context classloader
- AlertManagerRemote am = lc.getAlertManager();
+ Object am = lc.getScriptingAPI().get("AlertManager");
//check that both the original and simplified methods exist on the returned object
am.getClass().getMethod("deleteAlerts", new Class<?>[] { Subject.class, int[].class });
commit 09e7b73cf38378ccc825b8c9041ddc8b6a6b5429
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Jun 20 09:37:39 2012 +0200
Renaming "RhqManagers" to "RhqManager".
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
index 7f3a56f..ef46bb2 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
@@ -34,9 +34,9 @@ import org.rhq.core.domain.auth.Subject;
public abstract class AbstractRhqFacadeProxy<T extends RhqFacade> implements InvocationHandler {
private T facade;
- private RhqManagers manager;
+ private RhqManager manager;
- protected AbstractRhqFacadeProxy(T facade, RhqManagers manager) {
+ protected AbstractRhqFacadeProxy(T facade, RhqManager manager) {
this.facade = facade;
this.manager = manager;
}
@@ -45,7 +45,7 @@ public abstract class AbstractRhqFacadeProxy<T extends RhqFacade> implements Inv
return facade;
}
- protected RhqManagers getManager() {
+ protected RhqManager getManager() {
return manager;
}
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
index f2bde27..ca7fa83 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
@@ -129,7 +129,7 @@ public interface RhqFacade {
SynchronizationManagerRemote getSynchronizationManager();
/**
- * This map is constructed using all the elements in the {@link RhqManagers} enum which are then proxied
+ * This map is constructed using all the elements in the {@link RhqManager} enum which are then proxied
* using this instance.
*
* @return a map of all available proxied managers keyed by their names.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManager.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManager.java
new file mode 100644
index 0000000..cfa52e2
--- /dev/null
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManager.java
@@ -0,0 +1,133 @@
+/*
+ * 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.bindings.client;
+
+import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
+import org.rhq.enterprise.server.alert.AlertManagerRemote;
+import org.rhq.enterprise.server.auth.SubjectManagerRemote;
+import org.rhq.enterprise.server.authz.RoleManagerRemote;
+import org.rhq.enterprise.server.bundle.BundleManagerRemote;
+import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
+import org.rhq.enterprise.server.content.ContentManagerRemote;
+import org.rhq.enterprise.server.content.RepoManagerRemote;
+import org.rhq.enterprise.server.discovery.DiscoveryBossRemote;
+import org.rhq.enterprise.server.drift.DriftManagerRemote;
+import org.rhq.enterprise.server.drift.DriftTemplateManagerRemote;
+import org.rhq.enterprise.server.event.EventManagerRemote;
+import org.rhq.enterprise.server.install.remote.RemoteInstallManagerRemote;
+import org.rhq.enterprise.server.measurement.AvailabilityManagerRemote;
+import org.rhq.enterprise.server.measurement.CallTimeDataManagerRemote;
+import org.rhq.enterprise.server.measurement.MeasurementBaselineManagerRemote;
+import org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote;
+import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote;
+import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerRemote;
+import org.rhq.enterprise.server.operation.OperationManagerRemote;
+import org.rhq.enterprise.server.report.DataAccessManagerRemote;
+import org.rhq.enterprise.server.resource.ResourceFactoryManagerRemote;
+import org.rhq.enterprise.server.resource.ResourceManagerRemote;
+import org.rhq.enterprise.server.resource.ResourceTypeManagerRemote;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
+import org.rhq.enterprise.server.search.SavedSearchManagerRemote;
+import org.rhq.enterprise.server.support.SupportManagerRemote;
+import org.rhq.enterprise.server.sync.SynchronizationManagerRemote;
+import org.rhq.enterprise.server.system.SystemManagerRemote;
+import org.rhq.enterprise.server.tagging.TagManagerRemote;
+
+/**
+ * An enumeration of all remote SLSBs of the RHQ server.
+ *
+ * @author Lukas Krejci
+ * @author Greg Hinkle
+ */
+public enum RhqManager {
+ AlertManager(AlertManagerRemote.class, "${AlertManager}"), //
+ AlertDefinitionManager(AlertDefinitionManagerRemote.class, "${AlertDefinitionManager}"), //
+ AvailabilityManager(AvailabilityManagerRemote.class, "${AvailabilityManager}"), //
+ BundleManager(BundleManagerRemote.class, "${BundleManager}"), //
+ CallTimeDataManager(CallTimeDataManagerRemote.class, "${CallTimeDataManager}"), //
+ RepoManager(RepoManagerRemote.class, "${RepoManager}"), //
+ ConfigurationManager(ConfigurationManagerRemote.class, "${ConfigurationManager}"), //
+ ContentManager(ContentManagerRemote.class, "${ContentManager}"), //
+ DataAccessManager(DataAccessManagerRemote.class, "${DataAccessManager}"), //
+ DriftManager(DriftManagerRemote.class, "${DriftManager}"), //
+ DriftTemplateManager(DriftTemplateManagerRemote.class, "${DriftTemplateManager}"), //
+ DiscoveryBoss(DiscoveryBossRemote.class, "${DiscoveryBoss}"), //
+ EventManager(EventManagerRemote.class, "${EventManager}"), //
+ MeasurementBaselineManager(MeasurementBaselineManagerRemote.class, "${MeasurementBaselineManager}"), //
+ MeasurementDataManager(MeasurementDataManagerRemote.class, "${MeasurementDataManager}"), //
+ MeasurementDefinitionManager(MeasurementDefinitionManagerRemote.class, "${MeasurementDefinitionManager}"), //
+ MeasurementScheduleManager(MeasurementScheduleManagerRemote.class, "${MeasurementScheduleManager}"), //
+ OperationManager(OperationManagerRemote.class, "${OperationManager}"), //
+ ResourceManager(ResourceManagerRemote.class, "${ResourceManager}"), //
+ ResourceFactoryManager(ResourceFactoryManagerRemote.class, "${ResourceFactoryManager}"), //
+ ResourceGroupManager(ResourceGroupManagerRemote.class, "${ResourceGroupManager}"), //
+ ResourceTypeManager(ResourceTypeManagerRemote.class, "${ResourceTypeManager}"), //
+ RoleManager(RoleManagerRemote.class, "${RoleManager}"), //
+ SavedSearchManager(SavedSearchManagerRemote.class, "${SavedSearchManager}"), //
+ SubjectManager(SubjectManagerRemote.class, "${SubjectManager}"), //
+ SupportManager(SupportManagerRemote.class, "${SupportManager}"), //
+ SystemManager(SystemManagerRemote.class, "${SystemManager}"), //
+ RemoteInstallManager(RemoteInstallManagerRemote.class, "${RemoteInstallManager}"), //
+ TagManager(TagManagerRemote.class, "${TagManager}"), //
+ SynchronizationManager(SynchronizationManagerRemote.class, "${SynchronizationManager}");
+
+ private Class<?> remote;
+ private String remoteName;
+ private String beanName;
+ private boolean enabled;
+
+ private RhqManager(Class<?> remote, String enable) {
+ this.remote = remote;
+ this.beanName = this.name() + "Bean";
+ this.remoteName = this.name() + "Remote";
+ //defaults and evaluates to TRUE unless the string contains "false". Done to defend against
+ //possible errors in string replacement during rhq build.
+ this.enabled = true;
+ if ((enable != null) && (enable.trim().length() > 0)) {
+ this.enabled = (enable.trim().equalsIgnoreCase("false")) ? Boolean.FALSE : Boolean.TRUE;
+ }
+ }
+
+ public static RhqManager forInterface(Class<?> iface) {
+ for (RhqManager m : values()) {
+ if (m.remote().equals(iface)) {
+ return m;
+ }
+ }
+
+ return null;
+ }
+
+ public Class<?> remote() {
+ return this.remote;
+ }
+
+ public String beanName() {
+ return this.beanName;
+ }
+
+ public String remoteName() {
+ return this.remoteName;
+ }
+
+ public boolean enabled() {
+ return this.enabled;
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManagers.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManagers.java
deleted file mode 100644
index dfe600c..0000000
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManagers.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.bindings.client;
-
-import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
-import org.rhq.enterprise.server.alert.AlertManagerRemote;
-import org.rhq.enterprise.server.auth.SubjectManagerRemote;
-import org.rhq.enterprise.server.authz.RoleManagerRemote;
-import org.rhq.enterprise.server.bundle.BundleManagerRemote;
-import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
-import org.rhq.enterprise.server.content.ContentManagerRemote;
-import org.rhq.enterprise.server.content.RepoManagerRemote;
-import org.rhq.enterprise.server.discovery.DiscoveryBossRemote;
-import org.rhq.enterprise.server.drift.DriftManagerRemote;
-import org.rhq.enterprise.server.drift.DriftTemplateManagerRemote;
-import org.rhq.enterprise.server.event.EventManagerRemote;
-import org.rhq.enterprise.server.install.remote.RemoteInstallManagerRemote;
-import org.rhq.enterprise.server.measurement.AvailabilityManagerRemote;
-import org.rhq.enterprise.server.measurement.CallTimeDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementBaselineManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerRemote;
-import org.rhq.enterprise.server.operation.OperationManagerRemote;
-import org.rhq.enterprise.server.report.DataAccessManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceFactoryManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceTypeManagerRemote;
-import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
-import org.rhq.enterprise.server.search.SavedSearchManagerRemote;
-import org.rhq.enterprise.server.support.SupportManagerRemote;
-import org.rhq.enterprise.server.sync.SynchronizationManagerRemote;
-import org.rhq.enterprise.server.system.SystemManagerRemote;
-import org.rhq.enterprise.server.tagging.TagManagerRemote;
-
-/**
- * An enumeration of all remote SLSBs of the RHQ server.
- *
- * @author Lukas Krejci
- * @author Greg Hinkle
- */
-public enum RhqManagers {
- AlertManager(AlertManagerRemote.class, "${AlertManager}"), //
- AlertDefinitionManager(AlertDefinitionManagerRemote.class, "${AlertDefinitionManager}"), //
- AvailabilityManager(AvailabilityManagerRemote.class, "${AvailabilityManager}"), //
- BundleManager(BundleManagerRemote.class, "${BundleManager}"), //
- CallTimeDataManager(CallTimeDataManagerRemote.class, "${CallTimeDataManager}"), //
- RepoManager(RepoManagerRemote.class, "${RepoManager}"), //
- ConfigurationManager(ConfigurationManagerRemote.class, "${ConfigurationManager}"), //
- ContentManager(ContentManagerRemote.class, "${ContentManager}"), //
- DataAccessManager(DataAccessManagerRemote.class, "${DataAccessManager}"), //
- DriftManager(DriftManagerRemote.class, "${DriftManager}"), //
- DriftTemplateManager(DriftTemplateManagerRemote.class, "${DriftTemplateManager}"), //
- DiscoveryBoss(DiscoveryBossRemote.class, "${DiscoveryBoss}"), //
- EventManager(EventManagerRemote.class, "${EventManager}"), //
- MeasurementBaselineManager(MeasurementBaselineManagerRemote.class, "${MeasurementBaselineManager}"), //
- MeasurementDataManager(MeasurementDataManagerRemote.class, "${MeasurementDataManager}"), //
- MeasurementDefinitionManager(MeasurementDefinitionManagerRemote.class, "${MeasurementDefinitionManager}"), //
- MeasurementScheduleManager(MeasurementScheduleManagerRemote.class, "${MeasurementScheduleManager}"), //
- OperationManager(OperationManagerRemote.class, "${OperationManager}"), //
- ResourceManager(ResourceManagerRemote.class, "${ResourceManager}"), //
- ResourceFactoryManager(ResourceFactoryManagerRemote.class, "${ResourceFactoryManager}"), //
- ResourceGroupManager(ResourceGroupManagerRemote.class, "${ResourceGroupManager}"), //
- ResourceTypeManager(ResourceTypeManagerRemote.class, "${ResourceTypeManager}"), //
- RoleManager(RoleManagerRemote.class, "${RoleManager}"), //
- SavedSearchManager(SavedSearchManagerRemote.class, "${SavedSearchManager}"), //
- SubjectManager(SubjectManagerRemote.class, "${SubjectManager}"), //
- SupportManager(SupportManagerRemote.class, "${SupportManager}"), //
- SystemManager(SystemManagerRemote.class, "${SystemManager}"), //
- RemoteInstallManager(RemoteInstallManagerRemote.class, "${RemoteInstallManager}"), //
- TagManager(TagManagerRemote.class, "${TagManager}"), //
- SynchronizationManager(SynchronizationManagerRemote.class, "${SynchronizationManager}");
-
- private Class<?> remote;
- private String remoteName;
- private String beanName;
- private boolean enabled;
-
- private RhqManagers(Class<?> remote, String enable) {
- this.remote = remote;
- this.beanName = this.name() + "Bean";
- this.remoteName = this.name() + "Remote";
- //defaults and evaluates to TRUE unless the string contains "false". Done to defend against
- //possible errors in string replacement during rhq build.
- this.enabled = true;
- if ((enable != null) && (enable.trim().length() > 0)) {
- this.enabled = (enable.trim().equalsIgnoreCase("false")) ? Boolean.FALSE : Boolean.TRUE;
- }
- }
-
- public static RhqManagers forInterface(Class<?> iface) {
- for (RhqManagers m : values()) {
- if (m.remote().equals(iface)) {
- return m;
- }
- }
-
- return null;
- }
-
- public Class<?> remote() {
- return this.remote;
- }
-
- public String beanName() {
- return this.beanName;
- }
-
- public String remoteName() {
- return this.remoteName;
- }
-
- public boolean enabled() {
- return this.enabled;
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
index f3084d1..e80c346 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
@@ -36,7 +36,7 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.bindings.ScriptEngineFactory;
import org.rhq.bindings.StandardBindings;
-import org.rhq.bindings.client.RhqManagers;
+import org.rhq.bindings.client.RhqManager;
import org.rhq.bindings.output.TabularWriter;
import org.rhq.bindings.util.PackageFinder;
import org.rhq.enterprise.client.ClientMain;
@@ -295,6 +295,6 @@ public class ScriptCommand implements ClientCommand {
public String getDetailedHelp() {
return "Execute a statement or a script. The following service managers are available: "
- + Arrays.toString(RhqManagers.values());
+ + Arrays.toString(RhqManager.values());
}
}
diff --git a/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java b/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
index fe109a8..fc59cf3 100644
--- a/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
+++ b/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
@@ -23,7 +23,7 @@ import org.rhq.enterprise.server.authz.RoleManagerRemote;
import org.rhq.enterprise.server.resource.ResourceManagerRemote;
import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
import org.rhq.enterprise.server.auth.SubjectManagerRemote;
-import org.rhq.bindings.client.RhqManagers;
+import org.rhq.bindings.client.RhqManager;
import org.rhq.bindings.output.TabularWriter;
import org.rhq.bindings.util.ScriptUtil;
import org.rhq.core.domain.auth.Subject;
@@ -76,7 +76,7 @@ public class ScriptCommandTest {
ScriptEngine scriptEngine = client.getScriptEngine();
List<String> mgrsNotBound = new ArrayList<String>();
- for (RhqManagers mgr : RhqManagers.values()) {
+ for (RhqManager mgr : RhqManager.values()) {
if (!scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE).containsKey(mgr.name())) {
mgrsNotBound.add(mgr.remoteName());
}
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
index d0fb529..57829b9 100644
--- a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
@@ -32,7 +32,7 @@ import org.jboss.remoting.security.SSLSocketBuilder;
import org.jboss.remoting.transport.http.ssl.HTTPSClientInvoker;
import org.rhq.bindings.client.RhqFacade;
-import org.rhq.bindings.client.RhqManagers;
+import org.rhq.bindings.client.RhqManager;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.common.ProductInfo;
import org.rhq.enterprise.communications.util.SecurityUtil;
@@ -261,123 +261,123 @@ public class RemoteClient implements RhqFacade {
}
public AlertManagerRemote getAlertManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.AlertManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.AlertManager);
}
public AlertDefinitionManagerRemote getAlertDefinitionManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.AlertDefinitionManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.AlertDefinitionManager);
}
public AvailabilityManagerRemote getAvailabilityManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.AvailabilityManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.AvailabilityManager);
}
public BundleManagerRemote getBundleManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.BundleManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.BundleManager);
}
public CallTimeDataManagerRemote getCallTimeDataManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.CallTimeDataManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.CallTimeDataManager);
}
public DriftManagerRemote getDriftManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.DriftManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.DriftManager);
}
public DriftTemplateManagerRemote getDriftTemplateManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.DriftTemplateManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.DriftTemplateManager);
}
public RepoManagerRemote getRepoManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.RepoManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.RepoManager);
}
public ConfigurationManagerRemote getConfigurationManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.ConfigurationManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.ConfigurationManager);
}
public ContentManagerRemote getContentManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.ContentManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.ContentManager);
}
public DataAccessManagerRemote getDataAccessManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.DataAccessManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.DataAccessManager);
}
public DiscoveryBossRemote getDiscoveryBoss() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.DiscoveryBoss);
+ return RemoteClientProxy.getProcessor(this, RhqManager.DiscoveryBoss);
}
public EventManagerRemote getEventManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.EventManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.EventManager);
}
public MeasurementBaselineManagerRemote getMeasurementBaselineManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementBaselineManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementBaselineManager);
}
public MeasurementDataManagerRemote getMeasurementDataManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementDataManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementDataManager);
}
public MeasurementDefinitionManagerRemote getMeasurementDefinitionManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementDefinitionManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementDefinitionManager);
}
public MeasurementScheduleManagerRemote getMeasurementScheduleManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementScheduleManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementScheduleManager);
}
public OperationManagerRemote getOperationManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.OperationManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.OperationManager);
}
public ResourceManagerRemote getResourceManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.ResourceManager);
}
public ResourceFactoryManagerRemote getResourceFactoryManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceFactoryManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.ResourceFactoryManager);
}
public ResourceGroupManagerRemote getResourceGroupManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceGroupManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.ResourceGroupManager);
}
public ResourceTypeManagerRemote getResourceTypeManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceTypeManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.ResourceTypeManager);
}
public RoleManagerRemote getRoleManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.RoleManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.RoleManager);
}
public SavedSearchManagerRemote getSavedSearchManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.SavedSearchManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.SavedSearchManager);
}
public SubjectManagerRemote getSubjectManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.SubjectManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.SubjectManager);
}
public SupportManagerRemote getSupportManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.SupportManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.SupportManager);
}
public SystemManagerRemote getSystemManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.SystemManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.SystemManager);
}
public RemoteInstallManagerRemote getRemoteInstallManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.RemoteInstallManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.RemoteInstallManager);
}
public TagManagerRemote getTagManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.TagManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.TagManager);
}
public SynchronizationManagerRemote getSynchronizationManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.SynchronizationManager);
+ return RemoteClientProxy.getProcessor(this, RhqManager.SynchronizationManager);
}
/**
@@ -391,7 +391,7 @@ public class RemoteClient implements RhqFacade {
this.managers = new HashMap<String, Object>();
- for (RhqManagers manager : RhqManagers.values()) {
+ for (RhqManager manager : RhqManager.values()) {
try {
Method m = this.getClass().getMethod("get" + manager.name());
if (manager.enabled()) {
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java
index e9751c2..23dea3c 100644
--- a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java
@@ -27,7 +27,7 @@ import org.apache.commons.logging.LogFactory;
import org.jboss.remoting.invocation.NameBasedInvocation;
import org.rhq.bindings.client.AbstractRhqFacadeProxy;
-import org.rhq.bindings.client.RhqManagers;
+import org.rhq.bindings.client.RhqManager;
import org.rhq.bindings.util.InterfaceSimplifier;
import org.rhq.core.domain.server.ExternalizableStrategy;
@@ -42,7 +42,7 @@ public class RemoteClientProxy extends AbstractRhqFacadeProxy<RemoteClient> {
private static final Log LOG = LogFactory.getLog(RemoteClientProxy.class);
- public RemoteClientProxy(RemoteClient client, RhqManagers manager) {
+ public RemoteClientProxy(RemoteClient client, RhqManager manager) {
super(client, manager);
}
@@ -51,7 +51,7 @@ public class RemoteClientProxy extends AbstractRhqFacadeProxy<RemoteClient> {
}
@SuppressWarnings("unchecked")
- public static <T> T getProcessor(RemoteClient remoteClient, RhqManagers manager) {
+ public static <T> T getProcessor(RemoteClient remoteClient, RhqManager manager) {
try {
RemoteClientProxy gpc = new RemoteClientProxy(remoteClient, manager);
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
index 2e48048..dbb4424 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
@@ -31,7 +31,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rhq.bindings.client.RhqFacade;
-import org.rhq.bindings.client.RhqManagers;
+import org.rhq.bindings.client.RhqManager;
import org.rhq.bindings.util.InterfaceSimplifier;
import org.rhq.core.domain.auth.Subject;
import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
@@ -416,7 +416,7 @@ public class LocalClient implements RhqFacade {
managers = new HashMap<String, Object>();
- for (RhqManagers manager : RhqManagers.values()) {
+ for (RhqManager manager : RhqManager.values()) {
try {
Method m = getClass().getMethod("get" + manager.name());
managers.put(manager.name(), m.invoke(this));
@@ -430,7 +430,7 @@ public class LocalClient implements RhqFacade {
}
private <T> T getProxy(Object slsb, Class<T> iface) {
- RhqManagers manager = RhqManagers.forInterface(iface);
+ RhqManager manager = RhqManager.forInterface(iface);
Class<?> simplified = null;
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
index e9f1e4d..67bd5e7 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
@@ -28,7 +28,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rhq.bindings.client.AbstractRhqFacadeProxy;
-import org.rhq.bindings.client.RhqManagers;
+import org.rhq.bindings.client.RhqManager;
/**
* This is a proxy interface that simply calls given (de-simplified) method on a provided object.
@@ -42,7 +42,7 @@ public class LocalClientProxy extends AbstractRhqFacadeProxy<LocalClient> {
private Object localSLSB;
- public LocalClientProxy(Object localSLSB, LocalClient client, RhqManagers manager) {
+ public LocalClientProxy(Object localSLSB, LocalClient client, RhqManager manager) {
super(client, manager);
this.localSLSB = localSLSB;
}
commit 573dd3715035d095bd65f823dc9539e72a27fbe9
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Jun 20 09:22:03 2012 +0200
Making it all compile again and provide basic abstractions to cut the code completion out of the CLI.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
index da544c4..05e6a09 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
@@ -133,13 +133,11 @@ public class StandardBindings extends HashMap<String, Object> {
putAll(managers);
}
- @Override
public void preInject(ScriptEngine scriptEngine) {
((ScriptUtil) get(SCRIPT_UTIL)).init(scriptEngine);
((ScriptAssert) get(ASSERT)).init(scriptEngine);
}
- @Override
public void postInject(ScriptEngine scriptEngine) {
ScriptEngineFactory.bindIndirectionMethods(scriptEngine, SCRIPT_UTIL);
ScriptEngineFactory.bindIndirectionMethods(scriptEngine, ASSERT);
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index 7ebe141..4a1ed62 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@ -22,6 +22,9 @@
*/
package org.rhq.enterprise.client;
+import gnu.getopt.Getopt;
+import gnu.getopt.LongOpt;
+
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
@@ -34,6 +37,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
import gnu.getopt.Getopt;
import gnu.getopt.LongOpt;
@@ -44,6 +50,8 @@ import jline.MultiCompletor;
import jline.SimpleCompletor;
import mazz.i18n.Msg;
+import org.rhq.bindings.ScriptEngineFactory;
+import org.rhq.bindings.util.PackageFinder;
import org.rhq.core.domain.auth.Subject;
import org.rhq.enterprise.client.commands.ClientCommand;
import org.rhq.enterprise.client.commands.ScriptCommand;
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java
index f51e148..0f1b232 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java
@@ -91,6 +91,7 @@ public class InteractiveJavascriptCompletor implements Completor {
this.services = services;
}
+ @Override
@SuppressWarnings("unchecked")
public int complete(String s, int i, @SuppressWarnings("rawtypes") List list) {
try {
@@ -168,7 +169,7 @@ public class InteractiveJavascriptCompletor implements Completor {
* @param list
* @return location of relative completion
*/
- public int contextComplete(Object baseObject, String s, int i, List<String> list) {
+ private int contextComplete(Object baseObject, String s, int i, List<String> list) {
String temp = s.split("\\(", 2)[0];
if (temp.contains(".")) {
String[] call = temp.split("\\.", 2);
diff --git a/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml b/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
index ecf304e..202bef7 100644
--- a/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
+++ b/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
@@ -67,6 +67,10 @@
<copy file="${settings.localRepository}/net/sf/opencsv/opencsv/${opencsv.version}/opencsv-${opencsv.version}.jar" tofile="${lib.home}/opencsv-${opencsv.version}.jar" verbose="true" />
<copy file="${settings.localRepository}/org/rhq/rhq-script-bindings/${project.version}/rhq-script-bindings-${project.version}.jar" tofile="${lib.home}/rhq-script-bindings-${project.version}.jar" verbose="true" />
<copy file="${settings.localRepository}/hibernate-annotations/hibernate-annotations/${hibernate-annotations.version}/hibernate-annotations-${hibernate-annotations.version}.jar" todir="${lib.home}" verbose="true" />
+
+ <copy file="${settings.localRepository}/org/rhq/rhq-scripting-api/${project.version}/rhq-scripting-api-${project.version}.jar" tofile="${lib.home}/rhq-scripting-api-${project.version}.jar" verbose="true" />
+ <copy file="${settings.localRepository}/org/rhq/rhq-scripting-javascript/${project.version}/rhq-scripting-javascript-${project.version}.jar" tofile="${lib.home}/rhq-scripting-javascript-${project.version}.jar" verbose="true" />
+ <copy file="${settings.localRepository}/org/mozilla/rhino/${rhino.version}/rhino-${rhino.version}.jar" tofile="${lib.home}/rhino-${rhino.version}.jar" verbose="true" />
</target>
<target name="prepare-samples-dir">
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
index f8beb28..2c89718 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
@@ -19,8 +19,11 @@
package org.rhq.scripting;
+import java.io.PrintWriter;
import java.util.List;
+import javax.script.ScriptContext;
+
/**
* An interface for performing code completion in a given language.
* This inspired by the jline's <code>Completor</code> interface but
@@ -32,8 +35,29 @@ import java.util.List;
public interface CodeCompletion {
/**
+ * The code completor can use the provided script context to find out about possible
+ * completions.
+ * <p>
+ * This method is called once before the first {@link #complete(PrintWriter, String, int, List)} method
+ * is called.
+ *
+ * @param scriptContext
+ */
+ void setScriptContext(ScriptContext scriptContext);
+
+ /**
+ * Provides the code completion implementation with the metadata provider it can use to
+ * format more meaningful completion hints.
+ *
+ * @param metadataProvider
+ */
+ void setMetadataProvider(MetadataProvider metadataProvider);
+
+ /**
* Generates the completion candidates and fills the supplied list with them.
*
+ * @param output the output the completor can use to write some additional information to convey some
+ * additional info to the user
* @param context the context of the code completion, usually that is the current
* statement being edited by the user
* @param cursorPosition the position of the cursor inside the context
@@ -42,5 +66,5 @@ public interface CodeCompletion {
* @return the character index in the context for which the completion candidates were
* actually generated (might be different from the cursorPosition).
*/
- int complete(String context, int cursorPosition, @SuppressWarnings("rawtypes") List candidates);
+ int complete(PrintWriter output, String context, int cursorPosition, @SuppressWarnings("rawtypes") List candidates);
}
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java
new file mode 100644
index 0000000..598d952
--- /dev/null
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java
@@ -0,0 +1,69 @@
+/*
+ * 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.scripting;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+
+/**
+ * The scripting implementations don't have to supply an implementation of this interface but
+ * rather one is provided to the {@link CodeCompletion}.
+ * <p>
+ * The code completion can ask this implementation for various metadata on methods or classes.
+ * <p>
+ * The {@link CodeCompletion} implementations can use this information to format more meaningful
+ * completion hints.
+ *
+ * @author Lukas Krejci
+ */
+public interface MetadataProvider {
+
+ /**
+ * Tries to determine the name of a parameter on a method.
+ *
+ * @param method the method
+ * @param parameterIndex the index of the method parameter
+ * @return The name of the parameter or null if it could not be determined
+ */
+ String getParameterName(Method method, int parameterIndex);
+
+ /**
+ * @param clazz
+ * @return the (java)doc on a class or null if none could be determined
+ */
+ String getDocumentation(Class<?> clazz);
+
+ /**
+ * @param method
+ * @return the (java)doc on a method or null if none could be determined
+ */
+ String getDocumentation(Method method);
+
+ /**
+ * This is a utility method for determining the type name including the type parameters.
+ *
+ * @param type the type to determine the name for
+ * @param fullNames if true, all the types and type parameters will be the full class names, otherwise
+ * only the simple name of the class / type parameter will be used.
+ * @return the name of the type including type parameters
+ */
+ String getTypeName(Type type, boolean fullNames);
+}
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
new file mode 100644
index 0000000..d1df7f5
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
@@ -0,0 +1,578 @@
+/*
+ * 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.scripting.javascript;
+
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.MethodDescriptor;
+import java.beans.PropertyDescriptor;
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+
+import org.rhq.scripting.CodeCompletion;
+import org.rhq.scripting.MetadataProvider;
+
+/**
+ * A Contextual JavaScript interactive completor. Not perfect, but
+ * handles a fair number of cases.
+ *
+ * @author Greg Hinkle
+ * @author Lukas Krejci
+ */
+public class JavascriptCompletor implements CodeCompletion {
+
+ private static final String SUBJECT_CLASS_NAME = "org.rhq.core.domain.auth.Subject";
+ private ScriptContext context;
+ private MetadataProvider metadataProvider;
+
+ private String lastComplete;
+
+ // Consecutive times this exact complete has been requested
+ private int recomplete;
+
+ private static final Set<String> IGNORED_METHODS;
+ static {
+ IGNORED_METHODS = new HashSet<String>();
+ IGNORED_METHODS.add("newProxyInstance");
+ IGNORED_METHODS.add("hashCode");
+ IGNORED_METHODS.add("equals");
+ IGNORED_METHODS.add("getInvocationHandler");
+ IGNORED_METHODS.add("setHandler");
+ IGNORED_METHODS.add("isProxyClass");
+ IGNORED_METHODS.add("newProxyInstance");
+ IGNORED_METHODS.add("getProxyClass");
+ IGNORED_METHODS.add("main");
+ IGNORED_METHODS.add("handler");
+ IGNORED_METHODS.add("init");
+ IGNORED_METHODS.add("initChildren");
+ IGNORED_METHODS.add("initMeasurements");
+ IGNORED_METHODS.add("initOperations");
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public int complete(PrintWriter output, String s, int i, @SuppressWarnings("rawtypes") List list) {
+ try {
+ if (lastComplete != null && lastComplete.equals(s)) {
+ recomplete++;
+ } else {
+ recomplete = 1;
+ }
+
+ lastComplete = s;
+
+ String base = s;
+
+ int rootLength = 0;
+
+ if (s.indexOf('=') > 0) {
+ base = s.substring(s.indexOf("=") + 1).trim();
+ rootLength = s.length() - base.length();
+ }
+
+ String[] call = base.split("\\.");
+ if (base.endsWith(".")) {
+ String[] argPadded = new String[call.length + 1];
+ System.arraycopy(call, 0, argPadded, 0, call.length);
+ argPadded[call.length] = "";
+ call = argPadded;
+ }
+
+ if (call.length == 1) {
+ Map<String, Object> matches = getContextMatches(call[0]);
+ if (matches.size() == 1 && matches.containsKey(call[0]) && !s.endsWith(".")) {
+ list.add(".");
+ return rootLength + call[0].length() + 1;
+
+ } else {
+ list.addAll(matches.keySet());
+ }
+ } else {
+ Object rootObject = context.getAttribute(call[0]);
+ if (rootObject != null) {
+ String theRest = base.substring(call[0].length() + 1, base.length());
+ int matchIndex = contextComplete(output, rootObject, theRest, i, list);
+ Collections.sort(list);
+ return rootLength + call[0].length() + 1 + matchIndex;
+ }
+ }
+
+ Collections.sort(list);
+
+ return (list.size() == 0) ? (-1) : rootLength;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ @Override
+ public void setMetadataProvider(MetadataProvider metadataProvider) {
+ this.metadataProvider = metadataProvider;
+ }
+
+ /**
+ * Base Object can be an object where we're looking for methods on it, or an
+ * interface. This recursively works off the completions left to right.
+ *
+ * Objects can be completed with fields or method calls.
+ * method parameters are completed with type matching
+ * method result chainings are completed based on declared return types
+ *
+ * e.g. have a Resource in context as myResource. Original string is
+ * "myResource.name". This method would be called with a baseObject ==
+ * to myResource and the string "name".
+ *
+ * Note: this method will not and should not execute methods, but will
+ * read field properties to continue chained completions.
+ *
+ * @param output the output that can the completor use to convey info to the user
+ * @param baseObject the context object or class to complete from
+ * @param s the relative command string to check
+ * @param i
+ * @param list
+ * @return location of relative completion
+ */
+ private int contextComplete(PrintWriter output, Object baseObject, String s, int i, List<String> list) {
+ String temp = s.split("\\(", 2)[0];
+ if (temp.contains(".")) {
+ String[] call = temp.split("\\.", 2);
+
+ String next = call[0];
+ if (next.contains("(")) {
+ next = next.substring(0, next.indexOf("("));
+ }
+
+ Map<String, List<Object>> matches = getContextMatches(output, baseObject, next);
+ if (!matches.isEmpty()) {
+ Object rootObject = matches.get(next).get(0);
+ if (rootObject instanceof PropertyDescriptor && !(baseObject instanceof Class)) {
+ try {
+ rootObject = invoke(baseObject, ((PropertyDescriptor) rootObject).getReadMethod());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } else if (rootObject instanceof Method) {
+ rootObject = ((Method) rootObject).getReturnType();
+ }
+
+ return call[0].length() + 1 + contextComplete(output, rootObject, call[1], i, list);
+ } else {
+ return -1;
+ }
+ } else {
+ String[] call = s.split("\\(", 2);
+
+ Map<String, List<Object>> matches = getContextMatches(output, baseObject, call[0]);
+
+ if (call.length == 2 && matches.containsKey(call[0])) {
+
+ int x = 0;
+ for (String key : matches.keySet()) {
+
+ List<Object> matchList = matches.get(key);
+
+ if (recomplete == 2) {
+ List<Method> methods = new ArrayList<Method>();
+ for (Object match : matchList) {
+ if (match instanceof Method) {
+ methods.add((Method) match);
+ }
+ }
+ displaySignatures(output, baseObject, methods.toArray(new Method[methods.size()]));
+ return -1;
+ }
+
+ for (Object match : matchList) {
+
+ if (key.equals(call[0]) && match instanceof Method) {
+
+ int result = completeParameters(baseObject, call[1], i, list, (Method) match); // x should be the same for all calls
+ if (result > 0) {
+ x = result;
+ }
+ }
+ }
+ }
+ return call[0].length() + 1 + x;
+ }
+
+ if (matches.size() == 1 && matches.containsKey(call[0])) {
+ if (matches.get(call[0]).get(0) instanceof Method) {
+ list.add("(" + (((Method) matches.get(call[0]).get(0)).getParameterTypes().length == 0 ? ")" : ""));
+ }
+ return call[0].length() + 1;
+ }
+
+ if (recomplete == 2) {
+ List<Method> methods = new ArrayList<Method>();
+ for (List<Object> matchList : matches.values()) {
+ for (Object val : matchList) {
+ if (val instanceof Method) {
+ methods.add((Method) val);
+ }
+ }
+ }
+ displaySignatures(output, baseObject, methods.toArray(new Method[methods.size()]));
+ } else {
+ if (matches.size() == 1 && matches.values().iterator().next().get(0) instanceof Method) {
+ list.add(matches.keySet().iterator().next()
+ + "("
+ + ((((Method) matches.values().iterator().next().get(0)).getParameterTypes().length == 0 ? ")"
+ : "")));
+ } else {
+ list.addAll(matches.keySet());
+ }
+ }
+ return 0;
+
+ }
+ }
+
+ private void displaySignatures(PrintWriter output, Object object, Method... methods) {
+ try {
+ String[][] signatures = new String[methods.length][];
+ int i = 0;
+ for (Method m : methods) {
+ signatures[i++] = getSignature(object, m).split(" ", 2);
+ }
+
+ int maxReturnLength = 0;
+ for (String[] sig : signatures) {
+ if (sig[0].length() > maxReturnLength)
+ maxReturnLength = sig[0].length();
+ }
+
+ for (String[] sig : signatures) {
+ for (i = 0; i < (maxReturnLength - sig[0].length()); i++) {
+ output.print(" ");
+ }
+
+ output.print(sig[0]);
+ output.print(" ");
+ output.print(sig[1]);
+ output.println();
+ }
+ } catch (Exception e) {
+ e.printStackTrace(output);
+ }
+ }
+
+ /**
+ * Split apart the parameters to a method call and complete the last parameter. If the last
+ * paramater has a valid value close that field with a "," for the next param or a ")" if is
+ * the last parameter. Does all machting according to the type of the parameters of the
+ * supplied method.
+ *
+ * @param baseObject
+ * @param params
+ * @param i
+ * @param list
+ * @param method
+ * @return
+ */
+ public int completeParameters(Object baseObject, String params, int i, List<String> list, Method method) {
+
+ String[] paramList = params.split(",");
+
+ Class<?>[] c = method.getParameterTypes();
+
+ String lastParam = paramList[paramList.length - 1];
+ int paramIndex = paramList.length - 1;
+ if (params.trim().endsWith(",")) {
+ lastParam = "";
+ paramIndex++;
+ }
+
+ int baseLength = 0;
+
+ for (int x = 0; x < paramIndex; x++) {
+ Object paramFound = context.getAttribute(paramList[x]);
+
+ if (paramFound != null && !c[x].isAssignableFrom(paramFound.getClass())) {
+ return -1;
+ }
+ baseLength += paramList[x].length() + 1;
+ }
+
+ if (paramIndex >= c.length) {
+ if (params.endsWith(")")) {
+ return -1;
+ } else {
+ list.add(params + ")");
+ return (params + ")").length();
+ }
+ } else {
+
+ if (baseObject instanceof Map && method.getName().equals("get") && method.getParameterTypes().length == 1) {
+ //unused Class<?> keyType = method.getParameterTypes()[0];
+ for (Object key : ((Map<?, ?>) baseObject).keySet()) {
+ String lookupChoice = "\'" + String.valueOf(key) + "\'";
+ if (lookupChoice.startsWith(lastParam)) {
+ list.add(lookupChoice);
+ }
+ }
+ if (list.size() == 1) {
+ list.set(0, list.get(0) + ")");
+ }
+
+ } else {
+ Class<?> parameterType = c[paramIndex];
+
+ Map<String, Object> matches = getContextMatches(lastParam, parameterType);
+
+ if (matches.size() == 1 && matches.containsKey(lastParam)) {
+
+ list.add(paramIndex == c.length - 1 ? ")" : ",");
+ return baseLength + lastParam.length();
+ } else {
+ list.addAll(matches.keySet());
+ }
+ }
+
+ return baseLength;
+ }
+ }
+
+ private Map<String, Object> getContextMatches(String start) {
+ Map<String, Object> found = new HashMap<String, Object>();
+ if (context != null) {
+ for (Integer scope : context.getScopes()) {
+ Bindings bindings = context.getBindings(scope);
+ for (String var : bindings.keySet()) {
+ if (var.startsWith(start)) {
+ found.put(var, bindings.get(var));
+ }
+ }
+ }
+ }
+
+ //this was originally part of the code completor that lived in the CLI
+ //I don't think we need it, because the services are present under the
+ //same names in the context. This code can never add any new matches.
+ /*
+ if (services != null) {
+ for (String var : services.keySet()) {
+ if (var.startsWith(start)) {
+ found.put(var, services.get(var));
+ }
+ }
+ }
+ */
+
+ return found;
+ }
+
+ /**
+ * Look through all available contexts to find bindings that both start with
+ * the supplied start and match the typeFilter.
+ * @param start
+ * @param typeFilter
+ * @return
+ */
+ private Map<String, Object> getContextMatches(String start, Class<?> typeFilter) {
+ Map<String, Object> found = new HashMap<String, Object>();
+ if (context != null) {
+ for (int scope : context.getScopes()) {
+ Bindings bindings = context.getBindings(scope);
+ for (String var : bindings.keySet()) {
+ if (var.startsWith(start)) {
+
+ if ((bindings.get(var) != null && typeFilter.isAssignableFrom(bindings.get(var).getClass()))
+ || recomplete == 3) {
+ found.put(var, bindings.get(var));
+ }
+ }
+ }
+ }
+
+ if (typeFilter.isEnum()) {
+ for (Object ec : typeFilter.getEnumConstants()) {
+ Enum<?> e = (Enum<?>) ec;
+ String code = typeFilter.getSimpleName() + "." + e.name();
+ if (code.startsWith(start)) {
+ found.put(typeFilter.getSimpleName() + "." + e.name(), e);
+ }
+ }
+ }
+ }
+ return found;
+ }
+
+ private Map<String, List<Object>> getContextMatches(PrintWriter output, Object baseObject, String start) {
+ Map<String, List<Object>> found = new HashMap<String, List<Object>>();
+
+ Class<?> baseObjectClass = null;
+ if (baseObject instanceof Class) {
+ baseObjectClass = (Class<?>) baseObject;
+ } else {
+ baseObjectClass = baseObject.getClass();
+ }
+
+ try {
+ if (baseObjectClass.equals(Void.TYPE))
+ return found;
+
+ BeanInfo info = null;
+ if (baseObjectClass.isInterface() || baseObjectClass.equals(Object.class)) {
+ info = Introspector.getBeanInfo(baseObjectClass);
+ } else {
+ info = Introspector.getBeanInfo(baseObjectClass, Object.class);
+ }
+
+ Set<Method> methodsCovered = new HashSet<Method>();
+
+ PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
+ for (PropertyDescriptor desc : descriptors) {
+ if (desc.getName().startsWith(start) && (!IGNORED_METHODS.contains(desc.getName()))) {
+
+ List<Object> list = found.get(desc.getName());
+ if (list == null) {
+ list = new ArrayList<Object>();
+ found.put(desc.getName(), list);
+ }
+ list.add(desc);
+
+ methodsCovered.add(desc.getReadMethod());
+ methodsCovered.add(desc.getWriteMethod());
+ }
+ }
+
+ MethodDescriptor[] methods = info.getMethodDescriptors();
+ for (MethodDescriptor desc : methods) {
+ if (desc.getName().startsWith(start) && !methodsCovered.contains(desc.getMethod())
+ && !desc.getName().startsWith("_d") && !IGNORED_METHODS.contains(desc.getName())) {
+
+ Method m = desc.getMethod();
+ //TODO THIS IS SO WRONG - the methods are there but we just "forget" to
+ //to mention them to the user.
+ boolean isProxy = isProxyMethod(baseObject, m);
+ Class<?>[] parameters = m.getParameterTypes();
+ boolean startsWithSubject = ((parameters.length > 0) && isSubjectClass(parameters[0]));
+ if ((isProxy && startsWithSubject) || !startsWithSubject) {
+
+ List<Object> list = found.get(desc.getName());
+ if (list == null) {
+ list = new ArrayList<Object>();
+ found.put(desc.getName(), list);
+ }
+ list.add(m);
+ }
+ }
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace(output);
+ }
+ return found;
+ }
+
+ private String getSignature(Object object, Method m) {
+
+ StringBuilder buf = new StringBuilder();
+ Type[] params = m.getGenericParameterTypes();
+ int i = 0;
+
+ buf.append(metadataProvider.getTypeName(m.getGenericReturnType(), false));
+ buf.append(" ");
+
+ buf.append(m.getName());
+ buf.append("(");
+ boolean first = true;
+ for (Type type : params) {
+ if (!first) {
+ buf.append(", ");
+ } else {
+ first = false;
+ }
+
+ String name = metadataProvider.getTypeName(type, false);
+ String paramName = metadataProvider.getParameterName(m, i);
+ if (paramName != null) {
+ name += " " + paramName;
+ }
+
+ buf.append(name);
+
+ i++;
+ }
+ buf.append(")");
+ return buf.toString();
+ }
+
+ private static boolean isProxyMethod(Object object, Method m) {
+ // TODO this has to be changed - we have the MetaDataProvider which should be able
+ // to provide enough info so that the completors don't have to go through these hoops.
+ return false;
+
+ // boolean result = false;
+ // if (object instanceof Proxy) {
+ // if (Proxy.getInvocationHandler(object) instanceof RemoteClientProxy) {
+ // try {
+ // m =
+ // ((RemoteClientProxy) Proxy.getInvocationHandler(object)).getRemoteInterface()
+ // .getDeclaredMethod(m.getName(), m.getParameterTypes());
+ // } catch (NoSuchMethodException e) {
+ // result = true;
+ // }
+ // }
+ // }
+ // return result;
+ }
+
+ @Override
+ public void setScriptContext(ScriptContext context) {
+ this.context = context;
+ }
+
+ private static Object invoke(Object o, Method m) throws IllegalAccessException, InvocationTargetException {
+ boolean access = m.isAccessible();
+ m.setAccessible(true);
+ try {
+ return m.invoke(o);
+ } finally {
+ m.setAccessible(access);
+ }
+ }
+
+ private boolean isSubjectClass(Class<?> cls) {
+ while (cls != null) {
+ if (SUBJECT_CLASS_NAME.equals(cls.getName())) {
+ return true;
+ }
+
+ cls = cls.getSuperclass();
+ }
+
+ return false;
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
index 984e5fc..02d54eb 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
@@ -42,8 +42,7 @@ public class JsEngineProvider implements ScriptEngineProvider {
@Override
public CodeCompletion getCodeCompletion() {
- // TODO copy this over from the CLI
- return null;
+ return new JavascriptCompletor();
}
}
commit d35d0f2fb6ae66ed339dbe2099a9d475a3d0cea6
Merge: 6bd2fa8 bc0ab10
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Jun 18 13:05:37 2012 +0200
Merge branch 'master' into lkrejci/modular-scripting
diff --cc modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index 5021434,99595ab..7ebe141
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@@ -22,11 -22,7 +22,8 @@@
*/
package org.rhq.enterprise.client;
- import gnu.getopt.Getopt;
- import gnu.getopt.LongOpt;
-
import java.io.ByteArrayInputStream;
+import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
@@@ -37,9 -32,14 +34,9 @@@ import java.util.HashMap
import java.util.List;
import java.util.Map;
- import javax.script.ScriptEngine;
- import javax.script.ScriptException;
-import org.rhq.core.domain.auth.Subject;
-import org.rhq.enterprise.client.commands.ClientCommand;
-import org.rhq.enterprise.client.commands.ScriptCommand;
-import org.rhq.enterprise.client.script.CommandLineParseException;
-import org.rhq.enterprise.clientapi.RemoteClient;
-
+ import gnu.getopt.Getopt;
+ import gnu.getopt.LongOpt;
+
import jline.ArgumentCompletor;
import jline.Completor;
import jline.ConsoleReader;
@@@ -47,14 -47,6 +44,12 @@@ import jline.MultiCompletor
import jline.SimpleCompletor;
import mazz.i18n.Msg;
- import org.rhq.bindings.ScriptEngineFactory;
- import org.rhq.bindings.util.PackageFinder;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.enterprise.client.commands.ClientCommand;
+import org.rhq.enterprise.client.commands.ScriptCommand;
+import org.rhq.enterprise.client.script.CommandLineParseException;
+import org.rhq.enterprise.clientapi.RemoteClient;
+
/**
* @author Greg Hinkle
* @author Simeon Pinder
commit 6bd2fa80f4871209de16e6560b374a24cd308666
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed May 30 20:13:46 2012 +0200
Experimental and unfinished support for python in the CLI.
There's no support for custom script sources and code completion.
diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
new file mode 100644
index 0000000..4b48e52
--- /dev/null
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -0,0 +1,187 @@
+<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-scripting-parent</artifactId>
+ <groupId>org.rhq</groupId>
+ <version>4.5.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>rhq-scripting-python</artifactId>
+ <version>4.5.0-SNAPSHOT</version>
+ <name>RHQ Python support</name>
+ <description>Provides RHQ scripting in Python using Jython</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-scripting-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.python</groupId>
+ <artifactId>jython-standalone</artifactId>
+ <version>2.5.2</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+
+ <profile>
+ <id>dev</id>
+
+ <properties>
+ <rhq.rootDir>../../..</rhq.rootDir>
+ <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+ <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/lib</rhq.deploymentDir>
+ </properties>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.1</version>
+ <executions>
+
+ <execution>
+ <id>deploy</id>
+ <phase>compile</phase>
+ <configuration>
+ <tasks>
+ <mkdir dir="${rhq.deploymentDir}" />
+ <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Updating
+ ${deployment.file}...</echo>
+ <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>undeploy</id>
+ <phase>clean</phase>
+ <configuration>
+ <tasks>
+ <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Deleting
+ ${deployment.file}...</echo>
+ <delete file="${deployment.file}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+
+ <profile>
+ <id>cobertura-plugins</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>net.sourceforge.cobertura</groupId>
+ <artifactId>cobertura</artifactId>
+ <version>1.9.4.1</version>
+ </dependency>
+ </dependencies>
+ <executions>
+ <execution>
+ <id>cobertura-instrument</id>
+ <phase>pre-integration-test</phase>
+ <configuration>
+ <tasks>
+ <!-- prepare directory structure
+ for cobertura -->
+ <mkdir dir="target/cobertura" />
+ <mkdir dir="target/cobertura/backup" />
+ <!-- backup all classes so that we
+ can instrument the original classes -->
+ <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
+ <fileset dir="target/classes">
+ <include name="**/*.class" />
+ </fileset>
+ </copy>
+ <!-- create a properties file and
+ save there location of cobertura data file -->
+ <touch file="target/classes/cobertura.properties" />
+ <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
+ <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+ <!-- instrument all classes in target/classes
+ directory -->
+ <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser" todir="${project.build.directory}/classes">
+ <fileset dir="${project.build.directory}/classes">
+ <include name="**/*.class" />
+ </fileset>
+ </cobertura-instrument>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>cobertura-report</id>
+ <phase>post-integration-test</phase>
+ <configuration>
+ <tasks>
+ <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+ <!-- prepare directory structure
+ for cobertura -->
+ <mkdir dir="target/cobertura" />
+ <mkdir dir="target/site/cobertura" />
+ <!-- restore classes from backup
+ folder to classes folder -->
+ <copy toDir="target/classes" verbose="true" overwrite="true">
+ <fileset dir="target/cobertura/backup">
+ <include name="**/*.class" />
+ </fileset>
+ </copy>
+ <!-- delete backup folder -->
+ <delete dir="target/cobertura/backup" />
+ <!-- create a code coverage report -->
+ <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser" destdir="${project.build.directory}/site/cobertura">
+ <fileset dir="${basedir}/src/main/java">
+ <include name="**/*.java" />
+ </fileset>
+ </cobertura-report>
+ <!-- delete cobertura.properties
+ file -->
+ <delete file="target/classes/cobertura.properties" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
new file mode 100644
index 0000000..9ee50b8
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
@@ -0,0 +1,101 @@
+/*
+ * 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.scripting.python;
+
+import java.lang.reflect.Method;
+import java.security.PermissionCollection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+
+import org.rhq.scripting.ScriptEngineInitializer;
+import org.rhq.scripting.ScriptSourceProvider;
+import org.rhq.scripting.util.SandboxedScriptEngine;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class PythonScriptEngineInitializer implements ScriptEngineInitializer {
+
+ private ScriptEngineManager engineManager = new ScriptEngineManager();
+
+ @Override
+ public ScriptEngine instantiate(Set<String> packages, ScriptSourceProvider scriptSourceProvider,
+ PermissionCollection permissions) throws ScriptException {
+
+ ScriptEngine eng = engineManager.getEngineByName("python");
+
+ for (String pkg : packages) {
+ eng.eval("from " + pkg + " import *\n");
+ }
+
+ //TODO add support for script source providers... possibly using http://www.python.org/dev/peps/pep-0302/
+
+ //fingers crossed we can secure jython like this
+ return new SandboxedScriptEngine(eng, permissions);
+ }
+
+ @Override
+ public Set<String> generateIndirectionMethods(String boundObjectName, Set<Method> overloadedMethods) {
+ if (overloadedMethods == null || overloadedMethods.isEmpty()) {
+ return Collections.emptySet();
+ }
+
+ Set<Integer> argCnts = new HashSet<Integer>();
+ for(Method m : overloadedMethods) {
+ argCnts.add(m.getParameterTypes().length);
+ }
+
+ String methodName = overloadedMethods.iterator().next().getName();
+ StringBuilder functionBody = new StringBuilder();
+
+ functionBody.append("def ").append(methodName).append("(*args, **kwargs):\n");
+ functionBody.append("\t").append("if len(kwargs) > 0:\n");
+ functionBody.append("\t\t").append("raise ValueError(\"Named arguments not supported for Java methods\")\n");
+ functionBody.append("\t").append("argCnt = len(args)\n");
+
+ for(Integer argCnt : argCnts) {
+ functionBody.append("\t").append("if argCnt == ").append(argCnt).append(":\n");
+ functionBody.append("\t\treturn ").append(boundObjectName).append(".").append(methodName).append("(");
+ int last = argCnt - 1;
+ for(int i = 0; i < argCnt; ++i) {
+ functionBody.append("args[").append(i).append("]");
+ if (i < last) {
+ functionBody.append(", ");
+ }
+ }
+ functionBody.append(")\n");
+ }
+
+ return Collections.singleton(functionBody.toString());
+ }
+
+ @Override
+ public String extractUserFriendlyErrorMessage(ScriptException e) {
+ return e.getMessage();
+ }
+
+}
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java
new file mode 100644
index 0000000..c0bfcac
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java
@@ -0,0 +1,49 @@
+/*
+ * 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.scripting.python;
+
+import org.rhq.scripting.CodeCompletion;
+import org.rhq.scripting.ScriptEngineInitializer;
+import org.rhq.scripting.ScriptEngineProvider;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class PythonScriptEngineProvider implements ScriptEngineProvider {
+
+ @Override
+ public String getSupportedLanguage() {
+ return "python";
+ }
+
+ @Override
+ public ScriptEngineInitializer getInitializer() {
+ return new PythonScriptEngineInitializer();
+ }
+
+ @Override
+ public CodeCompletion getCodeCompletion() {
+ // XXX are we gonna support code completion for multiple langs in the CLI?
+ return null;
+ }
+
+}
diff --git a/modules/enterprise/scripting/python/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider b/modules/enterprise/scripting/python/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider
new file mode 100644
index 0000000..3882776
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider
@@ -0,0 +1 @@
+org.rhq.scripting.python.PythonScriptEngineProvider
commit 6515d4f28dfddde094d20b72bad3b2f038d70b13
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed May 30 20:08:03 2012 +0200
Initial impl of modules in the javascript CLI.
All should be hooked up apart from the actual bundling of now standalone
javascript support with the CLI. This will going to need some pom.xml love.
We now bundle our own ScriptEngine implementation based on the Phobos
javascript engine with modifications inspired by the version of the script
engine in JDK 1.6.30.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/SandboxedScriptEngine.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/SandboxedScriptEngine.java
deleted file mode 100644
index f994f09..0000000
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/SandboxedScriptEngine.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * 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.bindings;
-
-import java.io.Reader;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.CodeSource;
-import java.security.Permission;
-import java.security.PermissionCollection;
-import java.security.Permissions;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.security.ProtectionDomain;
-import java.security.cert.Certificate;
-import java.util.Arrays;
-import java.util.Collection;
-
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineFactory;
-import javax.script.ScriptException;
-
-/**
- * <b>DO NOT USE THIS CLASS DIRECTLY!!!!</b> Use {@link org.rhq.bindings.ScriptEngineFactory#getSecuredScriptEngine(String, org.rhq.bindings.util.PackageFinder, StandardBindings, PermissionCollection)}
- * method instead for a reliably secured script engine.
- * <p>
- * This is a decorator class for any other {@link ScriptEngine} implementation
- * that runs any of the eval methods with the defined set of {@link Permission}s.
- * <p>
- * For the permissions to have any effect, a SecurityManager has to be installed
- * in the current VM.
- *
- * @author Lukas Krejci
- */
-public class SandboxedScriptEngine implements ScriptEngine {
-
- private ScriptEngine engine;
- private AccessControlContext accessControlContext;
-
- public SandboxedScriptEngine(ScriptEngine engine) {
- this.engine = engine;
- }
-
- public SandboxedScriptEngine(ScriptEngine engine, PermissionCollection permissions) {
- this(engine);
- setPermissions(permissions);
- }
-
- public SandboxedScriptEngine(ScriptEngine engine, Collection<? extends Permission> permissions) {
- this(engine);
- setPermissions(permissions);
- }
-
- public void setPermissions(Permission... permissions) {
- setPermissions(Arrays.asList(permissions));
- }
-
- public void setPermissions(Collection<? extends Permission> permissions) {
- Permissions ps = new Permissions();
- for(Permission p : permissions) {
- ps.add(p);
- }
-
- setPermissions(ps);
- }
-
- public void setPermissions(PermissionCollection permissions) {
- CodeSource cs = new CodeSource(null, (Certificate[]) null);
-
- ProtectionDomain domain = new ProtectionDomain(cs, permissions);
- accessControlContext = new AccessControlContext(new ProtectionDomain[] { domain });
- }
-
- public Object eval(final String script, final ScriptContext context) throws ScriptException {
- try {
- return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
- return engine.eval(script, context);
- }
- }, accessControlContext);
- } catch (PrivilegedActionException e) {
- throw transfer(e);
- }
- }
-
- public Object eval(final Reader reader, final ScriptContext context) throws ScriptException {
- try {
- return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
- return engine.eval(reader, context);
- }
- }, accessControlContext);
- } catch (PrivilegedActionException e) {
- throw transfer(e);
- }
- }
-
- public Object eval(final String script) throws ScriptException {
- try {
- return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
- return engine.eval(script);
- }
- }, accessControlContext);
- } catch (PrivilegedActionException e) {
- throw transfer(e);
- }
- }
-
- public Object eval(final Reader reader) throws ScriptException {
- try {
- return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
- return engine.eval(reader);
- }
- }, accessControlContext);
- } catch (PrivilegedActionException e) {
- throw transfer(e);
- }
- }
-
- public Object eval(final String script, final Bindings n) throws ScriptException {
- try {
- return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
- return engine.eval(script, n);
- }
- }, accessControlContext);
- } catch (PrivilegedActionException e) {
- throw transfer(e);
- }
- }
-
- public Object eval(final Reader reader, final Bindings n) throws ScriptException {
- try {
- return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
- return engine.eval(reader, n);
- }
- }, accessControlContext);
- } catch (PrivilegedActionException e) {
- throw transfer(e);
- }
- }
-
- public void put(String key, Object value) {
- engine.put(key, value);
- }
-
- public Object get(String key) {
- return engine.get(key);
- }
-
- public Bindings getBindings(int scope) {
- return engine.getBindings(scope);
- }
-
- public void setBindings(Bindings bindings, int scope) {
- engine.setBindings(bindings, scope);
- }
-
- public Bindings createBindings() {
- return engine.createBindings();
- }
-
- public ScriptContext getContext() {
- return engine.getContext();
- }
-
- public void setContext(ScriptContext context) {
- engine.setContext(context);
- }
-
- public ScriptEngineFactory getFactory() {
- return engine.getFactory();
- }
-
- private static ScriptException transfer(PrivilegedActionException e) {
- if (e.getCause() instanceof ScriptException) {
- return (ScriptException) e.getCause();
- } else {
- return new ScriptException(e);
- }
- }
-}
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
index 73ffc9d..df78b41 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
@@ -25,15 +25,7 @@ import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.io.IOException;
import java.lang.reflect.Method;
-import java.net.URL;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.CodeSource;
import java.security.PermissionCollection;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.security.ProtectionDomain;
-import java.security.cert.Certificate;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -50,6 +42,7 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.bindings.util.NoTopLevelIndirection;
import org.rhq.bindings.util.PackageFinder;
+import org.rhq.scripting.CodeCompletion;
import org.rhq.scripting.ScriptEngineInitializer;
import org.rhq.scripting.ScriptEngineProvider;
@@ -131,19 +124,8 @@ public class ScriptEngineFactory {
*/
public static ScriptEngine getScriptEngine(String language, PackageFinder packageFinder, StandardBindings bindings)
throws ScriptException, IOException {
- ScriptEngineInitializer initializer = getInitializer(language);
-
- if (initializer == null) {
- return null;
- }
-
- ScriptEngine engine = initializer.instantiate(packageFinder.findPackages("org.rhq.core.domain"));
-
- if (bindings != null) {
- injectStandardBindings(engine, bindings, true);
- }
-
- return engine;
+
+ return getSecuredScriptEngine(language, packageFinder, bindings, null);
}
/**
@@ -155,45 +137,22 @@ public class ScriptEngineFactory {
*/
public static ScriptEngine getSecuredScriptEngine(final String language, final PackageFinder packageFinder,
final StandardBindings bindings, final PermissionCollection permissions) throws ScriptException, IOException {
- CodeSource src = new CodeSource(new URL("http://rhq-project.org/scripting"), (Certificate[]) null);
- ProtectionDomain scriptDomain = new ProtectionDomain(src, permissions);
- AccessControlContext ctx = new AccessControlContext(new ProtectionDomain[] { scriptDomain });
- try {
- return AccessController.doPrivileged(new PrivilegedExceptionAction<ScriptEngine>() {
- @Override
- public ScriptEngine run() throws Exception {
- //This might seem a bit excessive but is necessary due to the
- //change in security handling in the rhino script engine
- //that occured in Java6u27 (due to a CVE desribed here:
- //https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2011-3544)
-
- //In Java 6u26 and earlier, it was enough to wrap a script engine
- //in the sandbox and everything would work.
-
- //Java 6u27 introduced new behavior where the rhino script engine
- //remembers the access control context with which it has been
- //constructed and combines that with the callers protection domain
- //when a script is executed. Because this class has all perms and
- //all the code in RHQ that called ScriptEngine.eval* also
- //had all perms, the scripts would never be sandboxed even if the call
- //was pushed through the SandboxedScriptEngine.
-
- //This means that the below wrapping is necessary for the security
- //to work in java6 pre u27 while the surrounding privileged block
- //is necessary for the security to be applied in java6 u27 and later.
- return new SandboxedScriptEngine(getScriptEngine(language, packageFinder, bindings), permissions);
- }
- }, ctx);
- } catch (PrivilegedActionException e) {
- Throwable cause = e.getCause();
- if (cause instanceof IOException) {
- throw (IOException) cause;
- } else if (cause instanceof ScriptException) {
- throw (ScriptException) cause;
- } else {
- throw new ScriptException(e);
- }
+
+ ScriptEngineInitializer initializer = getInitializer(language);
+
+ if (initializer == null) {
+ return null;
+ }
+
+ //TODO change this so that we support supplying a custom module source provider so that callers
+ //have control over the location of the loadable scripts.
+ ScriptEngine engine = initializer.instantiate(packageFinder.findPackages("org.rhq.core.domain"), null, permissions);
+
+ if (bindings != null) {
+ injectStandardBindings(engine, bindings, true);
}
+
+ return engine;
}
/**
@@ -297,6 +256,12 @@ public class ScriptEngineFactory {
return provider == null ? null : provider.getInitializer();
}
+ public static CodeCompletion getCodeCompletion(String language) {
+ ScriptEngineProvider provider = KNOWN_PROVIDERS.get(language);
+
+ return provider == null ? null : provider.getCodeCompletion();
+ }
+
private static boolean shouldIndirect(Method method) {
return method.getAnnotation(NoTopLevelIndirection.class) == null;
}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index 308d6c1..5021434 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@ -26,15 +26,20 @@ import gnu.getopt.Getopt;
import gnu.getopt.LongOpt;
import java.io.ByteArrayInputStream;
+import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
import jline.ArgumentCompletor;
import jline.Completor;
import jline.ConsoleReader;
@@ -42,6 +47,8 @@ import jline.MultiCompletor;
import jline.SimpleCompletor;
import mazz.i18n.Msg;
+import org.rhq.bindings.ScriptEngineFactory;
+import org.rhq.bindings.util.PackageFinder;
import org.rhq.core.domain.auth.Subject;
import org.rhq.enterprise.client.commands.ClientCommand;
import org.rhq.enterprise.client.commands.ScriptCommand;
@@ -81,20 +88,23 @@ public class ClientMain {
private int port = 7080;
private String user;
private String pass;
+ private String language;
private ArrayList<String> notes = new ArrayList<String>();
-
+
// reference to the webservice reference factory
private RemoteClient remoteClient;
// The subject that will be used to carry out all requested actions
private Subject subject;
-
+
private InteractiveJavascriptCompletor serviceCompletor;
private boolean interactiveMode = true;
private Recorder recorder = new NoOpRecorder();
+ private ScriptEngine engine;
+
private class StartupConfiguration {
public boolean askForPassword;
public boolean displayUsage;
@@ -187,8 +197,7 @@ public class ClientMain {
}
private void initServiceCompletor() {
- ScriptCommand sc = (ScriptCommand) commands.get("exec");
- this.serviceCompletor.setContext(sc.getContext());
+ this.serviceCompletor.setContext(getScriptEngine().getContext());
if (remoteClient != null) {
this.serviceCompletor.setServices(remoteClient.getManagers());
@@ -363,7 +372,7 @@ public class ClientMain {
} else {
boolean result = commands.get("exec").execute(this, args);
if (loggedIn()) {
- this.serviceCompletor.setContext(((ScriptCommand) commands.get("exec")).getContext());
+ this.serviceCompletor.setContext(getScriptEngine().getContext());
}
return result;
@@ -460,6 +469,7 @@ public class ClientMain {
new LongOpt("command", LongOpt.REQUIRED_ARGUMENT, null, 'c'),
new LongOpt("file", LongOpt.NO_ARGUMENT, null, 'f'),
new LongOpt("version", LongOpt.NO_ARGUMENT, null, 'v'),
+ new LongOpt("language", LongOpt.REQUIRED_ARGUMENT, null, 'l'),
new LongOpt("args-style", LongOpt.REQUIRED_ARGUMENT, null, -2) };
Getopt getopt = new Getopt("Cli", args, sopts, lopts, false);
@@ -540,6 +550,9 @@ public class ClientMain {
}
break;
}
+ case 'l':
+ this.language = getopt.getOptarg();
+ break;
}
}
@@ -619,12 +632,31 @@ public class ClientMain {
this.outputWriter = writer;
}
+ public String getLanguage() {
+ return this.language == null ? "javascript" : this.language;
+ }
+
public int getConsoleWidth() {
//the console reader might be null when this method is asked for the output
//width in non-interactive mode where we don't attach to stdin.
return this.consoleReader == null ? DEFAULT_CONSOLE_WIDTH : this.consoleReader.getTermwidth();
}
+ public ScriptEngine getScriptEngine() {
+ if (engine == null) {
+ try {
+ engine = ScriptEngineFactory.getScriptEngine(getLanguage(),
+ new PackageFinder(Arrays.asList(getLibDir())), null);
+ } catch (ScriptException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ return engine;
+ }
+
public Map<String, ClientCommand> getCommands() {
return commands;
}
@@ -655,4 +687,9 @@ public class ClientMain {
public void setRecorder(Recorder recorder) {
this.recorder = recorder;
}
+
+ private static File getLibDir() {
+ String cwd = System.getProperty("user.dir");
+ return new File(cwd, "lib");
+ }
}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
index 4e7e79a..f3084d1 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
@@ -56,7 +56,6 @@ import org.rhq.enterprise.client.script.ScriptCmdLine;
*/
public class ScriptCommand implements ClientCommand {
- private ScriptEngine jsEngine;
private StandardBindings bindings;
private final Log log = LogFactory.getLog(ScriptCommand.class);
@@ -66,21 +65,6 @@ public class ScriptCommand implements ClientCommand {
private boolean isMultilineScript = false;
private boolean inMultilineScript = false;
- public ScriptEngine getScriptEngine() {
- if (jsEngine == null) {
- try {
- jsEngine = ScriptEngineFactory.getScriptEngine("JavaScript",
- new PackageFinder(Arrays.asList(getLibDir())), null);
- } catch (ScriptException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- return jsEngine;
- }
-
public String getPromptCommandString() {
return "exec";
}
@@ -100,8 +84,8 @@ public class ScriptCommand implements ClientCommand {
CmdLineParser cmdLineParser = new CmdLineParser();
ScriptCmdLine scriptCmdLine = cmdLineParser.parse(args);
- bindScriptArgs(scriptCmdLine);
- executeUtilScripts();
+ bindScriptArgs(client, scriptCmdLine);
+ executeUtilScripts(client);
FileReader reader = new FileReader(scriptCmdLine.getScriptFileName());
try {
@@ -153,7 +137,7 @@ public class ScriptCommand implements ClientCommand {
try {
- Object result = getScriptEngine().eval(script.toString());
+ Object result = client.getScriptEngine().eval(script.toString());
inMultilineScript = false;
script = new StringBuilder();
if (result != null) {
@@ -199,7 +183,7 @@ public class ScriptCommand implements ClientCommand {
bindings.put("configurationEditor", new ConfigurationEditor(client));
bindings.put("rhq", new Controller(client));
- ScriptEngine engine = getScriptEngine();
+ ScriptEngine engine = client.getScriptEngine();
ScriptEngineFactory.injectStandardBindings(engine, bindings, false);
@@ -212,7 +196,7 @@ public class ScriptCommand implements ClientCommand {
initBindings(client);
} else {
- ScriptEngine engine = getScriptEngine();
+ ScriptEngine engine = client.getScriptEngine();
// remove any current manager bindings from the engine, they may not be valid for the
// new client. The new standard bindings will include any new managers.
@@ -228,12 +212,12 @@ public class ScriptCommand implements ClientCommand {
return;
}
- private void executeUtilScripts() {
+ private void executeUtilScripts(ClientMain client) {
InputStream stream = getClass().getResourceAsStream("test_utils.js");
InputStreamReader reader = new InputStreamReader(stream);
try {
- getScriptEngine().eval(reader);
+ client.getScriptEngine().eval(reader);
} catch (ScriptException e) {
log.warn("An error occurred while executing test_utils.js", e);
}
@@ -254,17 +238,17 @@ public class ScriptCommand implements ClientCommand {
}
- private void bindScriptArgs(ScriptCmdLine cmdLine) {
- bindArgsArray(cmdLine);
+ private void bindScriptArgs(ClientMain client, ScriptCmdLine cmdLine) {
+ bindArgsArray(client, cmdLine);
if (cmdLine.getArgType() == ScriptCmdLine.ArgType.NAMED) {
- bindNamedArgs(cmdLine);
+ bindNamedArgs(client, cmdLine);
}
- getScriptEngine().put("script", new File(cmdLine.getScriptFileName()).getName());
+ client.getScriptEngine().put("script", new File(cmdLine.getScriptFileName()).getName());
}
- private void bindArgsArray(ScriptCmdLine cmdLine) {
+ private void bindArgsArray(ClientMain client, ScriptCmdLine cmdLine) {
String[] args = new String[cmdLine.getArgs().size()];
int i = 0;
@@ -272,19 +256,19 @@ public class ScriptCommand implements ClientCommand {
args[i++] = arg.getValue();
}
- getScriptEngine().put("args", args);
+ client.getScriptEngine().put("args", args);
}
- private void bindNamedArgs(ScriptCmdLine cmdLine) {
+ private void bindNamedArgs(ClientMain client, ScriptCmdLine cmdLine) {
for (ScriptArg arg : cmdLine.getArgs()) {
NamedScriptArg namedArg = (NamedScriptArg) arg;
- getScriptEngine().put(namedArg.getName(), namedArg.getValue());
+ client.getScriptEngine().put(namedArg.getName(), namedArg.getValue());
}
}
- private boolean executeScriptFile(Reader reader, ClientMain client) {
+ private boolean executeScriptFile( Reader reader, ClientMain client) {
try {
- Object result = getScriptEngine().eval(reader);
+ Object result = client.getScriptEngine().eval(reader);
if (result != null) {
if (client.isInteractiveMode()) {
new TabularWriter(client.getPrintWriter()).print(result);
@@ -313,13 +297,4 @@ public class ScriptCommand implements ClientCommand {
return "Execute a statement or a script. The following service managers are available: "
+ Arrays.toString(RhqManagers.values());
}
-
- public ScriptContext getContext() {
- return getScriptEngine().getContext();
- }
-
- private File getLibDir() {
- String cwd = System.getProperty("user.dir");
- return new File(cwd, "lib");
- }
}
diff --git a/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java b/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
index 4120f2d..fe109a8 100644
--- a/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
+++ b/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
@@ -35,10 +35,11 @@ import javax.script.Bindings;
public class ScriptCommandTest {
ScriptCommand cmd;
+ ClientMain client;
@Test(enabled=false)
public void executeShouldSetDefaultBindings() throws Exception {
- ClientMain client = createClient();
+ client = createClient();
cmd = new ScriptCommand();
String script = "exec var x = 1;";
String[] args = asList(script).toArray(new String[] {});
@@ -61,7 +62,7 @@ public class ScriptCommandTest {
}
void assertSubjectBoundToScript() {
- ScriptEngine scriptEngine = cmd.getScriptEngine();
+ ScriptEngine scriptEngine = client.getScriptEngine();
Object subject = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE).get("subject");
assertNotNull(subject, "Expected variable 'subject' to be bound to script in global scope");
@@ -72,7 +73,7 @@ public class ScriptCommandTest {
}
void assertManagersBoundToScript() {
- ScriptEngine scriptEngine = cmd.getScriptEngine();
+ ScriptEngine scriptEngine = client.getScriptEngine();
List<String> mgrsNotBound = new ArrayList<String>();
for (RhqManagers mgr : RhqManagers.values()) {
@@ -88,7 +89,7 @@ public class ScriptCommandTest {
}
void assertPrettyWriterBoundToScript() {
- ScriptEngine scriptEngine = cmd.getScriptEngine();
+ ScriptEngine scriptEngine = client.getScriptEngine();
Object writer = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE).get("pretty");
assertNotNull(writer, "Expected variable 'pretty' to be bound to script in global scope");
@@ -99,7 +100,7 @@ public class ScriptCommandTest {
}
void assertScriptUtilsBoundToScript() {
- ScriptEngine scriptEngine = cmd.getScriptEngine();
+ ScriptEngine scriptEngine = client.getScriptEngine();
Object scriptUtil = scriptEngine.get("scriptUtil");
assertNotNull(scriptUtil, "Expected variable 'scriptUtil' to be bound to script in engine scope");
@@ -110,7 +111,7 @@ public class ScriptCommandTest {
}
void assertIsDefinedFunctionBoundToScript() {
- ScriptEngine scriptEngine = cmd.getScriptEngine();
+ ScriptEngine scriptEngine = client.getScriptEngine();
Object function = scriptEngine.get("isDefined");
assertNotNull(function, "Expected function 'isDefined' to be bound to script in engine scope");
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
index 1569896..f8beb28 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
@@ -19,11 +19,28 @@
package org.rhq.scripting;
+import java.util.List;
+
/**
- * TODO This will hook into the interactive code completion provided by the CLI.
- *
+ * An interface for performing code completion in a given language.
+ * This inspired by the jline's <code>Completor</code> interface but
+ * is defined separately so that we don't introduce a dependency on
+ * jline where it doesn't make sense.
+ *
* @author Lukas Krejci
*/
public interface CodeCompletion {
+ /**
+ * Generates the completion candidates and fills the supplied list with them.
+ *
+ * @param context the context of the code completion, usually that is the current
+ * statement being edited by the user
+ * @param cursorPosition the position of the cursor inside the context
+ * @param completions this should be a list of strings but is intentionally left raw
+ * so that this interface is compatible with jline's <code>Completor</code>.
+ * @return the character index in the context for which the completion candidates were
+ * actually generated (might be different from the cursorPosition).
+ */
+ int complete(String context, int cursorPosition, @SuppressWarnings("rawtypes") List candidates);
}
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
index 3286f39..9365304 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
@@ -20,6 +20,7 @@
package org.rhq.scripting;
import java.lang.reflect.Method;
+import java.security.PermissionCollection;
import java.util.Set;
import javax.script.ScriptEngine;
@@ -33,7 +34,20 @@ import javax.script.ScriptException;
*/
public interface ScriptEngineInitializer {
- ScriptEngine instantiate(Set<String> packages) throws ScriptException;
+ /**
+ * Instantiates a new script engine, makes the provided java packages "imported" into the context
+ * (i.e. classes from those packages can be instantiated without providing the full class name)
+ * and makes the script engine use the scriptSourceProvider to locate scripts.
+ *
+ * @param packages the list of java packages to be imported in the context
+ * @param scriptSourceProvider the provider of the sources of scripts - can be null to use no
+ * script source provider and depend on the default module loading mechanisms of the script language
+ * @param permissions the security permissions the script engine should execute the script with, can be null
+ * in which case the script engine is unsecured
+ * @return a newly instantiated script engine configured as above
+ * @throws ScriptException
+ */
+ ScriptEngine instantiate(Set<String> packages, ScriptSourceProvider scriptSourceProvider, PermissionCollection permissions) throws ScriptException;
/**
* This function returns a definition string in the script engine's language
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
new file mode 100644
index 0000000..276e385
--- /dev/null
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
@@ -0,0 +1,35 @@
+/*
+ * 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.scripting;
+
+import java.io.Reader;
+import java.net.URI;
+
+/**
+ * Scripts in RHQ can be stored in various locations or maybe not even in the filesystem.
+ * Implementations of this interface can be used to provide the contents of the scripts
+ * based on URIs.
+ *
+ * @author Lukas Krejci
+ */
+public interface ScriptSourceProvider {
+
+ Reader getScriptSource(URI location);
+}
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/util/SandboxedScriptEngine.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/util/SandboxedScriptEngine.java
new file mode 100644
index 0000000..857c6f1
--- /dev/null
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/util/SandboxedScriptEngine.java
@@ -0,0 +1,224 @@
+/*
+ * 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.scripting.util;
+
+import java.io.Reader;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
+import java.security.cert.Certificate;
+import java.util.Arrays;
+import java.util.Collection;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptException;
+
+/**
+ * This is a decorator class for any other {@link ScriptEngine} implementation
+ * that runs any of the eval methods with the defined set of {@link Permission}s.
+ * <p>
+ * For the permissions to have any effect, a SecurityManager has to be installed
+ * in the current VM.
+ * <p>
+ * This class is provided in hopes that it can help provide security to script engines
+ * that do not directly implement some kind of security measures.
+ *
+ * @author Lukas Krejci
+ */
+public class SandboxedScriptEngine implements ScriptEngine {
+
+ private ScriptEngine engine;
+ private AccessControlContext accessControlContext;
+
+ public SandboxedScriptEngine(ScriptEngine engine) {
+ this.engine = engine;
+ }
+
+ public SandboxedScriptEngine(ScriptEngine engine, PermissionCollection permissions) {
+ this(engine);
+ setPermissions(permissions);
+ }
+
+ public SandboxedScriptEngine(ScriptEngine engine, Collection<? extends Permission> permissions) {
+ this(engine);
+ setPermissions(permissions);
+ }
+
+ public void setPermissions(Permission... permissions) {
+ setPermissions(Arrays.asList(permissions));
+ }
+
+ public void setPermissions(Collection<? extends Permission> permissions) {
+ Permissions ps = new Permissions();
+ for(Permission p : permissions) {
+ ps.add(p);
+ }
+
+ setPermissions(ps);
+ }
+
+ public void setPermissions(PermissionCollection permissions) {
+ CodeSource cs = new CodeSource(null, (Certificate[]) null);
+
+ ProtectionDomain domain = new ProtectionDomain(cs, permissions);
+ accessControlContext = new AccessControlContext(new ProtectionDomain[] { domain });
+ }
+
+ @Override
+ public Object eval(final String script, final ScriptContext context) throws ScriptException {
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ @Override
+ public Object run() throws Exception {
+ return engine.eval(script, context);
+ }
+ }, accessControlContext);
+ } catch (PrivilegedActionException e) {
+ throw transfer(e);
+ }
+ }
+
+ @Override
+ public Object eval(final Reader reader, final ScriptContext context) throws ScriptException {
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ @Override
+ public Object run() throws Exception {
+ return engine.eval(reader, context);
+ }
+ }, accessControlContext);
+ } catch (PrivilegedActionException e) {
+ throw transfer(e);
+ }
+ }
+
+ @Override
+ public Object eval(final String script) throws ScriptException {
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ @Override
+ public Object run() throws Exception {
+ return engine.eval(script);
+ }
+ }, accessControlContext);
+ } catch (PrivilegedActionException e) {
+ throw transfer(e);
+ }
+ }
+
+ @Override
+ public Object eval(final Reader reader) throws ScriptException {
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ @Override
+ public Object run() throws Exception {
+ return engine.eval(reader);
+ }
+ }, accessControlContext);
+ } catch (PrivilegedActionException e) {
+ throw transfer(e);
+ }
+ }
+
+ @Override
+ public Object eval(final String script, final Bindings n) throws ScriptException {
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ @Override
+ public Object run() throws Exception {
+ return engine.eval(script, n);
+ }
+ }, accessControlContext);
+ } catch (PrivilegedActionException e) {
+ throw transfer(e);
+ }
+ }
+
+ @Override
+ public Object eval(final Reader reader, final Bindings n) throws ScriptException {
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ @Override
+ public Object run() throws Exception {
+ return engine.eval(reader, n);
+ }
+ }, accessControlContext);
+ } catch (PrivilegedActionException e) {
+ throw transfer(e);
+ }
+ }
+
+ @Override
+ public void put(String key, Object value) {
+ engine.put(key, value);
+ }
+
+ @Override
+ public Object get(String key) {
+ return engine.get(key);
+ }
+
+ @Override
+ public Bindings getBindings(int scope) {
+ return engine.getBindings(scope);
+ }
+
+ @Override
+ public void setBindings(Bindings bindings, int scope) {
+ engine.setBindings(bindings, scope);
+ }
+
+ @Override
+ public Bindings createBindings() {
+ return engine.createBindings();
+ }
+
+ @Override
+ public ScriptContext getContext() {
+ return engine.getContext();
+ }
+
+ @Override
+ public void setContext(ScriptContext context) {
+ engine.setContext(context);
+ }
+
+ @Override
+ public ScriptEngineFactory getFactory() {
+ return engine.getFactory();
+ }
+
+ private static ScriptException transfer(PrivilegedActionException e) {
+ if (e.getCause() instanceof ScriptException) {
+ return (ScriptException) e.getCause();
+ } else {
+ return new ScriptException(e);
+ }
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index 8a5d96a..e813d3b 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -23,7 +23,8 @@
<version>1.7R3</version>
</dependency>
- <!-- JSR 223 support for Rhino -->
+<!-- we no longer depend on Phobos because we now bundle the Phobos script engine with
+ our own modifications.
<dependency>
<groupId>com.sun.phobos</groupId>
<artifactId>phobos-js</artifactId>
@@ -35,7 +36,7 @@
</exclusion>
</exclusions>
</dependency>
-
+ -->
</dependencies>
<build>
@@ -44,6 +45,9 @@
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+ <argLine>-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>
</plugin>
</plugins>
diff --git a/modules/enterprise/scripting/javascript/src/main/java/com/sun/phobos/script/javascript/PrintHavingRhinoScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/com/sun/phobos/script/javascript/PrintHavingRhinoScriptEngine.java
deleted file mode 100644
index 5a176fd..0000000
--- a/modules/enterprise/scripting/javascript/src/main/java/com/sun/phobos/script/javascript/PrintHavingRhinoScriptEngine.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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 com.sun.phobos.script.javascript;
-
-import javax.script.ScriptContext;
-
-import org.mozilla.javascript.Context;
-import org.mozilla.javascript.Scriptable;
-
-/**
- * We want our script engine to mimic the real JDK one as close as
- * possible.
- *
- * The Phobos impl of the script engine leaves out the predefined
- * print() and println() functions, but we really want them.
- *
- * To add them back we need to override a package-private method
- * in the phobos script engine.
- *
- * @author Lukas Krejci
- */
-public class PrintHavingRhinoScriptEngine extends RhinoScriptEngine {
-
- //copied over from the JDK's impl of RhinoScriptEngine
- private static final String printSource =
- "function print(str, newline) { \n" +
- " if (typeof(str) == 'undefined') { \n" +
- " str = 'undefined'; \n" +
- " } else if (str == null) { \n" +
- " str = 'null'; \n" +
- " } \n" +
- " var out = context.getWriter(); \n" +
- " out.print(String(str)); \n" +
- " if (newline) out.print('\\n'); \n" +
- " out.flush(); \n" +
- "}\n" +
- "function println(str) { \n" +
- " print(str, true); \n" +
- "}";
-
- @Override
- Scriptable getRuntimeScope(ScriptContext ctxt) {
- Scriptable newScope = super.getRuntimeScope(ctxt);
-
- Context cx = enterContext();
- try {
- cx.evaluateString(newScope, printSource, "print", 1, null);
-
- return newScope;
- } finally {
- Context.exit();
- }
- }
-}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
index 803225f..771ec1f 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
@@ -20,6 +20,14 @@
package org.rhq.scripting.javascript;
import java.lang.reflect.Method;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.PermissionCollection;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
+import java.security.cert.Certificate;
import java.util.Collections;
import java.util.Set;
@@ -28,6 +36,9 @@ import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.rhq.scripting.ScriptEngineInitializer;
+import org.rhq.scripting.ScriptSourceProvider;
+import org.rhq.scripting.javascript.engine.RhinoScriptEngine;
+import org.rhq.scripting.javascript.util.ScriptSourceToModuleSourceProviderAdapter;
/**
*
@@ -39,16 +50,34 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
private static final String WRAPPED_EXCEPTION_PREFIX = "Wrapped ";
private ScriptEngineManager engineManager = new ScriptEngineManager();
-
+
@Override
- public ScriptEngine instantiate(Set<String> packages) throws ScriptException {
- ScriptEngine eng = engineManager.getEngineByName("rhino-nonjdk");
+ public ScriptEngine instantiate(final Set<String> packages, final ScriptSourceProvider scriptSourceProvider,
+ PermissionCollection permissions) throws ScriptException {
- for(String pkg : packages) {
- eng.eval("importPackage(" + pkg + ")");
+ if (permissions == null) {
+ return instantiateUnsecured(packages, scriptSourceProvider);
+ } else {
+ try {
+ CodeSource cs = new CodeSource(null, (Certificate[]) null);
+ ProtectionDomain securityDomain = new ProtectionDomain(cs, permissions);
+
+ AccessControlContext acc = new AccessControlContext(new ProtectionDomain[] { securityDomain });
+
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<ScriptEngine>() {
+ @Override
+ public ScriptEngine run() throws Exception {
+ return instantiateUnsecured(packages, scriptSourceProvider);
+ }
+ }, acc);
+ } catch (PrivilegedActionException e) {
+ if (e.getCause() instanceof ScriptException) {
+ throw (ScriptException) e.getCause();
+ } else {
+ throw new ScriptException("Script execution failed.");
+ }
+ }
}
-
- return eng;
}
@Override
@@ -56,50 +85,69 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
if (methods.size() == 0) {
return Collections.emptySet();
}
-
+
String methodName = methods.iterator().next().getName();
-
+
StringBuilder functionBuilder = new StringBuilder("function ");
functionBuilder.append(methodName).append("() { switch(arguments.length) { ");
-
- for(Method method : methods) {
+
+ for (Method method : methods) {
int argCnt = method.getParameterTypes().length;
functionBuilder.append("case ").append(argCnt).append(": ");
functionBuilder.append("return ").append(boundObjectName).append(".").append(methodName).append("(");
- for(int i = 0; i < argCnt; ++i) {
+ for (int i = 0; i < argCnt; ++i) {
if (i > 0) {
functionBuilder.append(", ");
}
-
+
functionBuilder.append("arguments[").append(i).append("]");
}
-
+
functionBuilder.append("); break; ");
}
-
+
functionBuilder.append(" default: throw \"Unsupported number of parameters.\"; } }");
-
+
return Collections.singleton(functionBuilder.toString());
}
-
+
@Override
public String extractUserFriendlyErrorMessage(ScriptException e) {
String errorMessage = e.getMessage();
-
+
int wrappedIdx = errorMessage.lastIndexOf(WRAPPED_EXCEPTION_PREFIX);
-
+
if (wrappedIdx < 0) {
return errorMessage;
}
-
- errorMessage = errorMessage.substring(wrappedIdx + WRAPPED_EXCEPTION_PREFIX.length());
-
+
+ errorMessage = errorMessage.substring(wrappedIdx + WRAPPED_EXCEPTION_PREFIX.length());
+
int sourceInfoStartIdx = errorMessage.indexOf(" (<Unknown source>#");
-
+
if (sourceInfoStartIdx >= 0) {
errorMessage = errorMessage.substring(0, sourceInfoStartIdx);
}
-
+
return errorMessage;
}
+
+ private ScriptEngine instantiateUnsecured(Set<String> packages, ScriptSourceProvider scriptSourceProvider)
+ throws ScriptException {
+ RhinoScriptEngine eng = (RhinoScriptEngine) engineManager.getEngineByName("rhino-nonjdk");
+
+ if (eng == null) {
+ throw new IllegalStateException("Failed to instantiate the 'rhino-nonjdk' script engine. This means that either the required library is missing from the classpath or that there are some security issues preventing it from being instantiated.");
+ }
+
+ if (scriptSourceProvider != null) {
+ eng.setModuleSourceProvider(new ScriptSourceToModuleSourceProviderAdapter(scriptSourceProvider));
+ }
+
+ for (String pkg : packages) {
+ eng.eval("importPackage(" + pkg + ")");
+ }
+
+ return eng;
+ }
}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
index 8d9e4b7..984e5fc 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
@@ -32,7 +32,7 @@ public class JsEngineProvider implements ScriptEngineProvider {
@Override
public String getSupportedLanguage() {
- return "JavaScript";
+ return "javascript";
}
@Override
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/Main.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/Main.java
deleted file mode 100644
index 6bbf542..0000000
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/Main.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.scripting.javascript;
-
-import java.io.PrintWriter;
-
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-
-/**
- *
- *
- * @author Lukas Krejci
- */
-public class Main {
-
- public static void main(String[] args) throws Exception {
- ScriptEngineManager manager = new ScriptEngineManager();
- ScriptEngine engine = manager.getEngineByName("rhino-nonjdk");
-
- engine.getContext().setWriter(new PrintWriter(System.out, true));
- engine.eval("importPackage(java.lang); println('ahoj')");
- }
-}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngine.java
deleted file mode 100644
index ed8a33f..0000000
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngine.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.scripting.javascript;
-
-import com.sun.phobos.script.javascript.PrintHavingRhinoScriptEngine;
-
-/**
- *
- *
- * @author Lukas Krejci
- */
-public class ScriptEngine extends PrintHavingRhinoScriptEngine {
-
- private ScriptEngineFactory factory;
-
- @Override
- public ScriptEngineFactory getFactory() {
- if (factory == null) {
- factory = new ScriptEngineFactory();
- }
-
- return factory;
- }
-
- void setFactory(ScriptEngineFactory factory) {
- this.factory = factory;
- }
-}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngineFactory.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngineFactory.java
deleted file mode 100644
index 824f97a..0000000
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngineFactory.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.scripting.javascript;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import javax.script.ScriptEngine;
-
-import com.sun.phobos.script.javascript.RhinoScriptEngineFactory;
-
-import org.mozilla.javascript.Context;
-
-/**
- *
- *
- * @author Lukas Krejci
- */
-public class ScriptEngineFactory extends RhinoScriptEngineFactory {
-
- private static final List<String> NAMES;
- private static final String ENGINE_VERSION;
- private static final String LANGUAGE_VERSION;
- static {
- Context.enter();
- ENGINE_VERSION = Context.getCurrentContext().getImplementationVersion();
- int ver = Context.getCurrentContext().getLanguageVersion();
- Context.exit();
-
- String version = null;
- if (ver == 0) {
- version = "1.7";
- } else {
- //the versions are formatted like 170 for 1.7, 180 for 1.8, etc
- int major = ver / 100;
- int minor = (ver - 100) / 10;
- version = major + "." + minor;
- }
-
- LANGUAGE_VERSION = version;
-
- NAMES = Collections.unmodifiableList(Arrays.asList("rhino-nonjdk"));
-
- }
-
- @Override
- public List<String> getNames() {
- return NAMES;
- }
-
- @Override
- public Object getParameter(String key) {
- if (ScriptEngine.ENGINE_VERSION.equals(key)) {
- return ENGINE_VERSION;
- } else if (ScriptEngine.LANGUAGE_VERSION.equals(key)) {
- return LANGUAGE_VERSION;
- } else {
- return super.getParameter(key);
- }
- }
-
- @Override
- public ScriptEngine getScriptEngine() {
- org.rhq.scripting.javascript.ScriptEngine engine = new org.rhq.scripting.javascript.ScriptEngine();
- engine.setFactory(this);
- return engine;
- }
-}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/ExternalScriptable.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/ExternalScriptable.java
new file mode 100644
index 0000000..e14dc4b
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/ExternalScriptable.java
@@ -0,0 +1,496 @@
+/*
+ * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met: Redistributions of source code
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of
+ * is contributors may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.rhq.scripting.javascript.engine;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.NativeJavaClass;
+import org.mozilla.javascript.ScriptRuntime;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+import org.mozilla.javascript.Wrapper;
+
+/**
+ * ExternalScriptable is an implementation of Scriptable
+ * backed by a JSR 223 Bindings instance.
+ *
+ * @author Mike Grogan
+ * @author A. Sundararajan
+ * @since 1.6
+ */
+final class ExternalScriptable implements Scriptable {
+ /* Underlying ScriptContext that we use to store
+ * named variables of this scope.
+ */
+ private ScriptContext context;
+
+ /* JavaScript allows variables to be named as numbers (indexed
+ * properties). This way arrays, objects (scopes) are treated uniformly.
+ * Note that JSR 223 API supports only String named variables and
+ * so we can't store these in Bindings. Also, JavaScript allows name
+ * of the property name to be even empty String! Again, JSR 223 API
+ * does not support empty name. So, we use the following fallback map
+ * to store such variables of this scope. This map is not exposed to
+ * JSR 223 API. We can just script objects "as is" and need not convert.
+ */
+ private Map indexedProps;
+
+ // my prototype
+ private Scriptable prototype;
+ // my parent scope, if any
+ private Scriptable parent;
+
+ ExternalScriptable(ScriptContext context) {
+ this(context, new HashMap());
+ }
+
+ ExternalScriptable(ScriptContext context, Map indexedProps) {
+ if (context == null) {
+ throw new NullPointerException("context is null");
+ }
+ this.context = context;
+ this.indexedProps = indexedProps;
+ }
+
+ ScriptContext getContext() {
+ return context;
+ }
+
+ private boolean isInIndexedProps(Object key) {
+ return indexedProps != null && indexedProps.containsKey(key);
+ }
+
+ private boolean isEmpty(String name) {
+ return name.equals("");
+ }
+
+ /**
+ * Return the name of the class.
+ */
+ @Override
+ public String getClassName() {
+ return "Global";
+ }
+
+ /**
+ * Returns the value of the named property or NOT_FOUND.
+ *
+ * If the property was created using defineProperty, the
+ * appropriate getter method is called.
+ *
+ * @param name the name of the property
+ * @param start the object in which the lookup began
+ * @return the value of the property (may be null), or NOT_FOUND
+ */
+ @Override
+ public synchronized Object get(String name, Scriptable start) {
+ if (isEmpty(name)) {
+ if (indexedProps.containsKey(name)) {
+ return indexedProps.get(name);
+ } else {
+ return NOT_FOUND;
+ }
+ } else {
+ synchronized (context) {
+ int scope = context.getAttributesScope(name);
+ if (scope != -1) {
+ Object value = context.getAttribute(name, scope);
+ return Context.javaToJS(value, this);
+ } else {
+ return NOT_FOUND;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the value of the indexed property or NOT_FOUND.
+ *
+ * @param index the numeric index for the property
+ * @param start the object in which the lookup began
+ * @return the value of the property (may be null), or NOT_FOUND
+ */
+ @Override
+ public synchronized Object get(int index, Scriptable start) {
+ Integer key = new Integer(index);
+ if (indexedProps.containsKey(index)) {
+ return indexedProps.get(key);
+ } else {
+ return NOT_FOUND;
+ }
+ }
+
+ /**
+ * Returns true if the named property is defined.
+ *
+ * @param name the name of the property
+ * @param start the object in which the lookup began
+ * @return true if and only if the property was found in the object
+ */
+ @Override
+ public synchronized boolean has(String name, Scriptable start) {
+ if (isEmpty(name)) {
+ return indexedProps.containsKey(name);
+ } else {
+ synchronized (context) {
+ return context.getAttributesScope(name) != -1;
+ }
+ }
+ }
+
+ /**
+ * Returns true if the property index is defined.
+ *
+ * @param index the numeric index for the property
+ * @param start the object in which the lookup began
+ * @return true if and only if the property was found in the object
+ */
+ @Override
+ public synchronized boolean has(int index, Scriptable start) {
+ Integer key = new Integer(index);
+ return indexedProps.containsKey(key);
+ }
+
+ /**
+ * Sets the value of the named property, creating it if need be.
+ *
+ * @param name the name of the property
+ * @param start the object whose property is being set
+ * @param value value to set the property to
+ */
+ @Override
+ public void put(String name, Scriptable start, Object value) {
+ if (start == this) {
+ synchronized (this) {
+ if (isEmpty(name)) {
+ indexedProps.put(name, value);
+ } else {
+ synchronized (context) {
+ int scope = context.getAttributesScope(name);
+ if (scope == -1) {
+ scope = ScriptContext.ENGINE_SCOPE;
+ }
+ context.setAttribute(name, jsToJava(value), scope);
+ }
+ }
+ }
+ } else {
+ start.put(name, start, value);
+ }
+ }
+
+ /**
+ * Sets the value of the indexed property, creating it if need be.
+ *
+ * @param index the numeric index for the property
+ * @param start the object whose property is being set
+ * @param value value to set the property to
+ */
+ @Override
+ public void put(int index, Scriptable start, Object value) {
+ if (start == this) {
+ synchronized (this) {
+ indexedProps.put(new Integer(index), value);
+ }
+ } else {
+ start.put(index, start, value);
+ }
+ }
+
+ /**
+ * Removes a named property from the object.
+ *
+ * If the property is not found, no action is taken.
+ *
+ * @param name the name of the property
+ */
+ @Override
+ public synchronized void delete(String name) {
+ if (isEmpty(name)) {
+ indexedProps.remove(name);
+ } else {
+ synchronized (context) {
+ int scope = context.getAttributesScope(name);
+ if (scope != -1) {
+ context.removeAttribute(name, scope);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes the indexed property from the object.
+ *
+ * If the property is not found, no action is taken.
+ *
+ * @param index the numeric index for the property
+ */
+ @Override
+ public void delete(int index) {
+ indexedProps.remove(new Integer(index));
+ }
+
+ /**
+ * Get the prototype of the object.
+ * @return the prototype
+ */
+ @Override
+ public Scriptable getPrototype() {
+ return prototype;
+ }
+
+ /**
+ * Set the prototype of the object.
+ * @param prototype the prototype to set
+ */
+ @Override
+ public void setPrototype(Scriptable prototype) {
+ this.prototype = prototype;
+ }
+
+ /**
+ * Get the parent scope of the object.
+ * @return the parent scope
+ */
+ @Override
+ public Scriptable getParentScope() {
+ return parent;
+ }
+
+ /**
+ * Set the parent scope of the object.
+ * @param parent the parent scope to set
+ */
+ @Override
+ public void setParentScope(Scriptable parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Get an array of property ids.
+ *
+ * Not all property ids need be returned. Those properties
+ * whose ids are not returned are considered non-enumerable.
+ *
+ * @return an array of Objects. Each entry in the array is either
+ * a java.lang.String or a java.lang.Number
+ */
+ @Override
+ public synchronized Object[] getIds() {
+ String[] keys = getAllKeys();
+ int size = keys.length + indexedProps.size();
+ Object[] res = new Object[size];
+ System.arraycopy(keys, 0, res, 0, keys.length);
+ int i = keys.length;
+ // now add all indexed properties
+ for (Object index : indexedProps.keySet()) {
+ res[i++] = index;
+ }
+ return res;
+ }
+
+ /**
+ * Get the default value of the object with a given hint.
+ * The hints are String.class for type String, Number.class for type
+ * Number, Scriptable.class for type Object, and Boolean.class for
+ * type Boolean. <p>
+ *
+ * A <code>hint</code> of null means "no hint".
+ *
+ * See ECMA 8.6.2.6.
+ *
+ * @param hint the type hint
+ * @return the default value
+ */
+ @Override
+ public Object getDefaultValue(Class typeHint) {
+ for (int i=0; i < 2; i++) {
+ boolean tryToString;
+ if (typeHint == ScriptRuntime.StringClass) {
+ tryToString = (i == 0);
+ } else {
+ tryToString = (i == 1);
+ }
+
+ String methodName;
+ Object[] args;
+ if (tryToString) {
+ methodName = "toString";
+ args = ScriptRuntime.emptyArgs;
+ } else {
+ methodName = "valueOf";
+ args = new Object[1];
+ String hint;
+ if (typeHint == null) {
+ hint = "undefined";
+ } else if (typeHint == ScriptRuntime.StringClass) {
+ hint = "string";
+ } else if (typeHint == ScriptRuntime.ScriptableClass) {
+ hint = "object";
+ } else if (typeHint == ScriptRuntime.FunctionClass) {
+ hint = "function";
+ } else if (typeHint == ScriptRuntime.BooleanClass
+ || typeHint == Boolean.TYPE)
+ {
+ hint = "boolean";
+ } else if (typeHint == ScriptRuntime.NumberClass ||
+ typeHint == ScriptRuntime.ByteClass ||
+ typeHint == Byte.TYPE ||
+ typeHint == ScriptRuntime.ShortClass ||
+ typeHint == Short.TYPE ||
+ typeHint == ScriptRuntime.IntegerClass ||
+ typeHint == Integer.TYPE ||
+ typeHint == ScriptRuntime.FloatClass ||
+ typeHint == Float.TYPE ||
+ typeHint == ScriptRuntime.DoubleClass ||
+ typeHint == Double.TYPE)
+ {
+ hint = "number";
+ } else {
+ throw Context.reportRuntimeError(
+ "Invalid JavaScript value of type " +
+ typeHint.toString());
+ }
+ args[0] = hint;
+ }
+ Object v = ScriptableObject.getProperty(this, methodName);
+ if (!(v instanceof Function))
+ continue;
+ Function fun = (Function) v;
+ Context cx = RhinoScriptEngine.enterContext();
+ try {
+ v = fun.call(cx, fun.getParentScope(), this, args);
+ } finally {
+ cx.exit();
+ }
+ if (v != null) {
+ if (!(v instanceof Scriptable)) {
+ return v;
+ }
+ if (typeHint == ScriptRuntime.ScriptableClass
+ || typeHint == ScriptRuntime.FunctionClass)
+ {
+ return v;
+ }
+ if (tryToString && v instanceof Wrapper) {
+ // Let a wrapped java.lang.String pass for a primitive
+ // string.
+ Object u = ((Wrapper)v).unwrap();
+ if (u instanceof String)
+ return u;
+ }
+ }
+ }
+ // fall through to error
+ String arg = (typeHint == null) ? "undefined" : typeHint.getName();
+ throw Context.reportRuntimeError(
+ "Cannot find default value for object " + arg);
+ }
+
+ /**
+ * Implements the instanceof operator.
+ *
+ * @param instance The value that appeared on the LHS of the instanceof
+ * operator
+ * @return true if "this" appears in value's prototype chain
+ *
+ */
+ @Override
+ public boolean hasInstance(Scriptable instance) {
+ // Default for JS objects (other than Function) is to do prototype
+ // chasing.
+ Scriptable proto = instance.getPrototype();
+ while (proto != null) {
+ if (proto.equals(this)) return true;
+ proto = proto.getPrototype();
+ }
+ return false;
+ }
+
+ private String[] getAllKeys() {
+ ArrayList<String> list = new ArrayList<String>();
+ synchronized (context) {
+ for (int scope : context.getScopes()) {
+ Bindings bindings = context.getBindings(scope);
+ if (bindings != null) {
+ list.ensureCapacity(bindings.size());
+ for (String key : bindings.keySet()) {
+ list.add(key);
+ }
+ }
+ }
+ }
+ String[] res = new String[list.size()];
+ list.toArray(res);
+ return res;
+ }
+
+ /**
+ * We convert script values to the nearest Java value.
+ * We unwrap wrapped Java objects so that access from
+ * Bindings.get() would return "workable" value for Java.
+ * But, at the same time, we need to make few special cases
+ * and hence the following function is used.
+ */
+ private Object jsToJava(Object jsObj) {
+ if (jsObj instanceof Wrapper) {
+ Wrapper njb = (Wrapper) jsObj;
+ /* importClass feature of ImporterTopLevel puts
+ * NativeJavaClass in global scope. If we unwrap
+ * it, importClass won't work.
+ */
+ if (njb instanceof NativeJavaClass) {
+ return njb;
+ }
+
+ /* script may use Java primitive wrapper type objects
+ * (such as java.lang.Integer, java.lang.Boolean etc)
+ * explicitly. If we unwrap, then these script objects
+ * will become script primitive types. For example,
+ *
+ * var x = new java.lang.Double(3.0); print(typeof x);
+ *
+ * will print 'number'. We don't want that to happen.
+ */
+ Object obj = njb.unwrap();
+ if (obj instanceof Number || obj instanceof String ||
+ obj instanceof Boolean || obj instanceof Character) {
+ // special type wrapped -- we just leave it as is.
+ return njb;
+ } else {
+ // return unwrapped object for any other object.
+ return obj;
+ }
+ } else { // not-a-Java-wrapper
+ return jsObj;
+ }
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/JSAdapter.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/JSAdapter.java
new file mode 100644
index 0000000..b56bab7
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/JSAdapter.java
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met: Redistributions of source code
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of
+ * is contributors may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.rhq.scripting.javascript.engine;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.NativeArray;
+import org.mozilla.javascript.NativeJavaArray;
+import org.mozilla.javascript.RhinoException;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+
+/**
+ * JSAdapter is java.lang.reflect.Proxy equivalent for JavaScript. JSAdapter
+ * calls specially named JavaScript methods on an adaptee object when property
+ * access is attempted on it.
+ *
+ * Example:
+ *
+ * var y = {
+ * __get__ : function (name) { ... }
+ * __has__ : function (name) { ... }
+ * __put__ : function (name, value) {...}
+ * __delete__ : function (name) { ... }
+ * __getIds__ : function () { ... }
+ * };
+ *
+ * var x = new JSAdapter(y);
+ *
+ * x.i; // calls y.__get__
+ * i in x; // calls y.__has__
+ * x.p = 10; // calls y.__put__
+ * delete x.p; // calls y.__delete__
+ * for (i in x) { print(i); } // calls y.__getIds__
+ *
+ * If a special JavaScript method is not found in the adaptee, then JSAdapter
+ * forwards the property access to the adaptee itself.
+ *
+ * JavaScript caller of adapter object is isolated from the fact that
+ * the property access/mutation/deletion are really calls to
+ * JavaScript methods on adaptee. Use cases include 'smart'
+ * properties, property access tracing/debugging, encaptulation with
+ * easy client access - in short JavaScript becomes more "Self" like.
+ *
+ * Note that Rhino already supports special properties like __proto__
+ * (to set, get prototype), __parent__ (to set, get parent scope). We
+ * follow the same double underscore nameing convention here. Similarly
+ * the name JSAdapter is derived from JavaAdapter -- which is a facility
+ * to extend, implement Java classes/interfaces by JavaScript.
+ *
+ * @version 1.0
+ * @author A. Sundararajan
+ * @since 1.6
+ */
+public final class JSAdapter implements Scriptable, Function {
+ private JSAdapter(Scriptable obj) {
+ setAdaptee(obj);
+ }
+
+ // initializer to setup JSAdapter prototype in the given scope
+ public static void init(Context cx, Scriptable scope, boolean sealed)
+ throws RhinoException {
+ JSAdapter obj = new JSAdapter(cx.newObject(scope));
+ obj.setParentScope(scope);
+ obj.setPrototype(getFunctionPrototype(scope));
+ obj.isPrototype = true;
+ ScriptableObject.defineProperty(scope, "JSAdapter", obj,
+ ScriptableObject.DONTENUM);
+ }
+
+ @Override
+ public String getClassName() {
+ return "JSAdapter";
+ }
+
+ @Override
+ public Object get(String name, Scriptable start) {
+ Function func = getAdapteeFunction(GET_PROP);
+ if (func != null) {
+ return call(func, new Object[] { name });
+ } else {
+ start = getAdaptee();
+ return start.get(name, start);
+ }
+ }
+
+ @Override
+ public Object get(int index, Scriptable start) {
+ Function func = getAdapteeFunction(GET_PROP);
+ if (func != null) {
+ return call(func, new Object[] { new Integer(index) });
+ } else {
+ start = getAdaptee();
+ return start.get(index, start);
+ }
+ }
+
+ @Override
+ public boolean has(String name, Scriptable start) {
+ Function func = getAdapteeFunction(HAS_PROP);
+ if (func != null) {
+ Object res = call(func, new Object[] { name });
+ return Context.toBoolean(res);
+ } else {
+ start = getAdaptee();
+ return start.has(name, start);
+ }
+ }
+
+ @Override
+ public boolean has(int index, Scriptable start) {
+ Function func = getAdapteeFunction(HAS_PROP);
+ if (func != null) {
+ Object res = call(func, new Object[] { new Integer(index) });
+ return Context.toBoolean(res);
+ } else {
+ start = getAdaptee();
+ return start.has(index, start);
+ }
+ }
+
+ @Override
+ public void put(String name, Scriptable start, Object value) {
+ if (start == this) {
+ Function func = getAdapteeFunction(PUT_PROP);
+ if (func != null) {
+ call(func, new Object[] { name, value });
+ } else {
+ start = getAdaptee();
+ start.put(name, start, value);
+ }
+ } else {
+ start.put(name, start, value);
+ }
+ }
+
+ @Override
+ public void put(int index, Scriptable start, Object value) {
+ if (start == this) {
+ Function func = getAdapteeFunction(PUT_PROP);
+ if( func != null) {
+ call(func, new Object[] { new Integer(index), value });
+ } else {
+ start = getAdaptee();
+ start.put(index, start, value);
+ }
+ } else {
+ start.put(index, start, value);
+ }
+ }
+
+ @Override
+ public void delete(String name) {
+ Function func = getAdapteeFunction(DEL_PROP);
+ if (func != null) {
+ call(func, new Object[] { name });
+ } else {
+ getAdaptee().delete(name);
+ }
+ }
+
+ @Override
+ public void delete(int index) {
+ Function func = getAdapteeFunction(DEL_PROP);
+ if (func != null) {
+ call(func, new Object[] { new Integer(index) });
+ } else {
+ getAdaptee().delete(index);
+ }
+ }
+
+ @Override
+ public Scriptable getPrototype() {
+ return prototype;
+ }
+
+ @Override
+ public void setPrototype(Scriptable prototype) {
+ this.prototype = prototype;
+ }
+
+ @Override
+ public Scriptable getParentScope() {
+ return parent;
+ }
+
+ @Override
+ public void setParentScope(Scriptable parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public Object[] getIds() {
+ Function func = getAdapteeFunction(GET_PROPIDS);
+ if (func != null) {
+ Object val = call(func, new Object[0]);
+ // in most cases, adaptee would return native JS array
+ if (val instanceof NativeArray) {
+ NativeArray array = (NativeArray) val;
+ Object[] res = new Object[(int)array.getLength()];
+ for (int index = 0; index < res.length; index++) {
+ res[index] = mapToId(array.get(index, array));
+ }
+ return res;
+ } else if (val instanceof NativeJavaArray) {
+ // may be attempt wrapped Java array
+ Object tmp = ((NativeJavaArray)val).unwrap();
+ Object[] res;
+ if (tmp.getClass() == Object[].class) {
+ Object[] array = (Object[]) tmp;
+ res = new Object[array.length];
+ for (int index = 0; index < array.length; index++) {
+ res[index] = mapToId(array[index]);
+ }
+ } else {
+ // just return an empty array
+ res = Context.emptyArgs;
+ }
+ return res;
+ } else {
+ // some other return type, just return empty array
+ return Context.emptyArgs;
+ }
+ } else {
+ return getAdaptee().getIds();
+ }
+ }
+
+ @Override
+ public boolean hasInstance(Scriptable scriptable) {
+ if (scriptable instanceof JSAdapter) {
+ return true;
+ } else {
+ Scriptable proto = scriptable.getPrototype();
+ while (proto != null) {
+ if (proto.equals(this)) return true;
+ proto = proto.getPrototype();
+ }
+ return false;
+ }
+ }
+
+ @Override
+ public Object getDefaultValue(Class hint) {
+ return getAdaptee().getDefaultValue(hint);
+ }
+
+ @Override
+ public Object call(Context cx, Scriptable scope, Scriptable thisObj,
+ Object[] args)
+ throws RhinoException {
+ if (isPrototype) {
+ return construct(cx, scope, args);
+ } else {
+ Scriptable tmp = getAdaptee();
+ if (tmp instanceof Function) {
+ return ((Function)tmp).call(cx, scope, tmp, args);
+ } else {
+ throw Context.reportRuntimeError("TypeError: not a function");
+ }
+ }
+ }
+
+ @Override
+ public Scriptable construct(Context cx, Scriptable scope, Object[] args)
+ throws RhinoException {
+ if (isPrototype) {
+ Scriptable topLevel = ScriptableObject.getTopLevelScope(scope);
+ JSAdapter newObj;
+ if (args.length > 0) {
+ newObj = new JSAdapter(Context.toObject(args[0], topLevel));
+ } else {
+ throw Context.reportRuntimeError("JSAdapter requires adaptee");
+ }
+ return newObj;
+ } else {
+ Scriptable tmp = getAdaptee();
+ if (tmp instanceof Function) {
+ return ((Function)tmp).construct(cx, scope, args);
+ } else {
+ throw Context.reportRuntimeError("TypeError: not a constructor");
+ }
+ }
+ }
+
+ public Scriptable getAdaptee() {
+ return adaptee;
+ }
+
+ public void setAdaptee(Scriptable adaptee) {
+ if (adaptee == null) {
+ throw new NullPointerException("adaptee can not be null");
+ }
+ this.adaptee = adaptee;
+ }
+
+ //-- internals only below this point
+
+ // map a property id. Property id can only be an Integer or String
+ private Object mapToId(Object tmp) {
+ if (tmp instanceof Double) {
+ return new Integer(((Double)tmp).intValue());
+ } else {
+ return Context.toString(tmp);
+ }
+ }
+
+ private static Scriptable getFunctionPrototype(Scriptable scope) {
+ return ScriptableObject.getFunctionPrototype(scope);
+ }
+
+ private Function getAdapteeFunction(String name) {
+ Object o = ScriptableObject.getProperty(getAdaptee(), name);
+ return (o instanceof Function)? (Function)o : null;
+ }
+
+ private Object call(Function func, Object[] args) {
+ Context cx = Context.getCurrentContext();
+ Scriptable thisObj = getAdaptee();
+ Scriptable scope = func.getParentScope();
+ try {
+ return func.call(cx, scope, thisObj, args);
+ } catch (RhinoException re) {
+ throw Context.reportRuntimeError(re.getMessage());
+ }
+ }
+
+ private Scriptable prototype;
+ private Scriptable parent;
+ private Scriptable adaptee;
+ private boolean isPrototype;
+
+ // names of adaptee JavaScript functions
+ private static final String GET_PROP = "__get__";
+ private static final String HAS_PROP = "__has__";
+ private static final String PUT_PROP = "__put__";
+ private static final String DEL_PROP = "__delete__";
+ private static final String GET_PROPIDS = "__getIds__";
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoCompiledScript.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoCompiledScript.java
new file mode 100644
index 0000000..23d6b3c
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoCompiledScript.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met: Redistributions of source code
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of
+ * is contributors may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.rhq.scripting.javascript.engine;
+import javax.script.CompiledScript;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.JavaScriptException;
+import org.mozilla.javascript.RhinoException;
+import org.mozilla.javascript.Script;
+import org.mozilla.javascript.Scriptable;
+
+import org.rhq.scripting.javascript.engine.util.ExtendedScriptException;
+
+/**
+ * Represents compiled JavaScript code.
+ *
+ * @author Mike Grogan
+ * @version 1.0
+ * @since 1.6
+ */
+final class RhinoCompiledScript extends CompiledScript {
+
+ private RhinoScriptEngine engine;
+ private Script script;
+ private final static boolean DEBUG = RhinoScriptEngine.DEBUG;
+
+ RhinoCompiledScript(RhinoScriptEngine engine, Script script) {
+ this.engine = engine;
+ this.script = script;
+ }
+
+ @Override
+ public Object eval(ScriptContext context) throws ScriptException {
+
+ Object result = null;
+ Context cx = RhinoScriptEngine.enterContext();
+ try {
+
+ Scriptable scope = engine.getRuntimeScope(context);
+ Object ret = script.exec(cx, scope);
+ result = engine.unwrapReturnValue(ret);
+ } catch (JavaScriptException jse) {
+ if (DEBUG) jse.printStackTrace();
+ int line = (line = jse.lineNumber()) == 0 ? -1 : line;
+ Object value = jse.getValue();
+ String str = (value != null && value.getClass().getName().equals("org.mozilla.javascript.NativeError") ?
+ value.toString() :
+ jse.toString());
+ throw new ExtendedScriptException(jse, str, jse.sourceName(), line);
+ } catch (RhinoException re) {
+ if (DEBUG) re.printStackTrace();
+ int line = (line = re.lineNumber()) == 0 ? -1 : line;
+ throw new ExtendedScriptException(re, re.toString(), re.sourceName(), line);
+ } finally {
+ Context.exit();
+ }
+
+ return result;
+ }
+
+ @Override
+ public ScriptEngine getEngine() {
+ return engine;
+ }
+
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
new file mode 100644
index 0000000..a2dca22
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
@@ -0,0 +1,687 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2006-2011 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+/*
+ * Portions Copyright 2012 RHQ Management Platform
+ */
+
+/*
+ * RHQ Management Platform elects to include this software in this distribution
+ * under the GPL Version 2 license.
+ */
+
+
+
+package org.rhq.scripting.javascript.engine;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.script.AbstractScriptEngine;
+import javax.script.Bindings;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.Invocable;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptException;
+import javax.script.SimpleBindings;
+import javax.script.SimpleScriptContext;
+
+import org.mozilla.javascript.Callable;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.ContextFactory;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.ImporterTopLevel;
+import org.mozilla.javascript.JavaScriptException;
+import org.mozilla.javascript.LazilyLoadedCtor;
+import org.mozilla.javascript.RhinoException;
+import org.mozilla.javascript.Script;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+import org.mozilla.javascript.Synchronizer;
+import org.mozilla.javascript.Undefined;
+import org.mozilla.javascript.Wrapper;
+import org.mozilla.javascript.commonjs.module.RequireBuilder;
+import org.mozilla.javascript.commonjs.module.provider.ModuleSourceProvider;
+import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider;
+import org.mozilla.javascript.commonjs.module.provider.UrlModuleSourceProvider;
+
+import org.rhq.scripting.javascript.engine.util.ExtendedScriptException;
+import org.rhq.scripting.javascript.engine.util.InterfaceImplementor;
+
+
+/**
+ * Implementation of <code>ScriptEngine</code> using the Mozilla Rhino
+ * interpreter.
+ *
+ * @author Mike Grogan
+ * @author A. Sundararajan
+ * @version 1.0
+ * @since 1.6
+ *
+ * Modified for phobos to remove some of the restrictions.
+ * Modified to allow subclassing and preprocessing of script source code.
+ * Modified to avoid using the RhinoTopLevel class, since that introduces
+ * a circularity that prevents objects from being garbage collected.
+ *
+ * @author Roberto Chinnici
+ *
+ * Modified so that the top level scope is an ImportTopLevel instance so
+ * that importClass and importPackage functions are available.
+ * Modified so that the "print" and "println" functions work the same as with
+ * the stock javascript script engine provided by the JVM.
+ * Modified to include the "require()" function by default.
+ * Modified to tighten the security of the script execution by running it in an
+ * AccessControlContext active at the time of the script engine creation.
+ *
+ * @author Lukas Krejci
+ */
+public class RhinoScriptEngine extends AbstractScriptEngine
+ implements Invocable, Compilable {
+
+ public static final boolean DEBUG = false;
+ private static final String TOPLEVEL_SCRIPT_NAME = "META-INF/toplevel.js";
+
+ private static class TopLevelScope extends ImporterTopLevel {
+
+ private static final long serialVersionUID = 1L;
+
+ private AccessControlContext acc;
+
+ public TopLevelScope(AccessControlContext acc, Context cx, boolean sealed) {
+ super(cx, sealed);
+ this.acc = acc;
+ }
+
+ public AccessControlContext getAccessControlContext() {
+ return acc;
+ }
+ }
+
+ /* Scope where standard JavaScript objects and our
+ * extensions to it are stored. Note that these are not
+ * user defined engine level global variables. These are
+ * variables have to be there on all compliant ECMAScript
+ * scopes. We put these standard objects in this top level.
+ */
+ private TopLevelScope topLevel;
+
+ /* map used to store indexed properties in engine scope
+ * refer to comment on 'indexedProps' in ExternalScriptable.java.
+ */
+ private Map<?, ?> indexedProps;
+
+ private ScriptEngineFactory factory;
+ private InterfaceImplementor implementor;
+
+ //LK - added support for CommonJS modules
+ private RequireBuilder requireBuilder;
+
+ //LK - make all the scripts run in an access control context
+ static {
+ ContextFactory.initGlobal(new ContextFactory() {
+ @Override
+ protected Object doTopCall(final Callable callable,
+ final Context cx, final Scriptable scope,
+ final Scriptable thisObj, final Object[] args) {
+ AccessControlContext accCtxt = null;
+ Scriptable global = ScriptableObject.getTopLevelScope(scope);
+ Scriptable globalProto = global.getPrototype();
+ if (globalProto instanceof TopLevelScope) {
+ accCtxt = ((TopLevelScope)globalProto).getAccessControlContext();
+ }
+
+ if (accCtxt != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ return superDoTopCall(callable, cx, scope, thisObj, args);
+ }
+ }, accCtxt);
+ } else {
+ return superDoTopCall(callable, cx, scope, thisObj, args);
+ }
+ }
+
+ private Object superDoTopCall(final Callable callable,
+ final Context cx, final Scriptable scope,
+ final Scriptable thisObj, final Object[] args) {
+
+ return super.doTopCall(callable, cx, scope, thisObj, args);
+ }
+ });
+ }
+
+ /*
+ // in Phobos we want to support all javascript features
+ static {
+ ContextFactory.initGlobal(new ContextFactory() {
+ protected Context makeContext() {
+ Context cx = super.makeContext();
+ cx.setClassShutter(RhinoClassShutter.getInstance());
+ cx.setWrapFactory(RhinoWrapFactory.getInstance());
+ return cx;
+ }
+
+ public boolean hasFeature(Context cx, int feature) {
+ // we do not support E4X (ECMAScript for XML)!
+ if (feature == Context.FEATURE_E4X) {
+ return false;
+ } else {
+ return super.hasFeature(cx, feature);
+ }
+ }
+ });
+ }
+
+ static {
+ if (USE_INTERPRETER) {
+ ContextFactory.initGlobal(new ContextFactory() {
+ protected Context makeContext() {
+ Context cx = super.makeContext();
+ cx.setOptimizationLevel(-1);
+ return cx;
+ }
+ });
+ }
+ }
+ */
+
+ public RhinoScriptEngine() {
+ this(new UrlModuleSourceProvider(null, Arrays.asList(new File("./").toURI())));
+ }
+
+ /**
+ * Creates a new instance of RhinoScriptEngine with given moduleSourceProvider as the "locator"
+ * for the CommonJS modules.
+ *
+ * @param moduleSourceProvider the implementation able to locate sources of modules for CommonJS.
+ */
+ public RhinoScriptEngine(ModuleSourceProvider moduleSourceProvider) {
+
+ Context cx = enterContext();
+
+ try {
+ /*
+ * RRC - modified this code to register JSAdapter and some functions
+ * directly, without using a separate RhinoTopLevel class
+ */
+ /*
+ * LK - made the topLevel at the the ImporterTopLevel so that
+ * the circular reference to this script engine is avoided but
+ * all the functions (importClass, importPackage) are available.
+ * Also provide the security features similar to the bundled script engine.
+ */
+ topLevel = new TopLevelScope(AccessController.getContext(), cx, System.getSecurityManager() != null);
+
+ requireBuilder = new RequireBuilder();
+ setModuleSourceProvider(moduleSourceProvider);
+
+ new LazilyLoadedCtor(topLevel, "JSAdapter",
+ "org.rhq.scripting.javascript.engine.JSAdapter",
+ false);
+ // add top level functions
+ String names[] = { "bindings", "scope", "sync" };
+ topLevel.defineFunctionProperties(names, RhinoScriptEngine.class, ScriptableObject.DONTENUM);
+
+ processAllTopLevelScripts(cx);
+ } finally {
+ Context.exit();
+ }
+
+ indexedProps = new HashMap<Object, Object>();
+
+ //construct object used to implement getInterface
+ implementor = new InterfaceImplementor(this) {
+ @Override
+ protected Object convertResult(Method method, Object res)
+ throws ScriptException {
+ Class<?> desiredType = method.getReturnType();
+ if (desiredType == Void.TYPE) {
+ return null;
+ } else {
+ return Context.jsToJava(res, desiredType);
+ }
+ }
+ };
+ }
+
+ public void setModuleSourceProvider(ModuleSourceProvider provider) {
+ requireBuilder.setModuleScriptProvider(new SoftCachingModuleScriptProvider(provider));
+ }
+
+ @Override
+ public Object eval(Reader reader, ScriptContext ctxt)
+ throws ScriptException {
+ Object ret;
+
+ Context cx = enterContext();
+ try {
+ Scriptable scope = getRuntimeScope(ctxt);
+ scope.put("context", scope, ctxt);
+
+ // NOTE (RRC) - why does it look straight into the engine instead of asking
+ // the given ScriptContext object?
+ // Modified to use the context
+ // String filename = (String) get(ScriptEngine.FILENAME);
+ String filename = null;
+ if (ctxt != null && ctxt.getBindings(ScriptContext.ENGINE_SCOPE) != null) {
+ filename = (String) ctxt.getBindings(ScriptContext.ENGINE_SCOPE).get(RhinoScriptEngine.FILENAME);
+ }
+ if (filename == null) {
+ filename = (String) get(RhinoScriptEngine.FILENAME);
+ }
+
+ filename = filename == null ? "<Unknown source>" : filename;
+ ret = cx.evaluateReader(scope, preProcessScriptSource(reader), filename , 1, null);
+ } catch (JavaScriptException jse) {
+ if (DEBUG) jse.printStackTrace();
+ int line = (line = jse.lineNumber()) == 0 ? -1 : line;
+ Object value = jse.getValue();
+ String str = (value != null && value.getClass().getName().equals("org.mozilla.javascript.NativeError") ?
+ value.toString() :
+ jse.toString());
+ throw new ExtendedScriptException(jse, str, jse.sourceName(), line);
+ } catch (RhinoException re) {
+ if (DEBUG) re.printStackTrace();
+ int line = (line = re.lineNumber()) == 0 ? -1 : line;
+ throw new ExtendedScriptException(re, re.toString(), re.sourceName(), line);
+ } catch (IOException ee) {
+ throw new ScriptException(ee);
+ } finally {
+ Context.exit();
+ }
+
+ return unwrapReturnValue(ret);
+ }
+
+ @Override
+ public Object eval(String script, ScriptContext ctxt) throws ScriptException {
+ if (script == null) {
+ throw new NullPointerException("null script");
+ }
+ return eval(new StringReader(script), ctxt);
+ }
+
+ @Override
+ public ScriptEngineFactory getFactory() {
+ if (factory != null) {
+ return factory;
+ } else {
+ return new RhinoScriptEngineFactory();
+ }
+ }
+
+ @Override
+ public Bindings createBindings() {
+ return new SimpleBindings();
+ }
+
+ //Invocable methods
+ @Override
+ public Object invokeFunction(String name, Object... args)
+ throws ScriptException, NoSuchMethodException {
+ return invokeMethod(null, name, args);
+ }
+
+ @Override
+ public Object invokeMethod(Object thiz, String name, Object... args)
+ throws ScriptException, NoSuchMethodException {
+
+ Context cx = enterContext();
+ try {
+ if (name == null) {
+ throw new NullPointerException("method name is null");
+ }
+
+ if (thiz != null && !(thiz instanceof Scriptable)) {
+ thiz = Context.toObject(thiz, topLevel);
+ }
+
+ Scriptable engineScope = getRuntimeScope(context);
+ Scriptable localScope = (thiz != null)? (Scriptable) thiz :
+ engineScope;
+ Object obj = ScriptableObject.getProperty(localScope, name);
+ if (! (obj instanceof Function)) {
+ throw new NoSuchMethodException("no such method: " + name);
+ }
+
+ Function func = (Function) obj;
+ Scriptable scope = func.getParentScope();
+ if (scope == null) {
+ scope = engineScope;
+ }
+ Object result = func.call(cx, scope, localScope,
+ wrapArguments(args));
+ return unwrapReturnValue(result);
+ } catch (JavaScriptException jse) {
+ if (DEBUG) jse.printStackTrace();
+ int line = (line = jse.lineNumber()) == 0 ? -1 : line;
+ Object value = jse.getValue();
+ String str = (value != null && value.getClass().getName().equals("org.mozilla.javascript.NativeError") ?
+ value.toString() :
+ jse.toString());
+ throw new ExtendedScriptException(jse, str, jse.sourceName(), line);
+ } catch (RhinoException re) {
+ if (DEBUG) re.printStackTrace();
+ int line = (line = re.lineNumber()) == 0 ? -1 : line;
+ throw new ExtendedScriptException(re, re.toString(), re.sourceName(), line);
+ } finally {
+ Context.exit();
+ }
+ }
+
+ @Override
+ public <T> T getInterface(Class<T> clasz) {
+ try {
+ return implementor.getInterface(null, clasz);
+ } catch (ScriptException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public <T> T getInterface(Object thiz, Class<T> clasz) {
+ if (thiz == null) {
+ throw new IllegalArgumentException("script object can not be null");
+ }
+
+ try {
+ return implementor.getInterface(thiz, clasz);
+ } catch (ScriptException e) {
+ return null;
+ }
+ }
+
+ // RRC - not used
+ // LK - make it used again and modified to conform to the JVM version.
+ private static final String printSource =
+ "function print(str, newline) { \n" +
+ " if (typeof(str) == 'undefined') { \n" +
+ " str = 'undefined'; \n" +
+ " } else if (str == null) { \n" +
+ " str = 'null'; \n" +
+ " } \n" +
+ " var out = context.getWriter(); \n" +
+ " out.print(String(str)); \n" +
+ " if (newline) out.print('\\n'); \n" +
+ " out.flush(); \n" +
+ "}\n" +
+ "function println(str) { \n" +
+ " print(str, true); \n" +
+ "}";
+
+ Scriptable getRuntimeScope(ScriptContext ctxt) {
+ if (ctxt == null) {
+ throw new NullPointerException("null script context");
+ }
+
+ // we create a scope for the given ScriptContext
+ Scriptable newScope = new ExternalScriptable(ctxt, indexedProps);
+
+ // Set the prototype of newScope to be 'topLevel' so that
+ // JavaScript standard objects are visible from the scope.
+ newScope.setPrototype(topLevel);
+
+ // define "context" variable in the new scope
+ newScope.put("context", newScope, ctxt);
+
+
+ // RRC - save some time and don't define print
+ // LK - these functions are assumed by a lot of code so let's
+ // make them available
+ // define "print" function in the new scope
+ Context cx = enterContext();
+ try {
+ cx.evaluateString(newScope, printSource, "print", 1, null);
+ requireBuilder.createRequire(cx, topLevel).install(newScope);
+ } finally {
+ Context.exit();
+ }
+
+ return newScope;
+ }
+
+
+ //Compilable methods
+ @Override
+ public CompiledScript compile(String script) throws ScriptException {
+ return compile(new StringReader(script));
+ }
+
+ @Override
+ public CompiledScript compile(java.io.Reader script) throws ScriptException {
+ CompiledScript ret = null;
+ Context cx = enterContext();
+
+ try {
+ String filename = (String) get(RhinoScriptEngine.FILENAME);
+ if (filename == null) {
+ filename = "<Unknown Source>";
+ }
+
+ Script scr = cx.compileReader(preProcessScriptSource(script), filename, 1, null);
+ ret = new RhinoCompiledScript(this, scr);
+ } catch (Exception e) {
+ if (DEBUG) e.printStackTrace();
+ throw new ScriptException(e);
+ } finally {
+ Context.exit();
+ }
+ return ret;
+ }
+
+
+ //package-private helpers
+
+ static Context enterContext() {
+ // call this always so that initializer of this class runs
+ // and initializes custom wrap factory and class shutter.
+ return Context.enter();
+ }
+
+ void setEngineFactory(ScriptEngineFactory fac) {
+ factory = fac;
+ }
+
+ Object[] wrapArguments(Object[] args) {
+ if (args == null) {
+ return Context.emptyArgs;
+ }
+ Object[] res = new Object[args.length];
+ for (int i = 0; i < res.length; i++) {
+ res[i] = Context.javaToJS(args[i], topLevel);
+ }
+ return res;
+ }
+
+ Object unwrapReturnValue(Object result) {
+ if (result instanceof Wrapper) {
+ result = ( (Wrapper) result).unwrap();
+ }
+
+ return result instanceof Undefined ? null : result;
+ }
+
+ protected Reader preProcessScriptSource(Reader reader) throws ScriptException {
+ return reader;
+ }
+
+ protected void processAllTopLevelScripts(Context cx) {
+ processTopLevelScript(TOPLEVEL_SCRIPT_NAME, cx);
+ }
+
+ protected void processTopLevelScript(String scriptName, Context cx) {
+ InputStream toplevelScript = this.getClass().getClassLoader().getResourceAsStream(scriptName);
+ if (toplevelScript != null) {
+ Reader reader = new InputStreamReader(toplevelScript);
+ try {
+ cx.evaluateReader(topLevel, reader, scriptName, 1, null);
+ }
+ catch (Exception e) {
+ if (DEBUG) e.printStackTrace();
+ }
+ finally {
+ try {
+ toplevelScript.close();
+ }
+ catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ /**
+ * The bindings function takes a JavaScript scope object
+ * of type ExternalScriptable and returns the underlying Bindings
+ * instance.
+ *
+ * var page = scope(pageBindings);
+ * with (page) {
+ * // code that uses page scope
+ * }
+ * var b = bindings(page);
+ * // operate on bindings here.
+ */
+ public static Object bindings(Context cx, Scriptable thisObj, Object[] args,
+ Function funObj) {
+ if (args.length == 1) {
+ Object arg = args[0];
+ if (arg instanceof Wrapper) {
+ arg = ((Wrapper)arg).unwrap();
+ }
+ if (arg instanceof ExternalScriptable) {
+ ScriptContext ctx = ((ExternalScriptable)arg).getContext();
+ Bindings bind = ctx.getBindings(ScriptContext.ENGINE_SCOPE);
+ return Context.javaToJS(bind,
+ ScriptableObject.getTopLevelScope(thisObj));
+ }
+ }
+ return Context.getUndefinedValue();
+ }
+
+ /**
+ * The scope function creates a new JavaScript scope object
+ * with given Bindings object as backing store. This can be used
+ * to create a script scope based on arbitrary Bindings instance.
+ * For example, in webapp scenario, a 'page' level Bindings instance
+ * may be wrapped as a scope and code can be run in JavaScripe 'with'
+ * statement:
+ *
+ * var page = scope(pageBindings);
+ * with (page) {
+ * // code that uses page scope
+ * }
+ */
+ public static Object scope(Context cx, Scriptable thisObj, Object[] args,
+ Function funObj) {
+ if (args.length == 1) {
+ Object arg = args[0];
+ if (arg instanceof Wrapper) {
+ arg = ((Wrapper)arg).unwrap();
+ }
+ if (arg instanceof Bindings) {
+ ScriptContext ctx = new SimpleScriptContext();
+ ctx.setBindings((Bindings)arg, ScriptContext.ENGINE_SCOPE);
+ Scriptable res = new ExternalScriptable(ctx);
+ res.setPrototype(ScriptableObject.getObjectPrototype(thisObj));
+ res.setParentScope(ScriptableObject.getTopLevelScope(thisObj));
+ return res;
+ }
+ }
+ return Context.getUndefinedValue();
+ }
+
+ /**
+ * The sync function creates a synchronized function (in the sense
+ * of a Java synchronized method) from an existing function. The
+ * new function synchronizes on the <code>this</code> object of
+ * its invocation.
+ * js> var o = { f : sync(function(x) {
+ * print("entry");
+ * Packages.java.lang.Thread.sleep(x*1000);
+ * print("exit");
+ * })};
+ * js> thread(function() {o.f(5);});
+ * entry
+ * js> thread(function() {o.f(5);});
+ * js>
+ * exit
+ * entry
+ * exit
+ */
+ public static Object sync(Context cx, Scriptable thisObj, Object[] args,
+ Function funObj) {
+ if (args.length == 1 && args[0] instanceof Function) {
+ return new Synchronizer((Function)args[0]);
+ } else {
+ throw Context.reportRuntimeError("wrong argument(s) for sync");
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (args.length == 0) {
+ System.out.println("No file specified");
+ return;
+ }
+
+ InputStreamReader r = new InputStreamReader(new FileInputStream(args[0]));
+ RhinoScriptEngine engine = new RhinoScriptEngine();
+
+ SimpleScriptContext context = new SimpleScriptContext();
+ engine.put(RhinoScriptEngine.FILENAME, args[0]);
+ engine.eval(r, context);
+ // added this statement to save some typing to most script authors
+ context.getWriter().flush();
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngineFactory.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngineFactory.java
new file mode 100644
index 0000000..2db613b
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngineFactory.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met: Redistributions of source code
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of
+ * is contributors may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.rhq.scripting.javascript.engine;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+import javax.script.ScriptEngine;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.ContextFactory;
+
+import org.rhq.scripting.javascript.engine.util.ScriptEngineFactoryBase;
+
+/**
+ * Factory to create RhinoScriptEngine
+ *
+ * @version 1.0
+ * @author Mike Grogan
+ * @since 1.6
+ */
+public class RhinoScriptEngineFactory extends ScriptEngineFactoryBase {
+
+ public static final String USE_INTERPRETER_SYSTEM_PROPERTY = "org.rhq.scrpipting.javascript.useInterpreter";
+
+ private Properties properties;
+ private boolean initialized;
+ private ContextFactory.Listener listener;
+
+ public RhinoScriptEngineFactory() {
+ }
+
+ public RhinoScriptEngineFactory(ContextFactory.Listener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public List<String> getExtensions() {
+ return extensions;
+ }
+
+ @Override
+ public List<String> getMimeTypes() {
+ return mimeTypes;
+ }
+
+ @Override
+ public List<String> getNames() {
+ return names;
+ }
+
+ @Override
+ public Object getParameter(String key) {
+ if (key.equals(ScriptEngine.NAME)) {
+ return "javascript";
+ } else if (key.equals(ScriptEngine.ENGINE)) {
+ return "Mozilla Rhino";
+ } else if (key.equals(ScriptEngine.ENGINE_VERSION)) {
+ return "1.6R7";
+ } else if (key.equals(ScriptEngine.LANGUAGE)) {
+ return "ECMAScript";
+ } else if (key.equals(ScriptEngine.LANGUAGE_VERSION)) {
+ return "1.6";
+ } else if (key.equals("THREADING")) {
+ return "MULTITHREADED";
+ } else {
+ throw new IllegalArgumentException("Invalid key");
+ }
+ }
+
+ @Override
+ public ScriptEngine getScriptEngine() {
+ RhinoScriptEngine ret = new RhinoScriptEngine();
+ ret.setEngineFactory(this);
+ return ret;
+ }
+
+ public void initialize() {
+ if (!initialized) {
+ if ("true".equals(getProperty(USE_INTERPRETER_SYSTEM_PROPERTY))) {
+ if (!ContextFactory.hasExplicitGlobal()) {
+ ContextFactory.initGlobal(new ContextFactory() {
+ @Override
+ protected Context makeContext() {
+ Context cx = super.makeContext();
+ cx.setOptimizationLevel(-1);
+ return cx;
+ }
+ });
+ }
+ }
+ if (listener != null) {
+ ContextFactory.getGlobal().addListener(listener);
+ }
+ initialized = true;
+ }
+ }
+
+ public void destroy() {
+ if (initialized) {
+ if (listener != null) {
+ ContextFactory.getGlobal().removeListener(listener);
+ }
+ initialized = false;
+ }
+ }
+
+ public void setProperties(Properties properties) {
+ this.properties = properties;
+ }
+
+ private String getProperty(String key) {
+ String value = null;
+ if (properties != null) {
+ value = properties.getProperty(key);
+ }
+ if (value == null) {
+ value = System.getProperty(key);
+ }
+ return value;
+ }
+
+ private String getProperty(String name, String defaultValue) {
+ String s = getProperty(name);
+ return (s == null ? defaultValue : s);
+ }
+
+ @Override
+ public String getMethodCallSyntax(String obj, String method, String... args) {
+
+ String ret = obj + "." + method + "(";
+ int len = args.length;
+ if (len == 0) {
+ ret += ")";
+ return ret;
+ }
+
+ for (int i = 0; i < len; i++) {
+ ret += args[i];
+ if (i != len - 1) {
+ ret += ",";
+ } else {
+ ret += ")";
+ }
+ }
+ return ret;
+ }
+
+ @Override
+ public String getOutputStatement(String toDisplay) {
+ return "print(" + toDisplay + ")";
+ }
+
+ @Override
+ public String getProgram(String... statements) {
+ int len = statements.length;
+ String ret = "";
+ for (int i = 0; i < len; i++) {
+ ret += statements[i] + ";";
+ }
+
+ return ret;
+ }
+
+ public static void main(String[] args) {
+ RhinoScriptEngineFactory fact = new RhinoScriptEngineFactory();
+ System.out.println(fact.getParameter(ScriptEngine.ENGINE_VERSION));
+ }
+
+ private static List<String> names;
+ private static List<String> mimeTypes;
+ private static List<String> extensions;
+
+ static {
+ names = new ArrayList<String>(7);
+ names.add("rhino-nonjdk");
+ names.add("js");
+ names.add("rhino");
+ names.add("JavaScript");
+ names.add("javascript");
+ names.add("ECMAScript");
+ names.add("ecmascript");
+ names = Collections.unmodifiableList(names);
+
+ mimeTypes = new ArrayList<String>(4);
+ mimeTypes.add("application/javascript");
+ mimeTypes.add("application/ecmascript");
+ mimeTypes.add("text/javascript");
+ mimeTypes.add("text/ecmascript");
+ mimeTypes = Collections.unmodifiableList(mimeTypes);
+
+ extensions = new ArrayList<String>(1);
+ extensions.add("js");
+ extensions = Collections.unmodifiableList(extensions);
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ExtendedScriptException.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ExtendedScriptException.java
new file mode 100644
index 0000000..2979682
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ExtendedScriptException.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met: Redistributions of source code
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of
+ * is contributors may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.rhq.scripting.javascript.engine.util;
+
+import javax.script.ScriptException;
+
+/**
+ * An extension of javax.script.ScriptException that allows
+ * the cause of an exception to be set.
+ */
+public class ExtendedScriptException extends ScriptException {
+
+ private static final long serialVersionUID = 1L;
+
+ private Throwable cause;
+
+ public ExtendedScriptException(
+ Throwable cause,
+ String message,
+ String fileName,
+ int lineNumber,
+ int columnNumber) {
+ super(message, fileName, lineNumber, columnNumber);
+ this.cause = cause;
+ }
+
+ public ExtendedScriptException(String s) {
+ super(s);
+ }
+
+ public ExtendedScriptException(Exception e) {
+ super(e);
+ }
+
+ public ExtendedScriptException(String message, String fileName, int lineNumber) {
+ super(message, fileName, lineNumber);
+ }
+
+ public ExtendedScriptException(Throwable cause, String message, String fileName, int lineNumber) {
+ super(message, fileName, lineNumber);
+ this.cause = cause;
+ }
+
+ public ExtendedScriptException(String message,
+ String fileName,
+ int lineNumber,
+ int columnNumber) {
+ super(message, fileName, lineNumber, columnNumber);
+ }
+
+ public Throwable getCause() {
+ return cause;
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/InterfaceImplementor.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/InterfaceImplementor.java
new file mode 100644
index 0000000..b4880a7
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/InterfaceImplementor.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met: Redistributions of source code
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of
+ * is contributors may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.rhq.scripting.javascript.engine.util;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import javax.script.Invocable;
+import javax.script.ScriptException;
+
+/*
+ * java.lang.reflect.Proxy based interface implementor. This is meant
+ * to be used to implement Invocable.getInterface.
+ *
+ * @version 1.0
+ * @author Mike Grogan
+ * @since 1.6
+ */
+public class InterfaceImplementor {
+
+ private Invocable engine;
+
+ /** Creates a new instance of Invocable */
+ public InterfaceImplementor(Invocable engine) {
+ this.engine = engine;
+ }
+
+ public class InterfaceImplementorInvocationHandler implements InvocationHandler {
+ private Invocable engine;
+ private Object thiz;
+ public InterfaceImplementorInvocationHandler(Invocable engine, Object thiz) {
+
+ this.engine = engine;
+ this.thiz = thiz;
+ }
+
+ @Override
+ public Object invoke(Object proxy , Method method, Object[] args)
+ throws java.lang.Throwable {
+ // give chance to convert input args
+ args = convertArguments(method, args);
+ Object result = engine.invokeMethod(thiz, method.getName(), args);
+ // give chance to convert the method result
+ return convertResult(method, result);
+ }
+ }
+
+ public <T> T getInterface(Object thiz, Class<T> iface)
+ throws ScriptException {
+ if (iface == null || !iface.isInterface()) {
+ throw new IllegalArgumentException("interface Class expected");
+ }
+ return iface.cast(Proxy.newProxyInstance(iface.getClassLoader(),
+ new Class[]{iface},
+ new InterfaceImplementorInvocationHandler(engine, thiz)));
+ }
+
+ // called to convert method result after invoke
+ protected Object convertResult(Method method, Object res)
+ throws ScriptException {
+ // default is identity conversion
+ return res;
+ }
+
+ // called to convert method arguments before invoke
+ protected Object[] convertArguments(Method method, Object[] args)
+ throws ScriptException {
+ // default is identity conversion
+ return args;
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ScriptEngineFactoryBase.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ScriptEngineFactoryBase.java
new file mode 100644
index 0000000..89f12a9
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ScriptEngineFactoryBase.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met: Redistributions of source code
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of
+ * is contributors may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.rhq.scripting.javascript.engine.util;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+
+/*
+ * Abstract super class for factory implementations.
+ *
+ * @version 1.0
+ * @author Mike Grogan
+ * @since 1.6
+ */
+public abstract class ScriptEngineFactoryBase implements ScriptEngineFactory {
+
+ public String getName() {
+ return (String)getParameter(ScriptEngine.NAME);
+ }
+
+ @Override
+ public String getEngineName() {
+ return (String)getParameter(ScriptEngine.ENGINE);
+ }
+
+ @Override
+ public String getEngineVersion() {
+ return (String)getParameter(ScriptEngine.ENGINE_VERSION);
+ }
+
+ @Override
+ public String getLanguageName() {
+ return (String)getParameter(ScriptEngine.LANGUAGE);
+ }
+
+ @Override
+ public String getLanguageVersion() {
+ return (String)getParameter(ScriptEngine.LANGUAGE_VERSION);
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/util/ScriptSourceToModuleSourceProviderAdapter.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/util/ScriptSourceToModuleSourceProviderAdapter.java
new file mode 100644
index 0000000..fb3926b
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/util/ScriptSourceToModuleSourceProviderAdapter.java
@@ -0,0 +1,75 @@
+/*
+ * 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.scripting.javascript.util;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.mozilla.javascript.commonjs.module.provider.ModuleSource;
+import org.mozilla.javascript.commonjs.module.provider.ModuleSourceProviderBase;
+
+import org.rhq.scripting.ScriptSourceProvider;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class ScriptSourceToModuleSourceProviderAdapter extends ModuleSourceProviderBase {
+ private static final long serialVersionUID = 1L;
+
+ private ScriptSourceProvider scriptSourceProvider;
+
+ public ScriptSourceToModuleSourceProviderAdapter(ScriptSourceProvider provider) {
+ scriptSourceProvider = provider;
+ }
+
+ @Override
+ protected ModuleSource loadFromPrivilegedLocations(String moduleId, Object validator) throws IOException,
+ URISyntaxException {
+
+ //if the URI is absolute, we make sure to define the ModuleSource as sandboxed.
+ //this is done by making the URI a "subpath" of the base.
+ URI uri = new URI(moduleId);
+ URI base = null;
+ if (uri.isAbsolute()) {
+ base = uri;
+ }
+ return loadFromUri(uri, base, validator);
+ }
+
+ @Override
+ protected ModuleSource loadFromUri(URI uri, URI base, Object validator) throws IOException, URISyntaxException {
+ URI fullUri = uri;
+ if (base != null) {
+ fullUri = uri.resolve(base);
+ }
+
+ Reader sourceReader = scriptSourceProvider.getScriptSource(fullUri);
+
+ if (sourceReader == null) {
+ return null;
+ } else {
+ return new ModuleSource(sourceReader, null, uri, base, validator);
+ }
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory b/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
index ab267fe..1480e04 100644
--- a/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
+++ b/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
@@ -1 +1 @@
-org.rhq.scripting.javascript.ScriptEngineFactory
+org.rhq.scripting.javascript.engine.RhinoScriptEngineFactory
diff --git a/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java
new file mode 100644
index 0000000..7ccde17
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.scripting.javascript;
+
+import static org.testng.Assert.*;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+
+import org.testng.annotations.Test;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+@Test
+public class EngineTest {
+
+ public void engineAvailable() throws Exception {
+ assertNotNull(getScriptEngine(), "Failed to obtain the script engine.");
+ }
+
+ public void printFunctionsAvailable() throws Exception {
+ String output = captureScriptOutput("print('a'); println('b');");
+ assertEquals(output, "ab\n", "Unexpected output printed by the print functions.");
+ }
+
+ public void importClassAndImportPackageAvailable() throws Exception {
+ String script = "importClass(java.lang.System); print(System.currentTimeMillis());";
+ String output = captureScriptOutput(script);
+ assertFalse(output.isEmpty(), "importClass function doesn't seem to work.");
+
+ script = "importPackage(java.util); println(new Date);";
+ output = captureScriptOutput(script);
+ assertFalse(output.isEmpty());
+ }
+
+ public void requireFunctionDefined() throws Exception {
+ String output = captureScriptOutput("print(typeof(require))");
+ assertEquals(output, "function", "The require function doesn't seem to be defined.");
+ }
+
+ public void modulesCanBeLoaded() throws Exception {
+ String script = "" +
+ "var m1 = require('target/test-classes/test-module1.js'); \n" +
+ "var m2 = require('target/test-classes/test-module2.js'); \n" +
+ "println(typeof(m1.func1));\n" +
+ "println(typeof(m1.func2));\n" +
+ "println(typeof(m2.func3));\n" +
+ "println(typeof(m2.func4));\n" +
+ "println(typeof(m2.func1));\n" +
+ "println(typeof(m2.func2));\n" +
+ "println(typeof(m1.func3));\n" +
+ "println(typeof(m1.func4));\n";
+ String output = "function\nfunction\nfunction\nfunction\nundefined\nundefined\nundefined\nundefined\n";
+
+ assertEquals(captureScriptOutput(script), output, "Unexpected functions found in modules");
+ }
+
+ private ScriptEngine getScriptEngine() {
+ ScriptEngineManager manager = new ScriptEngineManager();
+ return manager.getEngineByName("rhino-nonjdk");
+ }
+
+ private String captureScriptOutput(String script) throws Exception {
+ ScriptEngine engine = getScriptEngine();
+
+ StringWriter stdOut = new StringWriter();
+ PrintWriter wrt = new PrintWriter(stdOut);
+
+ engine.getContext().setWriter(wrt);
+
+ engine.eval(script);
+
+ return stdOut.toString();
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java
new file mode 100644
index 0000000..3a50839
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java
@@ -0,0 +1,189 @@
+/*
+ * 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.scripting.javascript;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.FilePermission;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.security.Permissions;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.PropertyPermission;
+import java.util.Set;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+import org.testng.annotations.Test;
+
+import org.rhq.scripting.ScriptEngineInitializer;
+import org.rhq.scripting.ScriptSourceProvider;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+@Test
+public class InitializerTest {
+
+ //for Rhino to see this class, it must be public
+ public static class TestClass {
+ public boolean[] functionsCalled;
+
+ public TestClass() {
+ functionsCalled = new boolean[6];
+ }
+
+ public void func1() {
+ functionsCalled[0] = true;
+ }
+
+ public void func2() {
+ functionsCalled[1] = true;
+ }
+
+ public void func3() {
+ functionsCalled[2] = true;
+ }
+
+ public void func3(int a, int b) {
+ functionsCalled[3] = true;
+ }
+
+ public void func3(String a, String b) {
+ functionsCalled[4] = true;
+ }
+
+ public void func3(int a, int b, int c) {
+ functionsCalled[5] = true;
+ }
+ }
+
+ public void engineSecured() throws Exception {
+ Permissions perms = new Permissions();
+ //we need to be able to read files and props so that the default module source provider can work
+ perms.add(new FilePermission("<<ALL FILES>>", "read"));
+ perms.add(new PropertyPermission("*", "read"));
+
+ ScriptEngine eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), null, perms);
+
+ try {
+ eng.eval("java.lang.System.exit(1)");
+ } catch (Exception e) {
+ assertSecurityExceptionPresent(e);
+ }
+ }
+
+ public void scriptSourceProviderApplied() throws Exception {
+
+ String script = "var m = require('rhq://test-module1.js'); m.func1();";
+
+ //first let's try to find the scripts with the default source provider...
+ ScriptEngine eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), null, null);
+ try {
+ eng.eval(script);
+ fail("The module should not have been loaded using the default source provider.");
+ } catch (ScriptException e) {
+ //expected
+ }
+
+ eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), new ScriptSourceProvider() {
+ @Override
+ public Reader getScriptSource(URI location) {
+ if (!"rhq".equals(location.getScheme())) {
+ return null;
+ }
+ String scriptName = location.getSchemeSpecificPart().substring(2); //remove the '//'
+ InputStream src = getClass().getClassLoader().getResourceAsStream(scriptName);
+ return new InputStreamReader(src);
+ }
+ }, null);
+
+ try {
+ eng.eval(script);
+ } catch (ScriptException e) {
+ fail("The module should have been loaded using the custom source provider. Error message: " + e.getMessage(), e);
+ }
+ }
+
+ public void indirectionMethodsValid() throws Exception {
+ JsEngineInitializer initializer = new JsEngineInitializer();
+
+ ScriptEngine eng = initializer.instantiate(Collections.<String>emptySet(), null, null);
+
+ TestClass myObject = new TestClass();
+
+ eng.put("myObject", myObject);
+
+ generateIndirectionMethods(initializer, eng, myObject, "myObject", "func1");
+ generateIndirectionMethods(initializer, eng, myObject, "myObject", "func2");
+ generateIndirectionMethods(initializer, eng, myObject, "myObject", "func3");
+
+ eng.eval("func1(); func2(); func3(); func3(1, 1); func3('a', 'b'); func3(1, 1, 1);");
+
+ assertTrue(myObject.functionsCalled[0], "Function func1() should have been called.");
+ assertTrue(myObject.functionsCalled[1], "Function func2() should have been called.");
+ assertTrue(myObject.functionsCalled[2], "Function func3() should have been called.");
+ assertTrue(myObject.functionsCalled[3], "Function func3(int, int) should have been called.");
+ assertTrue(myObject.functionsCalled[4], "Function func3(String, String) should have been called.");
+ assertTrue(myObject.functionsCalled[5], "Function func3(int, int, int) should have been called.");
+ }
+
+ private void assertSecurityExceptionPresent(Throwable t) {
+ boolean ok = false;
+ while (t != null) {
+ if (t instanceof SecurityException) {
+ ok = true;
+ break;
+ } else if ((t instanceof ScriptException) &&
+ (t.getMessage().contains("java.security.AccessControlException")
+ || t.getMessage().contains("java.lang.SecurityException"))) {
+ ok = true;
+ break;
+ }
+
+ t = t.getCause();
+ }
+
+ assertTrue(ok, "Didn't find a SecurityException, which should have occured.");
+ }
+
+ private void generateIndirectionMethods(ScriptEngineInitializer initializer, ScriptEngine eng, Object object, String objectName, String methodName) throws ScriptException {
+ Set<Method> methods = new HashSet<Method>();
+ for(Method m : object.getClass().getDeclaredMethods()) {
+ if (methodName.equals(m.getName())) {
+ methods.add(m);
+ }
+ }
+
+ eng.put(objectName, object);
+
+ for(String m : initializer.generateIndirectionMethods(objectName, methods)) {
+ eng.eval(m);
+ }
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/test/resources/allow-all.policy b/modules/enterprise/scripting/javascript/src/test/resources/allow-all.policy
new file mode 100644
index 0000000..cb9dbed
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/test/resources/allow-all.policy
@@ -0,0 +1,3 @@
+grant {
+ permission java.security.AllPermission;
+};
diff --git a/modules/enterprise/scripting/javascript/src/test/resources/test-module1.js b/modules/enterprise/scripting/javascript/src/test/resources/test-module1.js
new file mode 100644
index 0000000..7cc760b
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/test/resources/test-module1.js
@@ -0,0 +1,7 @@
+exports.func1 = function() {
+ return "func1";
+}
+
+exports.func2 = function() {
+ return "func2";
+}
\ No newline at end of file
diff --git a/modules/enterprise/scripting/javascript/src/test/resources/test-module2.js b/modules/enterprise/scripting/javascript/src/test/resources/test-module2.js
new file mode 100644
index 0000000..b2ad389
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/test/resources/test-module2.js
@@ -0,0 +1,7 @@
+exports.func3 = function() {
+ return "func3";
+}
+
+exports.func4 = function() {
+ return "func4";
+}
\ No newline at end of file
diff --git a/modules/enterprise/scripting/pom.xml b/modules/enterprise/scripting/pom.xml
index 92b72d4..c786cdc 100644
--- a/modules/enterprise/scripting/pom.xml
+++ b/modules/enterprise/scripting/pom.xml
@@ -13,7 +13,6 @@
<modules>
<module>api</module>
- <module>factory</module>
<module>javascript</module>
</modules>
commit ff78b1e7cf7b64f78fd155752222fba7ad4261f4
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Fri May 18 13:39:27 2012 +0200
An attempt to use Rhino 1.7R3 as a script engine. This will most probably
not work because of the number of changes in behavior between phobos-based
ScriptEngine and the JDK-bundled ScriptEngine.
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index bd0d585..8a5d96a 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -22,6 +22,20 @@
<artifactId>rhino</artifactId>
<version>1.7R3</version>
</dependency>
+
+ <!-- JSR 223 support for Rhino -->
+ <dependency>
+ <groupId>com.sun.phobos</groupId>
+ <artifactId>phobos-js</artifactId>
+ <version>0.6.2</version>
+ <exclusions>
+ <exclusion>
+ <groupId>com.sun.phobos</groupId>
+ <artifactId>phobos-rhino</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
</dependencies>
<build>
diff --git a/modules/enterprise/scripting/javascript/src/main/java/com/sun/phobos/script/javascript/PrintHavingRhinoScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/com/sun/phobos/script/javascript/PrintHavingRhinoScriptEngine.java
new file mode 100644
index 0000000..5a176fd
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/com/sun/phobos/script/javascript/PrintHavingRhinoScriptEngine.java
@@ -0,0 +1,71 @@
+/*
+ * 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 com.sun.phobos.script.javascript;
+
+import javax.script.ScriptContext;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Scriptable;
+
+/**
+ * We want our script engine to mimic the real JDK one as close as
+ * possible.
+ *
+ * The Phobos impl of the script engine leaves out the predefined
+ * print() and println() functions, but we really want them.
+ *
+ * To add them back we need to override a package-private method
+ * in the phobos script engine.
+ *
+ * @author Lukas Krejci
+ */
+public class PrintHavingRhinoScriptEngine extends RhinoScriptEngine {
+
+ //copied over from the JDK's impl of RhinoScriptEngine
+ private static final String printSource =
+ "function print(str, newline) { \n" +
+ " if (typeof(str) == 'undefined') { \n" +
+ " str = 'undefined'; \n" +
+ " } else if (str == null) { \n" +
+ " str = 'null'; \n" +
+ " } \n" +
+ " var out = context.getWriter(); \n" +
+ " out.print(String(str)); \n" +
+ " if (newline) out.print('\\n'); \n" +
+ " out.flush(); \n" +
+ "}\n" +
+ "function println(str) { \n" +
+ " print(str, true); \n" +
+ "}";
+
+ @Override
+ Scriptable getRuntimeScope(ScriptContext ctxt) {
+ Scriptable newScope = super.getRuntimeScope(ctxt);
+
+ Context cx = enterContext();
+ try {
+ cx.evaluateString(newScope, printSource, "print", 1, null);
+
+ return newScope;
+ } finally {
+ Context.exit();
+ }
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
index 3ad2296..803225f 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
@@ -42,7 +42,7 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
@Override
public ScriptEngine instantiate(Set<String> packages) throws ScriptException {
- ScriptEngine eng = engineManager.getEngineByName("JavaScript");
+ ScriptEngine eng = engineManager.getEngineByName("rhino-nonjdk");
for(String pkg : packages) {
eng.eval("importPackage(" + pkg + ")");
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/Main.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/Main.java
new file mode 100644
index 0000000..6bbf542
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/Main.java
@@ -0,0 +1,41 @@
+/*
+ * 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.scripting.javascript;
+
+import java.io.PrintWriter;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class Main {
+
+ public static void main(String[] args) throws Exception {
+ ScriptEngineManager manager = new ScriptEngineManager();
+ ScriptEngine engine = manager.getEngineByName("rhino-nonjdk");
+
+ engine.getContext().setWriter(new PrintWriter(System.out, true));
+ engine.eval("importPackage(java.lang); println('ahoj')");
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngine.java
new file mode 100644
index 0000000..ed8a33f
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngine.java
@@ -0,0 +1,45 @@
+/*
+ * 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.scripting.javascript;
+
+import com.sun.phobos.script.javascript.PrintHavingRhinoScriptEngine;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class ScriptEngine extends PrintHavingRhinoScriptEngine {
+
+ private ScriptEngineFactory factory;
+
+ @Override
+ public ScriptEngineFactory getFactory() {
+ if (factory == null) {
+ factory = new ScriptEngineFactory();
+ }
+
+ return factory;
+ }
+
+ void setFactory(ScriptEngineFactory factory) {
+ this.factory = factory;
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngineFactory.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngineFactory.java
new file mode 100644
index 0000000..824f97a
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngineFactory.java
@@ -0,0 +1,86 @@
+/*
+ * 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.scripting.javascript;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import javax.script.ScriptEngine;
+
+import com.sun.phobos.script.javascript.RhinoScriptEngineFactory;
+
+import org.mozilla.javascript.Context;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class ScriptEngineFactory extends RhinoScriptEngineFactory {
+
+ private static final List<String> NAMES;
+ private static final String ENGINE_VERSION;
+ private static final String LANGUAGE_VERSION;
+ static {
+ Context.enter();
+ ENGINE_VERSION = Context.getCurrentContext().getImplementationVersion();
+ int ver = Context.getCurrentContext().getLanguageVersion();
+ Context.exit();
+
+ String version = null;
+ if (ver == 0) {
+ version = "1.7";
+ } else {
+ //the versions are formatted like 170 for 1.7, 180 for 1.8, etc
+ int major = ver / 100;
+ int minor = (ver - 100) / 10;
+ version = major + "." + minor;
+ }
+
+ LANGUAGE_VERSION = version;
+
+ NAMES = Collections.unmodifiableList(Arrays.asList("rhino-nonjdk"));
+
+ }
+
+ @Override
+ public List<String> getNames() {
+ return NAMES;
+ }
+
+ @Override
+ public Object getParameter(String key) {
+ if (ScriptEngine.ENGINE_VERSION.equals(key)) {
+ return ENGINE_VERSION;
+ } else if (ScriptEngine.LANGUAGE_VERSION.equals(key)) {
+ return LANGUAGE_VERSION;
+ } else {
+ return super.getParameter(key);
+ }
+ }
+
+ @Override
+ public ScriptEngine getScriptEngine() {
+ org.rhq.scripting.javascript.ScriptEngine engine = new org.rhq.scripting.javascript.ScriptEngine();
+ engine.setFactory(this);
+ return engine;
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory b/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
new file mode 100644
index 0000000..ab267fe
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
@@ -0,0 +1 @@
+org.rhq.scripting.javascript.ScriptEngineFactory
commit 13e77125213af769de8f72ff5017458ba81a4cea
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu May 17 10:18:13 2012 +0200
Initial refactoring of the scripting infrastructure to allow language
support to be defined in a standalone module (and allow multiple script
langs in the future).
The ScriptEngineFactory now searches for the supported script langs using
META-INF/services.
The project probably doesn't compile with this commit but this will get
fixed by the future commits.
diff --git a/modules/enterprise/binding/pom.xml b/modules/enterprise/binding/pom.xml
index 7ca5ea1..6683bd8 100644
--- a/modules/enterprise/binding/pom.xml
+++ b/modules/enterprise/binding/pom.xml
@@ -19,6 +19,12 @@
<dependencies>
<dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-scripting-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>${project.groupId}</groupId>
<artifactId>rhq-core-domain</artifactId>
<version>${project.version}</version>
@@ -30,6 +36,14 @@
</exclusions>
</dependency>
+ <!-- Provide a scripting impl for the tests -->
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-scripting-javascript</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>rhq-core-domain</artifactId>
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
index 106c2ae..73ffc9d 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
@@ -37,6 +37,7 @@ import java.security.cert.Certificate;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.ServiceLoader;
import java.util.Set;
import javax.script.Bindings;
@@ -47,10 +48,10 @@ import javax.script.ScriptException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.rhq.bindings.engine.JsEngineInitializer;
-import org.rhq.bindings.engine.ScriptEngineInitializer;
import org.rhq.bindings.util.NoTopLevelIndirection;
import org.rhq.bindings.util.PackageFinder;
+import org.rhq.scripting.ScriptEngineInitializer;
+import org.rhq.scripting.ScriptEngineProvider;
/**
* This is RHQ specific imitation of ScriptEngineFactory.
@@ -68,13 +69,56 @@ import org.rhq.bindings.util.PackageFinder;
public class ScriptEngineFactory {
private static final Log LOG = LogFactory.getLog(ScriptEngineFactory.class);
- private static final ScriptEngineInitializer[] KNOWN_ENGINES = { new JsEngineInitializer() };
+ private static final Map<String, ScriptEngineProvider> KNOWN_PROVIDERS;
+ static {
+ KNOWN_PROVIDERS = new HashMap<String, ScriptEngineProvider>();
+
+ reloadScriptEngineProviders(null);
+ }
private ScriptEngineFactory() {
}
/**
+ * Reloads the list of the known script engine providers using the given classloader
+ * or the current thread's context classloader if it is null.
+ *
+ * @param classLoader the classloader used to find the script engine providers on the classpath
+ *
+ * @throws IllegalStateException if more than 1 script engine provider is found for a single language
+ */
+ public static void reloadScriptEngineProviders(ClassLoader classLoader) {
+ if (classLoader == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ }
+
+ ServiceLoader<ScriptEngineProvider> loader = ServiceLoader.load(ScriptEngineProvider.class, classLoader);
+
+ KNOWN_PROVIDERS.clear();
+
+ for (ScriptEngineProvider provider : loader) {
+ String lang = provider.getSupportedLanguage();
+
+ if (KNOWN_PROVIDERS.containsKey(lang)) {
+ String existing = KNOWN_PROVIDERS.get(lang).getClass().getName();
+ String thisOne = provider.getClass().getName();
+ throw new IllegalStateException("'" + lang + "' scripting language provided by at least 2 providers: '"
+ + existing + "' and '" + thisOne + "'. Only 1 provider per language is allowed.");
+ }
+
+ KNOWN_PROVIDERS.put(lang, provider);
+ }
+ }
+
+ /**
+ * @return the set of the scripting languages supported by this factory
+ */
+ public static Set<String> getSupportedLanguages() {
+ return new HashSet<String>(KNOWN_PROVIDERS.keySet());
+ }
+
+ /**
* Initializes the script engine for given language.
*
* @param language the language of the script to instantiate
@@ -248,13 +292,9 @@ public class ScriptEngineFactory {
}
public static ScriptEngineInitializer getInitializer(String language) {
- for (ScriptEngineInitializer i : KNOWN_ENGINES) {
- if (i.implementsLanguage(language)) {
- return i;
- }
- }
-
- return null;
+ ScriptEngineProvider provider = KNOWN_PROVIDERS.get(language);
+
+ return provider == null ? null : provider.getInitializer();
}
private static boolean shouldIndirect(Method method) {
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
index fd84c6d..da544c4 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
@@ -72,14 +72,17 @@ public class StandardBindings extends HashMap<String, Object> {
this.clazz = clazz;
}
+ @Override
public String getKey() {
return inner.getKey();
}
+ @Override
public T getValue() {
return clazz.cast(inner.getValue());
}
+ @Override
public T setValue(T value) {
return clazz.cast(inner.setValue(value));
}
@@ -130,11 +133,13 @@ public class StandardBindings extends HashMap<String, Object> {
putAll(managers);
}
+ @Override
public void preInject(ScriptEngine scriptEngine) {
((ScriptUtil) get(SCRIPT_UTIL)).init(scriptEngine);
((ScriptAssert) get(ASSERT)).init(scriptEngine);
}
+ @Override
public void postInject(ScriptEngine scriptEngine) {
ScriptEngineFactory.bindIndirectionMethods(scriptEngine, SCRIPT_UTIL);
ScriptEngineFactory.bindIndirectionMethods(scriptEngine, ASSERT);
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/JsEngineInitializer.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/JsEngineInitializer.java
deleted file mode 100644
index e810bfe..0000000
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/JsEngineInitializer.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.bindings.engine;
-
-import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.Set;
-
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
-
-/**
- *
- *
- * @author Lukas Krejci
- */
-public class JsEngineInitializer implements ScriptEngineInitializer {
-
- private static final String WRAPPED_EXCEPTION_PREFIX = "Wrapped ";
-
- private ScriptEngineManager engineManager = new ScriptEngineManager();
-
- public boolean implementsLanguage(String language) {
- return language != null && ("JavaScript".equals(language) || "ECMAScript".equals(language));
- }
-
- public ScriptEngine instantiate(Set<String> packages) throws ScriptException {
- ScriptEngine eng = engineManager.getEngineByName("JavaScript");
-
- for(String pkg : packages) {
- eng.eval("importPackage(" + pkg + ")");
- }
-
- return eng;
- }
-
- public Set<String> generateIndirectionMethods(String boundObjectName, Set<Method> methods) {
- if (methods.size() == 0) {
- return Collections.emptySet();
- }
-
- String methodName = methods.iterator().next().getName();
-
- StringBuilder functionBuilder = new StringBuilder("function ");
- functionBuilder.append(methodName).append("() { switch(arguments.length) { ");
-
- for(Method method : methods) {
- int argCnt = method.getParameterTypes().length;
- functionBuilder.append("case ").append(argCnt).append(": ");
- functionBuilder.append("return ").append(boundObjectName).append(".").append(methodName).append("(");
- for(int i = 0; i < argCnt; ++i) {
- if (i > 0) {
- functionBuilder.append(", ");
- }
-
- functionBuilder.append("arguments[").append(i).append("]");
- }
-
- functionBuilder.append("); break; ");
- }
-
- functionBuilder.append(" default: throw \"Unsupported number of parameters.\"; } }");
-
- return Collections.singleton(functionBuilder.toString());
- }
-
- public String extractUserFriendlyErrorMessage(ScriptException e) {
- String errorMessage = e.getMessage();
-
- int wrappedIdx = errorMessage.lastIndexOf(WRAPPED_EXCEPTION_PREFIX);
-
- if (wrappedIdx < 0) {
- return errorMessage;
- }
-
- errorMessage = errorMessage.substring(wrappedIdx + WRAPPED_EXCEPTION_PREFIX.length());
-
- int sourceInfoStartIdx = errorMessage.indexOf(" (<Unknown source>#");
-
- if (sourceInfoStartIdx >= 0) {
- errorMessage = errorMessage.substring(0, sourceInfoStartIdx);
- }
-
- return errorMessage;
- }
-}
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/ScriptEngineInitializer.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/ScriptEngineInitializer.java
deleted file mode 100644
index 968e815..0000000
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/ScriptEngineInitializer.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.bindings.engine;
-
-import java.lang.reflect.Method;
-import java.util.Set;
-
-import javax.script.ScriptEngine;
-import javax.script.ScriptException;
-
-/**
- * Is able to instantiate a script engine and import packages into the context
- * of the engine.
- *
- * @author Lukas Krejci
- */
-public interface ScriptEngineInitializer {
-
- boolean implementsLanguage(String language);
-
- ScriptEngine instantiate(Set<String> packages) throws ScriptException;
-
- /**
- * This function returns a definition string in the script engine's language
- * that provides an indirection to calling the method on the bound object.
- *
- * for example for parameters:
- * <ul>
- * <li> <code>boundObjectName = foo</code>
- * <li> <code> method = <int bar(int)></code>
- * </ul>
- * The method would generate this javascript:<br/>
- * <code>
- * function bar(arg) { return foo.bar(arg); }
- * </code>
- * <p>
- * This method gets passed all the overloaded versions of a method on the object (i.e.
- * all the methods with the same name) and is free to return any number of functions
- * that will map all the possible overloaded versions.
- * <p>
- * This is because different scripting languages have different support for function
- * overloading and different ways of handling varying number of arguments of a function.
- *
- * @param boundObjectName
- * @param overloadedMethods
- * @return a set of strings with top-level function definitions in the scripting language
- */
- Set<String> generateIndirectionMethods(String boundObjectName, Set<Method> overloadedMethods);
-
- /**
- * At least the Rhino script engine for java script generates exceptions
- * whose error messages contain just "too much" information to be easily
- * decipherable by the end users.
- * <p>
- * This method extracts messages from the exception such that they are
- * presentable to the end user.
- * <p>
- * The returned string should only contain the error message. The filename, line
- * and column information should be stripped from it if at all possible.
- *
- * @param e
- * @return
- */
- String extractUserFriendlyErrorMessage(ScriptException e);
-}
diff --git a/modules/enterprise/pom.xml b/modules/enterprise/pom.xml
index 158709c..e572daf 100644
--- a/modules/enterprise/pom.xml
+++ b/modules/enterprise/pom.xml
@@ -46,6 +46,7 @@
<module>server/plugins</module>
<module>server/ear</module>
<module>binding</module>
+ <module>scripting</module>
<module>server/client-api</module>
<module>server/itests</module>
</modules>
@@ -67,6 +68,7 @@
<module>server/safe-invoker</module>
<module>server/sars</module>
<module>binding</module>
+ <module>scripting</module>
<module>remoting</module>
<module>gui</module>
<module>server/plugins</module>
diff --git a/modules/enterprise/scripting/api/pom.xml b/modules/enterprise/scripting/api/pom.xml
new file mode 100644
index 0000000..b3d036b
--- /dev/null
+++ b/modules/enterprise/scripting/api/pom.xml
@@ -0,0 +1,173 @@
+<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-scripting-parent</artifactId>
+ <groupId>org.rhq</groupId>
+ <version>4.5.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>rhq-scripting-api</artifactId>
+ <version>4.5.0-SNAPSHOT</version>
+ <name>RHQ Scripting API</name>
+ <description>Provides API for adding scripting support to RHQ using different javax.scripting - based interpreters</description>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+
+ <profile>
+ <id>dev</id>
+
+ <properties>
+ <rhq.rootDir>../../..</rhq.rootDir>
+ <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+ <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/lib</rhq.deploymentDir>
+ </properties>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.1</version>
+ <executions>
+
+ <execution>
+ <id>deploy</id>
+ <phase>compile</phase>
+ <configuration>
+ <tasks>
+ <mkdir dir="${rhq.deploymentDir}" />
+ <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Updating
+ ${deployment.file}...</echo>
+ <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>undeploy</id>
+ <phase>clean</phase>
+ <configuration>
+ <tasks>
+ <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Deleting
+ ${deployment.file}...</echo>
+ <delete file="${deployment.file}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+
+ <profile>
+ <id>cobertura-plugins</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>net.sourceforge.cobertura</groupId>
+ <artifactId>cobertura</artifactId>
+ <version>1.9.4.1</version>
+ </dependency>
+ </dependencies>
+ <executions>
+ <execution>
+ <id>cobertura-instrument</id>
+ <phase>pre-integration-test</phase>
+ <configuration>
+ <tasks>
+ <!-- prepare directory structure
+ for cobertura -->
+ <mkdir dir="target/cobertura" />
+ <mkdir dir="target/cobertura/backup" />
+ <!-- backup all classes so that we
+ can instrument the original classes -->
+ <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
+ <fileset dir="target/classes">
+ <include name="**/*.class" />
+ </fileset>
+ </copy>
+ <!-- create a properties file and
+ save there location of cobertura data file -->
+ <touch file="target/classes/cobertura.properties" />
+ <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
+ <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+ <!-- instrument all classes in target/classes
+ directory -->
+ <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser" todir="${project.build.directory}/classes">
+ <fileset dir="${project.build.directory}/classes">
+ <include name="**/*.class" />
+ </fileset>
+ </cobertura-instrument>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>cobertura-report</id>
+ <phase>post-integration-test</phase>
+ <configuration>
+ <tasks>
+ <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+ <!-- prepare directory structure
+ for cobertura -->
+ <mkdir dir="target/cobertura" />
+ <mkdir dir="target/site/cobertura" />
+ <!-- restore classes from backup
+ folder to classes folder -->
+ <copy toDir="target/classes" verbose="true" overwrite="true">
+ <fileset dir="target/cobertura/backup">
+ <include name="**/*.class" />
+ </fileset>
+ </copy>
+ <!-- delete backup folder -->
+ <delete dir="target/cobertura/backup" />
+ <!-- create a code coverage report -->
+ <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser" destdir="${project.build.directory}/site/cobertura">
+ <fileset dir="${basedir}/src/main/java">
+ <include name="**/*.java" />
+ </fileset>
+ </cobertura-report>
+ <!-- delete cobertura.properties
+ file -->
+ <delete file="target/classes/cobertura.properties" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
new file mode 100644
index 0000000..1569896
--- /dev/null
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
@@ -0,0 +1,29 @@
+/*
+ * 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.scripting;
+
+/**
+ * TODO This will hook into the interactive code completion provided by the CLI.
+ *
+ * @author Lukas Krejci
+ */
+public interface CodeCompletion {
+
+}
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
new file mode 100644
index 0000000..3286f39
--- /dev/null
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
@@ -0,0 +1,80 @@
+/*
+ * 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.scripting;
+
+import java.lang.reflect.Method;
+import java.util.Set;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+/**
+ * Is able to instantiate a script engine and import packages into the context
+ * of the engine.
+ *
+ * @author Lukas Krejci
+ */
+public interface ScriptEngineInitializer {
+
+ ScriptEngine instantiate(Set<String> packages) throws ScriptException;
+
+ /**
+ * This function returns a definition string in the script engine's language
+ * that provides an indirection to calling the method on the bound object.
+ *
+ * for example for parameters:
+ * <ul>
+ * <li> <code>boundObjectName = foo</code>
+ * <li> <code> method = <int bar(int)></code>
+ * </ul>
+ * The method would generate this javascript:<br/>
+ * <code>
+ * function bar(arg) { return foo.bar(arg); }
+ * </code>
+ * <p>
+ * This method gets passed all the overloaded versions of a method on the object (i.e.
+ * all the methods with the same name) and is free to return any number of functions
+ * that will map all the possible overloaded versions.
+ * <p>
+ * This is because different scripting languages have different support for function
+ * overloading and different ways of handling varying number of arguments of a function.
+ *
+ * @param boundObjectName
+ * @param overloadedMethods
+ * @return a set of strings with top-level function definitions in the scripting language
+ */
+ Set<String> generateIndirectionMethods(String boundObjectName, Set<Method> overloadedMethods);
+
+ /**
+ * At least the Rhino script engine for java script generates exceptions
+ * whose error messages contain just "too much" information to be easily
+ * decipherable by the end users.
+ * <p>
+ * This method extracts messages from the exception such that they are
+ * presentable to the end user.
+ * <p>
+ * The returned string should only contain the error message. The filename, line
+ * and column information should be stripped from it if at all possible.
+ *
+ * @param e
+ * @return
+ */
+ String extractUserFriendlyErrorMessage(ScriptException e);
+}
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
new file mode 100644
index 0000000..db22068
--- /dev/null
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
@@ -0,0 +1,52 @@
+/*
+ * 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.scripting;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * This is the service interface for scripting language implementations for RHQ
+ * (loaded using the META-INF/services mechanism).
+ *
+ * @author Lukas Krejci
+ */
+public interface ScriptEngineProvider {
+
+ /**
+ * @return the scripting language understood by this provider.
+ */
+ @NotNull
+ String getSupportedLanguage();
+
+ /**
+ * @return an implementation of {@link ScriptEngineInitializer} that can instantiate
+ * and initialize a script engine for the supported language for use with RHQ.
+ */
+ @NotNull
+ ScriptEngineInitializer getInitializer();
+
+ /**
+ * @return a {@link CodeCompletion} implementation for the supported language or null
+ * if this provider doesn't provide one.
+ */
+ @Nullable
+ CodeCompletion getCodeCompletion();
+}
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
new file mode 100644
index 0000000..bd0d585
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -0,0 +1,187 @@
+<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-scripting-parent</artifactId>
+ <groupId>org.rhq</groupId>
+ <version>4.5.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>rhq-scripting-javascript</artifactId>
+ <version>4.5.0-SNAPSHOT</version>
+ <name>RHQ Javascript support</name>
+ <description>Provides RHQ scripting in Javascript using Rhino</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-scripting-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mozilla</groupId>
+ <artifactId>rhino</artifactId>
+ <version>1.7R3</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+
+ <profile>
+ <id>dev</id>
+
+ <properties>
+ <rhq.rootDir>../../..</rhq.rootDir>
+ <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+ <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/lib</rhq.deploymentDir>
+ </properties>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.1</version>
+ <executions>
+
+ <execution>
+ <id>deploy</id>
+ <phase>compile</phase>
+ <configuration>
+ <tasks>
+ <mkdir dir="${rhq.deploymentDir}" />
+ <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Updating
+ ${deployment.file}...</echo>
+ <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>undeploy</id>
+ <phase>clean</phase>
+ <configuration>
+ <tasks>
+ <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Deleting
+ ${deployment.file}...</echo>
+ <delete file="${deployment.file}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+
+ <profile>
+ <id>cobertura-plugins</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>net.sourceforge.cobertura</groupId>
+ <artifactId>cobertura</artifactId>
+ <version>1.9.4.1</version>
+ </dependency>
+ </dependencies>
+ <executions>
+ <execution>
+ <id>cobertura-instrument</id>
+ <phase>pre-integration-test</phase>
+ <configuration>
+ <tasks>
+ <!-- prepare directory structure
+ for cobertura -->
+ <mkdir dir="target/cobertura" />
+ <mkdir dir="target/cobertura/backup" />
+ <!-- backup all classes so that we
+ can instrument the original classes -->
+ <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
+ <fileset dir="target/classes">
+ <include name="**/*.class" />
+ </fileset>
+ </copy>
+ <!-- create a properties file and
+ save there location of cobertura data file -->
+ <touch file="target/classes/cobertura.properties" />
+ <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
+ <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+ <!-- instrument all classes in target/classes
+ directory -->
+ <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser" todir="${project.build.directory}/classes">
+ <fileset dir="${project.build.directory}/classes">
+ <include name="**/*.class" />
+ </fileset>
+ </cobertura-instrument>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>cobertura-report</id>
+ <phase>post-integration-test</phase>
+ <configuration>
+ <tasks>
+ <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+ <!-- prepare directory structure
+ for cobertura -->
+ <mkdir dir="target/cobertura" />
+ <mkdir dir="target/site/cobertura" />
+ <!-- restore classes from backup
+ folder to classes folder -->
+ <copy toDir="target/classes" verbose="true" overwrite="true">
+ <fileset dir="target/cobertura/backup">
+ <include name="**/*.class" />
+ </fileset>
+ </copy>
+ <!-- delete backup folder -->
+ <delete dir="target/cobertura/backup" />
+ <!-- create a code coverage report -->
+ <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser" destdir="${project.build.directory}/site/cobertura">
+ <fileset dir="${basedir}/src/main/java">
+ <include name="**/*.java" />
+ </fileset>
+ </cobertura-report>
+ <!-- delete cobertura.properties
+ file -->
+ <delete file="target/classes/cobertura.properties" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
new file mode 100644
index 0000000..3ad2296
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
@@ -0,0 +1,105 @@
+/*
+ * 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.scripting.javascript;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.Set;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+
+import org.rhq.scripting.ScriptEngineInitializer;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class JsEngineInitializer implements ScriptEngineInitializer {
+
+ private static final String WRAPPED_EXCEPTION_PREFIX = "Wrapped ";
+
+ private ScriptEngineManager engineManager = new ScriptEngineManager();
+
+ @Override
+ public ScriptEngine instantiate(Set<String> packages) throws ScriptException {
+ ScriptEngine eng = engineManager.getEngineByName("JavaScript");
+
+ for(String pkg : packages) {
+ eng.eval("importPackage(" + pkg + ")");
+ }
+
+ return eng;
+ }
+
+ @Override
+ public Set<String> generateIndirectionMethods(String boundObjectName, Set<Method> methods) {
+ if (methods.size() == 0) {
+ return Collections.emptySet();
+ }
+
+ String methodName = methods.iterator().next().getName();
+
+ StringBuilder functionBuilder = new StringBuilder("function ");
+ functionBuilder.append(methodName).append("() { switch(arguments.length) { ");
+
+ for(Method method : methods) {
+ int argCnt = method.getParameterTypes().length;
+ functionBuilder.append("case ").append(argCnt).append(": ");
+ functionBuilder.append("return ").append(boundObjectName).append(".").append(methodName).append("(");
+ for(int i = 0; i < argCnt; ++i) {
+ if (i > 0) {
+ functionBuilder.append(", ");
+ }
+
+ functionBuilder.append("arguments[").append(i).append("]");
+ }
+
+ functionBuilder.append("); break; ");
+ }
+
+ functionBuilder.append(" default: throw \"Unsupported number of parameters.\"; } }");
+
+ return Collections.singleton(functionBuilder.toString());
+ }
+
+ @Override
+ public String extractUserFriendlyErrorMessage(ScriptException e) {
+ String errorMessage = e.getMessage();
+
+ int wrappedIdx = errorMessage.lastIndexOf(WRAPPED_EXCEPTION_PREFIX);
+
+ if (wrappedIdx < 0) {
+ return errorMessage;
+ }
+
+ errorMessage = errorMessage.substring(wrappedIdx + WRAPPED_EXCEPTION_PREFIX.length());
+
+ int sourceInfoStartIdx = errorMessage.indexOf(" (<Unknown source>#");
+
+ if (sourceInfoStartIdx >= 0) {
+ errorMessage = errorMessage.substring(0, sourceInfoStartIdx);
+ }
+
+ return errorMessage;
+ }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
new file mode 100644
index 0000000..8d9e4b7
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
@@ -0,0 +1,49 @@
+/*
+ * 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.scripting.javascript;
+
+import org.rhq.scripting.CodeCompletion;
+import org.rhq.scripting.ScriptEngineInitializer;
+import org.rhq.scripting.ScriptEngineProvider;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class JsEngineProvider implements ScriptEngineProvider {
+
+ @Override
+ public String getSupportedLanguage() {
+ return "JavaScript";
+ }
+
+ @Override
+ public ScriptEngineInitializer getInitializer() {
+ return new JsEngineInitializer();
+ }
+
+ @Override
+ public CodeCompletion getCodeCompletion() {
+ // TODO copy this over from the CLI
+ return null;
+ }
+
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider b/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider
new file mode 100644
index 0000000..1c55fe7
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider
@@ -0,0 +1 @@
+org.rhq.scripting.javascript.JsEngineProvider
diff --git a/modules/enterprise/scripting/pom.xml b/modules/enterprise/scripting/pom.xml
new file mode 100644
index 0000000..92b72d4
--- /dev/null
+++ b/modules/enterprise/scripting/pom.xml
@@ -0,0 +1,34 @@
+<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-enterprise-parent</artifactId>
+ <groupId>org.rhq</groupId>
+ <version>4.5.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>rhq-scripting-parent</artifactId>
+ <packaging>pom</packaging>
+
+ <version>4.5.0-SNAPSHOT</version>
+ <name>RHQ Scripting Parent Module</name>
+
+ <modules>
+ <module>api</module>
+ <module>factory</module>
+ <module>javascript</module>
+ </modules>
+
+ <profiles>
+ <profile>
+ <id>experimental</id>
+ <activation>
+ <property>
+ <name>experimental-script-languages</name>
+ </property>
+ </activation>
+
+ <modules>
+ <module>python</module>
+ </modules>
+ </profile>
+ </profiles>
+</project>
diff --git a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
index da003f6..09dc8a5 100644
--- a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
+++ b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
@@ -43,7 +43,6 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.bindings.ScriptEngineFactory;
import org.rhq.bindings.StandardBindings;
import org.rhq.bindings.StandardScriptPermissions;
-import org.rhq.bindings.engine.ScriptEngineInitializer;
import org.rhq.bindings.util.PackageFinder;
import org.rhq.core.domain.alert.Alert;
import org.rhq.core.domain.alert.notification.SenderResult;
@@ -61,6 +60,7 @@ import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.plugin.pc.alert.AlertSender;
import org.rhq.enterprise.server.plugin.pc.alert.AlertSenderValidationResults;
import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.scripting.ScriptEngineInitializer;
/**
* Uses CLI to perform the alert notification.
11 years, 9 months
[rhq] .classpath
by mazz
.classpath | 1 +
1 file changed, 1 insertion(+)
New commits:
commit 6da6f84c7fd682c5c1e2f3d2c2eedc40989c381a
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Sep 6 17:43:32 2012 -0400
add mysql test classes to eclipse
diff --git a/.classpath b/.classpath
index 2094bae..a5a5568 100644
--- a/.classpath
+++ b/.classpath
@@ -107,6 +107,7 @@
<classpathentry kind="src" path="modules/plugins/postgres/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/postgres/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/mysql/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/mysql/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/oracle/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/oracle/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/apache/src/main/java"/>
11 years, 9 months
[rhq] .classpath
by mazz
.classpath | 1 +
1 file changed, 1 insertion(+)
New commits:
commit e5bf5151f28aa3c5f973e01963a610629cc389dc
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Sep 6 17:34:32 2012 -0400
add database test module to eclipse
diff --git a/.classpath b/.classpath
index 9ce50a8..2094bae 100644
--- a/.classpath
+++ b/.classpath
@@ -103,6 +103,7 @@
<classpathentry kind="src" path="modules/plugins/jboss-cache/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/jboss-cache-v3/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/database/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/database/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/postgres/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/postgres/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/mysql/src/main/java"/>
11 years, 9 months
[rhq] .classpath
by Jay Shaughnessy
.classpath | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
New commits:
commit 84b8df302149f20bd6eef423d55ec3e26581c283
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Sep 6 16:55:24 2012 -0400
Eclipse .classpath update
diff --git a/.classpath b/.classpath
index 0516dd7..9ce50a8 100644
--- a/.classpath
+++ b/.classpath
@@ -270,7 +270,7 @@
<classpathentry exported="true" kind="var" path="M2_REPO/com/google/gwt/gwt-user/2.4.0/gwt-user-2.4.0.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/com/google/gwt/gwt-dev/2.4.0/gwt-dev-2.4.0.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/com/smartgwt/smartgwt/3.0/smartgwt-3.0.jar"/>
- <classpathentry exported="true" kind="var" path="M2_REPO/ca/nanometrics/gflot/1.0.0/gflot-1.0.0.jar"/>
+ <classpathentry exported="true" kind="var" path="M2_REPO/com/googlecode/gflot/gflot/2.4.2/gflot-2.4.2.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/com/jcraft/jsch/0.1.29/jsch-0.1.29.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/commons-jxpath/commons-jxpath/1.3/commons-jxpath-1.3.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/org/dbunit/dbunit/2.4.8/dbunit-2.4.8.jar"/>
11 years, 9 months
[rhq] Branch 'jsanda/metrics-rhq' - 78 commits - modules/core modules/enterprise modules/helpers modules/plugins pom.xml
by John Sanda
modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/drift/DriftServerService.java | 5
modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml | 31
modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java | 2
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java | 3
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java | 2
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/InventoryContext.java | 65
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java | 14
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java | 6
modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java | 12
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java | 6
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java | 12
modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java | 43
modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryContextImpl.java | 57
modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java | 49
modules/core/plugin-container/src/test/java/org/rhq/core/pc/bundle/BundleManagerTest.java | 2
modules/enterprise/agent/src/etc/rhq-agent-wrapper.sh | 40
modules/enterprise/binding/pom.xml | 7
modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java | 39
modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java | 58
modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptedTestBase.java | 220 +
modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java | 269 +-
modules/enterprise/gui/coregui/pom.xml | 13
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java | 33
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java | 5
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java | 14
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java | 11
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesDataSource.java | 28
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java | 35
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java | 45
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/DynamicCallbackFormImplIE8.java | 50
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java | 21
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java | 33
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java | 7
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java | 116
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java | 6
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java | 17
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java | 6
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml | 20
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties | 10
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties | 6
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties | 10
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties | 6
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties | 10
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties | 6
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties | 10
modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html | 3
modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.7.2.min.js | 4
modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-1.6.js | 1271 ----------
modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-2.0.min.js | 5
modules/enterprise/remoting/cli/pom.xml | 27
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java | 28
modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml | 9
modules/enterprise/scripting/javascript/pom.xml | 2
modules/enterprise/scripting/pom.xml | 5
modules/enterprise/scripting/python/pom.xml | 2
modules/enterprise/server/ear/pom.xml | 20
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java | 18
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java | 19
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java | 5
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftServerServiceImpl.java | 20
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java | 13
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java | 2
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/LargeGroupCriteriaTest.java | 55
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java | 139 -
modules/enterprise/server/plugins/pom.xml | 1
modules/helpers/pluginAnnotations/pom.xml | 8
modules/helpers/pluginGen/pom.xml | 6
modules/helpers/pluginGen/src/main/resources/pom.ftl | 15
modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java | 3
modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java | 7
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/WebApplicationContextComponent.java | 46
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java | 13
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstallationInfo.java | 47
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java | 7
modules/plugins/jboss-as-7/pom.xml | 1
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java | 56
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationLoadDelegate.java | 3
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java | 49
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConnectorDiscoveryGroupValidatorComponent.java | 83
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DatasourceComponent.java | 43
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DomainDeploymentComponent.java | 8
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HornetQComponent.java | 27
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java | 7
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JmsComponent.java | 32
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java | 2
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SocketBindingGroupComponent.java | 11
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java | 118
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java | 7
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SubsystemDiscovery.java | 61
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/TransactionsComponent.java | 62
modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml | 334 +-
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java | 107
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java | 6
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java | 3
modules/plugins/jboss-as-7/src/test/resources/test-plugin.xml | 33
modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/util/FileContentDelegate.java | 38
modules/plugins/jboss-cache-v3/src/main/java/org/rhq/plugins/jbosscache3/JBossCacheDetailDiscoveryComponent.java | 8
modules/plugins/jboss-cache-v3/src/main/resources/META-INF/rhq-plugin.xml | 2
modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java | 5
modules/plugins/oracle/src/test/java/org/rhq/plugins/oracle/ComponentTest.java | 12
modules/plugins/perftest/src/main/resources/META-INF/rhq-plugin.xml | 8
modules/plugins/perftest/src/main/resources/configurable-7.xml | 40
modules/plugins/snmptrapd/src/test/java/org/rhq/plugins/snmptrapd/ComponentTest.java | 5
pom.xml | 19
106 files changed, 2410 insertions(+), 2045 deletions(-)
New commits:
commit 8e5f17203b143ac986c5d7db683fdb204fe28dbb
Merge: bdb98df 42c00f9
Author: John Sanda <jsanda(a)redhat.com>
Date: Thu Sep 6 07:51:39 2012 -0400
Merge branch 'master' into jsanda/metrics-rhq
Conflicts:
modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
diff --cc modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index 13c240d,1443b80..5b80b4a
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@@ -4007,22 -4007,34 +4007,33 @@@
<schema-javaTask className="ContentSourceConfigurationObfuscationUpgradeTask" />
</schemaSpec>
+ <!-- RHQ 4.4, JON 3.1.0 RELEASE uses DB Schema 2.121 -->
+
<schemaSpec version="2.122">
- <schema-addColumn table="RHQ_CONFIG_PROP_DEF" column="MIN_ENTRIES" columnType="INTEGER"/>
- <schema-addColumn table="RHQ_CONFIG_PROP_DEF" column="MAX_ENTRIES" columnType="INTEGER"/>
+ <schema-directSQL>
+ <statement desc="Updating DOWN Alert Conditions to new format">
+ UPDATE RHQ_ALERT_CONDITION
+ SET NAME = 'AVAIL_GOES_DOWN', OPTION_STATUS = NULL
+ WHERE TYPE = 'AVAILABILITY'
+ AND NAME IS NULL
+ AND OPTION_STATUS = 'DOWN'
+ </statement>
+ <statement desc="Updating UP Alert Conditions to new format">
+ UPDATE RHQ_ALERT_CONDITION
+ SET NAME = 'AVAIL_GOES_UP', OPTION_STATUS = NULL
+ WHERE TYPE = 'AVAILABILITY'
+ AND NAME IS NULL
+ AND OPTION_STATUS = 'UP'
+ </statement>
+ </schema-directSQL>
</schemaSpec>
-
-<!-- JON 3.1.1 RELEASE uses DB Schema 2.122 -->
+
+
<schemaSpec version="2.123">
- <schema-directSQL>
- <statement desc="Adding metrics server plugin active plugin system configuration property">
- INSERT INTO rhq_system_config (id, property_key, property_value, default_property_value)
- VALUES (59, 'ACTIVE_METRICS_PLUGIN', 'metrics-rhq', 'metrics-rhq')
- </statement>
- </schema-directSQL>
+ <schema-addColumn table="RHQ_CONFIG_PROP_DEF" column="MIN_ENTRIES" columnType="INTEGER"/>
+ <schema-addColumn table="RHQ_CONFIG_PROP_DEF" column="MAX_ENTRIES" columnType="INTEGER"/>
</schemaSpec>
-
-
</dbupgrade>
</target>
</project>
diff --cc modules/enterprise/server/plugins/pom.xml
index f9a86f5,11f3b5c..6a5e729
--- a/modules/enterprise/server/plugins/pom.xml
+++ b/modules/enterprise/server/plugins/pom.xml
@@@ -78,9 -78,7 +78,8 @@@
<module>filetemplate-bundle</module>
<module>ant-bundle</module>
<module>validate-all-serverplugins</module>
- <module>groovy-script</module>
<module>packagetype-cli</module>
+ <module>metrics-rhq</module>
</modules>
</project>
commit 42c00f9ade61af787ec4dd325b1045c6841f22bb
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Aug 27 15:25:57 2012 -0400
Update pom-template.
diff --git a/modules/helpers/pluginGen/src/main/resources/pom.ftl b/modules/helpers/pluginGen/src/main/resources/pom.ftl
index 378bd76..2434ddd 100644
--- a/modules/helpers/pluginGen/src/main/resources/pom.ftl
+++ b/modules/helpers/pluginGen/src/main/resources/pom.ftl
@@ -2,7 +2,7 @@
<#--
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-20012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -31,7 +31,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version><#if props.rhqVersion??>${props.rhqVersion}<#else >1.3.0-SNAPSHOT</#if></version><!-- TODO adjust RHQ version -->
+ <version><#if props.rhqVersion??>${props.rhqVersion}<#else >4.5.0-SNAPSHOT</#if></version><!-- TODO adjust RHQ version -->
</parent>
<groupId>org.rhq</groupId>
@@ -43,9 +43,6 @@
<description>${props.description}</description>
</#if>
- <properties>
- <rhq.version><#if props.rhqVersion??>${props.rhqVersion}<#else >1.3.0-SNAPSHOT</#if></rhq.version> <!-- TODO adjust, see above too -->
- </properties>
<build>
<plugins>
@@ -212,26 +209,26 @@
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-domain</artifactId>
- <version>${r"${rhq.version}"}</version>
+ <version>${r"${project.version}"}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-plugin-api</artifactId>
- <version>${r"${rhq.version}"}</version>
+ <version>${r"${project.version}"}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-native-system</artifactId>
- <version>${r"${rhq.version}"}</version>
+ <version>${r"${project.version}"}</version>
<scope>provided</scope>
</dependency>
<#if props.dependsOnJmxPlugin>
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-jmx-plugin</artifactId>
- <version>${r"${rhq.version}"}</version>
+ <version>${r"${project.version}"}</version>
<scope>provided</scope>
</dependency>
</#if>
commit 11fb6e5360c29a76726d7759b680220459386497
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu Aug 23 12:07:35 2012 -0400
Update plugin generator poms.
diff --git a/modules/helpers/pluginAnnotations/pom.xml b/modules/helpers/pluginAnnotations/pom.xml
index b6720cb..74800f8 100644
--- a/modules/helpers/pluginAnnotations/pom.xml
+++ b/modules/helpers/pluginAnnotations/pom.xml
@@ -7,20 +7,20 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.0</version>
+ <version>4.5.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-pluginAnnotations</artifactId>
<packaging>jar</packaging>
- <version>3.0.2-SNAPSHOT</version>
+ <version>4.5.0-SNAPSHOT</version>
<name>RHQ plugin annotations</name>
<description>Annotations to help generate plugin descriptors</description>
<build>
-
+
<plugins>
<plugin>
@@ -31,7 +31,7 @@
</configuration>
</plugin>
- <plugin>
+ <plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
diff --git a/modules/helpers/pluginGen/pom.xml b/modules/helpers/pluginGen/pom.xml
index 299550d..62bf822 100644
--- a/modules/helpers/pluginGen/pom.xml
+++ b/modules/helpers/pluginGen/pom.xml
@@ -7,14 +7,14 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.0</version>
+ <version>4.5.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-pluginGen</artifactId>
<packaging>jar</packaging>
- <version>3.0.2-SNAPSHOT</version>
+ <version>4.5.0-SNAPSHOT</version>
<name>RHQ plugin generator</name>
<description>Helper to generate plugin skeletons</description>
@@ -90,7 +90,7 @@
<dependency>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-pluginAnnotations</artifactId>
- <version>3.0.2-SNAPSHOT</version>
+ <version>4.5.0-SNAPSHOT</version>
</dependency>
</dependencies>
commit e33404e91d4b0cfc681e7816872e93c107b5d8f5
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Fri Aug 31 13:02:07 2012 +0200
[BZ 773626 - Failed to load resource composite data error when refreshing Inventory page (Unavailable Servers, Servers, etc)] handling the exception on the client side and re-fetch the data
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
index 55271c6..383602b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
@@ -171,6 +171,12 @@ public class ResourceDatasource extends RPCDataSource<Resource, ResourceCriteria
if (caught.getMessage().contains("SearchExpressionException")) {
Message message = new Message("Invalid search expression.", Message.Severity.Error);
CoreGUI.getMessageCenter().notify(message);
+ } else if (caught.getMessage().contains("PageList was passed an empty collection")) {
+ // Because of bug 773626
+ Log.warn(caught.getMessage());
+ criteria.setPageControl(new PageControl(0, getDataPageSize()));
+ executeFetch(request, response, criteria);
+ return;
} else {
CoreGUI.getErrorHandler().handleError(MSG.view_inventory_resources_loadFailed(), caught);
}
commit 1293a88ef64918b6401bd830a0739c8f22398fc9
Author: Simeon Pinder <spinder(a)fulliautomatix.conchfritter.com>
Date: Thu Aug 30 16:11:28 2012 -0400
[BZ 840512] adding logic to defend against @PostLoad logic not being called after installation as expected.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java
index 07b3467..bb00ef5 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java
@@ -122,6 +122,9 @@ public class ObfuscatedPropertySimple extends PropertySimple {
*/
@Override
public String getStringValue() {
+ if (clearTextValue == null) {
+ initClearTextValue();
+ }
return clearTextValue;
}
commit 26941dd6fb00043842ad5d4e6786b1f5ed391382
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Aug 30 11:18:30 2012 -0400
[Bug 852561 - AlertCondition.name is null in database after JON 2.4 to 3.1 upgrade]
fix merge issue
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index 94fa46f..1443b80 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -4010,20 +4010,22 @@
<!-- RHQ 4.4, JON 3.1.0 RELEASE uses DB Schema 2.121 -->
<schemaSpec version="2.122">
- <statement desc="Updating DOWN Alert Conditions to new format">
- UPDATE RHQ_ALERT_CONDITION
- SET NAME = 'AVAIL_GOES_DOWN', OPTION_STATUS = NULL
- WHERE TYPE = 'AVAILABILITY'
- AND NAME IS NULL
- AND OPTION_STATUS = 'DOWN'
- </statement>
- <statement desc="Updating UP Alert Conditions to new format">
- UPDATE RHQ_ALERT_CONDITION
- SET NAME = 'AVAIL_GOES_UP', OPTION_STATUS = NULL
- WHERE TYPE = 'AVAILABILITY'
- AND NAME IS NULL
- AND OPTION_STATUS = 'UP'
- </statement>
+ <schema-directSQL>
+ <statement desc="Updating DOWN Alert Conditions to new format">
+ UPDATE RHQ_ALERT_CONDITION
+ SET NAME = 'AVAIL_GOES_DOWN', OPTION_STATUS = NULL
+ WHERE TYPE = 'AVAILABILITY'
+ AND NAME IS NULL
+ AND OPTION_STATUS = 'DOWN'
+ </statement>
+ <statement desc="Updating UP Alert Conditions to new format">
+ UPDATE RHQ_ALERT_CONDITION
+ SET NAME = 'AVAIL_GOES_UP', OPTION_STATUS = NULL
+ WHERE TYPE = 'AVAILABILITY'
+ AND NAME IS NULL
+ AND OPTION_STATUS = 'UP'
+ </statement>
+ </schema-directSQL>
</schemaSpec>
<!-- JON 3.1.1 RELEASE uses DB Schema 2.122 -->
commit 35c152e87e280d8a5cd93353892da39067883819
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Wed Aug 29 15:39:00 2012 -0400
[Bug 852561 - AlertCondition.name is null in database after JON 2.4 to 3.1 upgrade]
From an RHQ perspective this should have affected upgrades to RHQ 4.4. Add
a db upgrade step to convert relevant alert condition rows to the new format.
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index d4b5505..eee04da 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -17,7 +17,7 @@
<description>Database schema setup, upgrade and other utilities</description>
<properties>
- <db.schema.version>2.122</db.schema.version>
+ <db.schema.version>2.123</db.schema.version>
<rhq.ds.type-mapping>${rhq.test.ds.type-mapping}</rhq.ds.type-mapping>
<rhq.ds.server-name>${rhq.test.ds.server-name}</rhq.ds.server-name>
<rhq.ds.db-name>${rhq.test.ds.db-name}</rhq.ds.db-name>
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index 2cee9f4..94fa46f 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -4007,7 +4007,28 @@
<schema-javaTask className="ContentSourceConfigurationObfuscationUpgradeTask" />
</schemaSpec>
- <schemaSpec version="2.122">
+<!-- RHQ 4.4, JON 3.1.0 RELEASE uses DB Schema 2.121 -->
+
+ <schemaSpec version="2.122">
+ <statement desc="Updating DOWN Alert Conditions to new format">
+ UPDATE RHQ_ALERT_CONDITION
+ SET NAME = 'AVAIL_GOES_DOWN', OPTION_STATUS = NULL
+ WHERE TYPE = 'AVAILABILITY'
+ AND NAME IS NULL
+ AND OPTION_STATUS = 'DOWN'
+ </statement>
+ <statement desc="Updating UP Alert Conditions to new format">
+ UPDATE RHQ_ALERT_CONDITION
+ SET NAME = 'AVAIL_GOES_UP', OPTION_STATUS = NULL
+ WHERE TYPE = 'AVAILABILITY'
+ AND NAME IS NULL
+ AND OPTION_STATUS = 'UP'
+ </statement>
+ </schemaSpec>
+
+<!-- JON 3.1.1 RELEASE uses DB Schema 2.122 -->
+
+ <schemaSpec version="2.123">
<schema-addColumn table="RHQ_CONFIG_PROP_DEF" column="MIN_ENTRIES" columnType="INTEGER"/>
<schema-addColumn table="RHQ_CONFIG_PROP_DEF" column="MAX_ENTRIES" columnType="INTEGER"/>
</schemaSpec>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java
index 8a72244..0744199 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java
@@ -427,7 +427,7 @@ public class AlertCondition implements Serializable {
/**
* The name of the condition whose semantics are different based on this condition's category:
*
- * AVAILABILITY: n/a (null)
+ * AVAILABILITY: The relevant Avail AlertConditionOperator name
* THRESHOLD: the name of the metric (TODO: today its the display name, very bad for i18n purposes)
* BASELINE: the name of the metric (TODO: today its the display name, very bad for i18n purposes)
* CHANGE: the name of the metric (TODO: today its the display name, very bad for i18n purposes)
commit 74704eda37bce26278fa089437d98bcd590b4317
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Wed Aug 29 14:15:26 2012 +0200
[BZ 814305 - Dealing with singletons in inventory] Refresh button now takes into consideration the already created singletons and they are not populated in the create/import child combobox
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
index 2eea340..d539136 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
@@ -597,7 +597,7 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
} else {
// menu action
LocatableMenu menu = new LocatableMenu(tableAction.getLocatorId() + "Menu");
- final Map<String, ? extends Object> menuEntries = tableAction.getValueMap();
+ final Map<String, Object> menuEntries = tableAction.getValueMap();
for (final String key : menuEntries.keySet()) {
MenuItem item = new MenuItem(key);
item.addClickHandler(new com.smartgwt.client.widgets.menu.events.ClickHandler() {
@@ -980,7 +980,7 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
* completion. Failure to do so may leave the widgets disabled.
*/
public void addTableAction(String locatorId, String title, String confirmation,
- LinkedHashMap<String, ? extends Object> valueMap, TableAction tableAction) {
+ Map<String, Object> valueMap, TableAction tableAction) {
// If the specified locator ID is qualified, strip off the ancestry prefix, so we can make sure its locator ID
// extends the footer's locator ID as it should.
int underscoreIndex = locatorId.lastIndexOf('_');
@@ -995,6 +995,37 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
tableActions.add(info);
}
+ /**
+ * Updates the list of table's associated actions <code>tableActions</code>.
+ * It automatically updates the gui by calling <code>drawFooter()</code> provided the table has been initialized.
+ *
+ * Note: To prevent user action while a current action completes, all widgets on the footer are disabled
+ * when footer actions take place, typically a button click. It is up to the action to ensure the page
+ * (via refresh() or CoreGUI.refresh()) or footer (via refreshTableActions) are refreshed as needed at action
+ * completion. Failure to do so may leave the widgets disabled.
+ *
+ * @param title the title of a modified action
+ * @param valueMap the map containing the tuples with name of a select item and <code>actionValue</code> which is
+ * then passed to <code>tableAction.executeAction()</code>; use the <code>LinkedHashMap</code> if you want to
+ * preserve the order of map items
+ * @param tableAction the tableAction object (on this object the <code>executeAction()</code> is actually invoked)
+ */
+ public void updateTableAction(String title, Map<String, Object> valueMap,
+ TableAction tableAction) {
+ if (title == null) {
+ return;
+ }
+ for (TableActionInfo info : tableActions) {
+ if (title.equals(info.getTitle())) {
+ if (valueMap != null) info.setValueMap(valueMap);
+ if (tableAction != null) info.setAction(tableAction);
+ // the action listeners have to be re-added
+ if (isInitialized()) drawFooter();
+ break;
+ }
+ }
+ }
+
public void setListGridDoubleClickHandler(DoubleClickHandler handler) {
doubleClickHandler = handler;
}
@@ -1247,12 +1278,12 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
private String locatorId;
private String title;
private String confirmMessage;
- private LinkedHashMap<String, ? extends Object> valueMap;
+ private Map<String, Object> valueMap;
private TableAction action;
private Canvas actionCanvas;
protected TableActionInfo(String locatorId, String title, String confirmMessage,
- LinkedHashMap<String, ? extends Object> valueMap, TableAction action) {
+ Map<String, Object> valueMap, TableAction action) {
this.locatorId = locatorId;
this.title = title;
this.confirmMessage = confirmMessage;
@@ -1272,9 +1303,13 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
return confirmMessage;
}
- public LinkedHashMap<String, ? extends Object> getValueMap() {
+ public Map<String, Object> getValueMap() {
return valueMap;
}
+
+ public void setValueMap(Map<String, Object> valueMap) {
+ this.valueMap = valueMap;
+ }
public Canvas getActionCanvas() {
return actionCanvas;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java
index bb43f26..265778b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java
@@ -89,41 +89,49 @@ public class ResourceCompositeSearchView extends ResourceSearchView {
super.onInit();
// To properly filter Create Child and Import menus we need existing singleton child resources. If the
- // user has creat permission and the parent type has singleton child types and creatable or importable child
+ // user has create permission and the parent type has singleton child types and creatable or importable child
// types, perform an async call to fetch the singleton children. If we make the async call don't declare this
- // instance initialized until after it completesas we must have the children before the menu buttons can be drawn.
+ // instance initialized until after it completes as we must have the children before the menu buttons can be drawn.
final Resource parentResource = parentResourceComposite.getResource();
ResourceType parentType = parentResource.getResourceType();
-
creatableChildTypes = getCreatableChildTypes(parentType);
importableChildTypes = getImportableChildTypes(parentType);
hasCreatableTypes = !creatableChildTypes.isEmpty();
hasImportableTypes = !importableChildTypes.isEmpty();
- singletonChildren = new ArrayList(); // initialize to non-null
+ refreshSingletons(parentResource, null);
+
+ }
+
+ private void refreshSingletons(final Resource parentResource, final AsyncCallback<PageList<Resource>> callback) {
+ singletonChildren = new ArrayList<Resource>(); // initialize to non-null
- Integer[] singletonChildTypes = getSingletonChildTypes(parentType);
+ Integer[] singletonChildTypes = getSingletonChildTypes(parentResource.getResourceType());
if (canCreate && singletonChildTypes.length > 0 && (hasCreatableTypes || hasImportableTypes)) {
ResourceCriteria criteria = new ResourceCriteria();
criteria.addFilterParentResourceId(parentResource.getId());
criteria.addFilterResourceTypeIds(singletonChildTypes);
- GWTServiceLookup.getResourceService().findResourcesByCriteria(criteria,
- new AsyncCallback<PageList<Resource>>() {
-
- @Override
- public void onSuccess(PageList<Resource> result) {
- singletonChildren = result;
- initialized = true;
+ GWTServiceLookup.getResourceService().findResourcesByCriteria(criteria, new AsyncCallback<PageList<Resource>>() {
+
+ @Override
+ public void onSuccess(PageList<Resource> result) {
+ singletonChildren = result;
+ initialized = true;
+ if (callback != null) {
+ callback.onSuccess(result);
}
+ }
- @Override
- public void onFailure(Throwable caught) {
- Log.error("Failed to load child resources for [" + parentResource + "]", caught);
- initialized = true;
+ @Override
+ public void onFailure(Throwable caught) {
+ Log.error("Failed to load child resources for [" + parentResource + "]", caught);
+ initialized = true;
+ if (callback != null) {
+ callback.onFailure(caught);
}
- });
-
+ }
+ });
} else {
initialized = true;
}
@@ -196,34 +204,38 @@ public class ResourceCompositeSearchView extends ResourceSearchView {
}
});
- addImportAndCreateButtons();
+ addImportAndCreateButtons(false);
super.configureTable();
}
@SuppressWarnings("unchecked")
- private void addImportAndCreateButtons() {
+ private void addImportAndCreateButtons(boolean override) {
final Resource parentResource = parentResourceComposite.getResource();
ResourceType parentType = parentResource.getResourceType();
// Create Child Menu and Manual Import Menu
if (canCreate && (hasCreatableTypes || hasImportableTypes)) {
-
if (hasCreatableTypes) {
Map<String, ResourceType> displayNameMap = getDisplayNames(creatableChildTypes);
LinkedHashMap<String, ResourceType> createTypeValueMap = new LinkedHashMap<String, ResourceType>(
displayNameMap);
removeExistingSingletons(singletonChildren, createTypeValueMap);
- addTableAction(extendLocatorId("CreateChild"), MSG.common_button_create_child(), null,
- createTypeValueMap, new AbstractTableAction(TableActionEnablement.ALWAYS) {
- public void executeAction(ListGridRecord[] selection, Object actionValue) {
- ResourceFactoryCreateWizard.showCreateWizard(parentResource, (ResourceType) actionValue);
- // we can refresh the table buttons immediately since the wizard is a dialog, the
- // user can't access enabled buttons anyway.
- ResourceCompositeSearchView.this.refreshTableInfo();
- }
- });
+ AbstractTableAction createAction = new AbstractTableAction(TableActionEnablement.ALWAYS) {
+ public void executeAction(ListGridRecord[] selection, Object actionValue) {
+ ResourceFactoryCreateWizard.showCreateWizard(parentResource, (ResourceType) actionValue);
+ // we can refresh the table buttons immediately since the wizard is a dialog, the
+ // user can't access enabled buttons anyway.
+ ResourceCompositeSearchView.this.refreshTableInfo();
+ }
+ };
+ if (override) {
+ updateTableAction(MSG.common_button_create_child(), createTypeValueMap, createAction);
+ } else {
+ addTableAction(extendLocatorId("CreateChild"), MSG.common_button_create_child(), null,
+ createTypeValueMap, createAction);
+ }
}
if (hasImportableTypes) {
@@ -231,18 +243,23 @@ public class ResourceCompositeSearchView extends ResourceSearchView {
LinkedHashMap<String, ResourceType> importTypeValueMap = new LinkedHashMap<String, ResourceType>(
displayNameMap);
removeExistingSingletons(singletonChildren, importTypeValueMap);
- addTableAction(extendLocatorId("Import"), MSG.common_button_import(), null, importTypeValueMap,
- new AbstractTableAction(TableActionEnablement.ALWAYS) {
- public void executeAction(ListGridRecord[] selection, Object actionValue) {
- ResourceFactoryImportWizard.showImportWizard(parentResource, (ResourceType) actionValue);
- // we can refresh the table buttons immediately since the wizard is a dialog, the
- // user can't access enabled buttons anyway.
- ResourceCompositeSearchView.this.refreshTableInfo();
- }
- });
+ AbstractTableAction importAction = new AbstractTableAction(TableActionEnablement.ALWAYS) {
+ public void executeAction(ListGridRecord[] selection, Object actionValue) {
+ ResourceFactoryImportWizard.showImportWizard(parentResource, (ResourceType) actionValue);
+ // we can refresh the table buttons immediately since the wizard is a dialog, the
+ // user can't access enabled buttons anyway.
+ ResourceCompositeSearchView.this.refreshTableInfo();
+ }
+ };
+ if (override) {
+ updateTableAction(MSG.common_button_import(), importTypeValueMap, importAction);
+ } else {
+ addTableAction(extendLocatorId("Import"), MSG.common_button_import(), null, importTypeValueMap,
+ importAction);
+ }
}
- } else {
+ } else if (!override) {
if (!canCreate && hasCreatableTypes) {
addTableAction(extendLocatorId("CreateChild"), MSG.common_button_create_child(),
new AbstractTableAction(TableActionEnablement.NEVER) {
@@ -261,6 +278,7 @@ public class ResourceCompositeSearchView extends ResourceSearchView {
}
}
}
+
private void removeExistingSingletons(List<Resource> singletonChildren, Map<String, ResourceType> displayNameMap) {
@@ -359,5 +377,23 @@ public class ResourceCompositeSearchView extends ResourceSearchView {
return new ResourceCompositeSearchView(locatorId, parentResourceComposite, new Criteria("parentId",
String.valueOf(parentResourceComposite.getResource().getId())), MSG.view_tabs_common_child_resources());
}
+
+ @Override
+ public void refresh() {
+ refreshSingletons(parentResourceComposite.getResource(), new AsyncCallback<PageList<Resource>>() {
+
+ @Override
+ public void onSuccess(PageList<Resource> result) {
+ addImportAndCreateButtons(true);
+ ResourceCompositeSearchView.super.refresh();
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ ResourceCompositeSearchView.super.refresh();
+ }
+ });
+
+ }
}
commit c6c1e7819fbd8f667649223e12355e66ddd33252
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Aug 29 03:06:38 2012 -0500
[BZ 852632] Remove allow-direct-connections-only property from configuration to prevent sending the value to the application server. If this property is not left undefined, the configuration file for the server becomes invalid if the user attempts to use discovery-group-name.
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 01618e2..46b3084 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
@@ -4714,7 +4714,6 @@
<metric property="started" dataType="trait" description="Whether the cluster connection is started."/>
<resource-configuration>
- <c:simple-property name="allow-direct-connections-only" required="false" type="boolean" readOnly="true" defaultValue="false" description="Whether, if a node learns of the existence of a node that is more than 1 hop away, we do not create a bridge for direct cluster connection. Only relevant if 'static-connectors' is defined. The default value is false."/>
<c:simple-property name="call-timeout" required="false" type="long" readOnly="true" defaultValue="30000" description="The timeout (in ms) for remote calls made by the cluster connection. The default value is 30000."/>
<c:simple-property name="check-period" required="false" type="long" readOnly="true" defaultValue="30000" description="The period (in milliseconds) between client failure check. The default value is 30000."/>
<c:simple-property name="cluster-connection-address" required="true" type="string" readOnly="true" description="Each cluster connection only applies to messages sent to an address that starts with this value."/>
@@ -6843,7 +6842,6 @@
</plugin-configuration>
<resource-configuration>
- <c:simple-property name="allow-direct-connections-only" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether, if a node learns of the existence of a node that is more than 1 hop away, we do not create a bridge for direct cluster connection. Only relevant if 'static-connectors' is defined. The default value is false."/>
<c:simple-property name="call-timeout" required="false" type="long" readOnly="false" defaultValue="30000" description="The timeout (in ms) for remote calls made by the cluster connection. The default value is 30000."/>
<c:simple-property name="check-period" required="false" type="long" readOnly="false" defaultValue="30000" description="The period (in milliseconds) between client failure check. The default value is 30000."/>
<c:simple-property name="cluster-connection-address" required="true" type="string" readOnly="false" description="Each cluster connection only applies to messages sent to an address that starts with this value."/>
@@ -12948,7 +12946,6 @@
<metric property="started" dataType="trait" description="Whether the cluster connection is started."/>
<resource-configuration>
- <c:simple-property name="allow-direct-connections-only" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether, if a node learns of the existence of a node that is more than 1 hop away, we do not create a bridge for direct cluster connection. Only relevant if 'static-connectors' is defined. The default value is false."/>
<c:simple-property name="call-timeout" required="false" type="long" readOnly="false" defaultValue="30000" description="The timeout (in ms) for remote calls made by the cluster connection. The default value is 30000."/>
<c:simple-property name="check-period" required="false" type="long" readOnly="false" defaultValue="30000" description="The period (in milliseconds) between client failure check. The default value is 30000."/>
<c:simple-property name="cluster-connection-address" required="true" type="string" readOnly="false" description="Each cluster connection only applies to messages sent to an address that starts with this value."/>
commit 74aa0f7f9b0f2dd1044450d924f61b3faee78c27
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Aug 29 02:52:42 2012 -0500
[BZ 852552] Updates to set correctly all the data-source and xa-data-source properties that do not support null values and cannot be undefined.
While these properties look undefined in the server, they cannot undefined or set to null at any point in time. The application server makes use of the default value at all times.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DatasourceComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DatasourceComponent.java
index a4efae1..5011120 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DatasourceComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DatasourceComponent.java
@@ -13,6 +13,9 @@ import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.Property;
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.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
import org.rhq.core.domain.measurement.MeasurementDataNumeric;
import org.rhq.core.domain.measurement.MeasurementDataTrait;
import org.rhq.core.domain.measurement.MeasurementReport;
@@ -174,6 +177,27 @@ public class DatasourceComponent extends BaseComponent<BaseComponent<?>> impleme
}
}
+ @Override
+ public void updateResourceConfiguration(ConfigurationUpdateReport report) {
+ Configuration config = report.getConfiguration();
+ ConfigurationDefinition configDef = context.getResourceType().getResourceConfigurationDefinition();
+
+ //These properties cannot be undefined once set.
+ //Also the AS7 server does not accept null values even if the properties are still unset.
+ replaceWithDefaultIfNull("max-pool-size", config, configDef);
+ replaceWithDefaultIfNull("min-pool-size", config, configDef);
+ replaceWithDefaultIfNull("pool-prefill", config, configDef);
+ replaceWithDefaultIfNull("pool-use-strict-min", config, configDef);
+ replaceWithDefaultIfNull("blocking-timeout-wait-millis", config, configDef);
+ replaceWithDefaultIfNull("idle-timeout-minutes", config, configDef);
+ replaceWithDefaultIfNull("background-validation-millis", config, configDef);
+ replaceWithDefaultIfNull("background-validation-minutes", config, configDef);
+ replaceWithDefaultIfNull("background-validation", config, configDef);
+
+ ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(configDef, getASConnection(), address);
+ delegate.updateResourceConfiguration(report);
+ }
+
private void getRCAsMetric(MeasurementReport report, MeasurementScheduleRequest request) {
Operation op = new ReadAttribute(getAddress(), request.getName());
Result res = getASConnection().execute(op);
@@ -204,4 +228,23 @@ public class DatasourceComponent extends BaseComponent<BaseComponent<?>> impleme
return trait;
}
+
+ /**
+ * Replace the value configured by the user with the default value from the resource descriptor if
+ * the value to be sent to the server is null or empty.
+ *
+ * @param propertyName property name
+ * @param config configuration update
+ * @param configDef configuration definition
+ */
+ private void replaceWithDefaultIfNull(String propertyName, Configuration config, ConfigurationDefinition configDef) {
+ PropertyDefinitionSimple propertyDefinition = configDef.getPropertyDefinitionSimple(propertyName);
+
+ if (propertyDefinition != null) {
+ String propertyValue = config.getSimpleValue(propertyName);
+ if (propertyValue == null || propertyValue.isEmpty()) {
+ config.put(new PropertySimple(propertyName, propertyDefinition.getDefaultValue()));
+ }
+ }
+ }
}
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 29ef057..01618e2 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
@@ -412,10 +412,10 @@
<c:simple-property name="use-java-context" type="boolean" readOnly="false" required="false" default="true" description="Setting this to false will bind the DataSource into global JNDI;"/>
<c:simple-property name="enabled" type="boolean" readOnly="true" required="false" description="Specifies if the datasource should be enabled"/>
<c:simple-property name="jta" type="boolean" readOnly="false" required="false" default="true" description="Enable JTA integration"/>
- <c:simple-property name="max-pool-size" type="integer" readOnly="false" required="false" description="The max-pool-size element indicates the maximum number of connections for a pool. No more connections will be created in each sub-pool."/>
- <c:simple-property name="min-pool-size" type="integer" readOnly="false" required="false" description="The min-pool-size element 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."/>
- <c:simple-property name="pool-prefill" type="boolean" readOnly="false" required="false" default="false" description="Whether to attempt to prefill the connection pool. Changing this value require a server restart."/>
- <c:simple-property name="pool-use-strict-min" type="boolean" readOnly="false" required="false" default="false" description="Define if the min-pool-size should be considered a strictly."/>
+ <c:simple-property name="max-pool-size" type="integer" readOnly="false" required="false" defaultValue="20" description="The max-pool-size element indicates the maximum number of connections for a pool. No more connections will be created in each sub-pool."/>
+ <c:simple-property name="min-pool-size" type="integer" readOnly="false" required="false" defaultValue="0" description="The min-pool-size element 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."/>
+ <c:simple-property name="pool-prefill" type="boolean" readOnly="false" required="false" defaultValue="false" description="Whether to attempt to prefill the connection pool. Changing this value require a server restart."/>
+ <c:simple-property name="pool-use-strict-min" type="boolean" readOnly="false" required="false" defaultValue="false" description="Define if the min-pool-size should be considered a strictly."/>
<c:simple-property name="security-domain" required="false" type="string" readOnly="false" description="Indicates Subject (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 handleauthentication. This name correlates to the JAAS login-config.xml descriptor application-policy/name attribute."/>
<c:simple-property name="reauth-plugin-class-name" required="false" type="string" readOnly="false" description="re-authentication plugin implementation provided for specific purpose (i.e vendor)"/>
<!--
@@ -433,7 +433,7 @@
</c:simple-property>
<c:simple-property name="allow-multiple-users" type="boolean" required="false" readOnly="false" description="Specifies if multiple users will access the datasource through the getConnection(user, password) method and hence if the internal pool type should account for that"/>
- <c:simple-property name="prepared-statements-cacheSize" type="long" readOnly="false" required="false" description="The number of prepared statements per connection in an LRU cache"/>
+ <c:simple-property name="prepared-statements-cache-size" type="long" readOnly="false" required="false" description="The number of prepared statements per connection in an LRU cache"/>
<c:simple-property name="share-prepared-statements" type="boolean" readOnly="false" required="false" default="false" description="Whether to share prepare statements, i.e. whether asking for same statement twice without closing uses the same underlying prepared statement"/>
<c:simple-property name="track-statements" type="string" readOnly="false" required="false" description="Whether to check for unclosed statements when a connection is returned to the pool and result sets are closed when a statement is closed/return to the prepared statement cache. valid values are: false - do not track statements and results true - track statements and result sets and warn when they are not closed nowarn - track statements but do no warn about them being unclosed">
<c:property-options>
@@ -444,8 +444,8 @@
</c:simple-property>
<c:simple-property name="allocation-retry" type="integer" readOnly="false" required="false" description="The allocation retry element indicates the number of times that allocating a connection should be tried before throwing an exception."/>
<c:simple-property name="allocation-retry-wait-millis" type="long" readOnly="false" required="false" description="Indicates the time in milliseconds to wait between retrying to allocate a connection."/>
- <c:simple-property name="blocking-timeout-wait-millis" type="long" readOnly="false" required="false" description="The blocking-timeout-millis element 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."/>
- <c:simple-property name="idle-timeout-minutes" type="long" readOnly="false" required="false" description="The idle-timeout-minutes elements 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. Changing this value require a server restart."/>
+ <c:simple-property name="blocking-timeout-wait-millis" type="long" readOnly="false" required="false" defaultValue="30000" description="The blocking-timeout-millis element 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."/>
+ <c:simple-property name="idle-timeout-minutes" type="long" readOnly="false" required="false" defaultValue="15" description="The idle-timeout-minutes elements 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. Changing this value require a server restart."/>
<c:simple-property name="query-timeout" type="long" readOnly="false" required="false" description="Any configured query timeout in seconds The default is no timeout"/>
<c:simple-property name="use-try-lock" type="long" readOnly="false" required="false" description="Any configured timeout for internal locks on the resource adapter objects in seconds"/>
<c:simple-property name="set-tx-query-timeout" type="boolean" readOnly="false" required="false" default="false" description="Whether to set the query timeout based on the time remaining until transaction timeout, any configured query timeout will be used if there is no transaction."/>
@@ -462,8 +462,8 @@
<c:simple-property name="exception-sorter-class-name" type="string" readOnly="false" required="false" description="An org.jboss.jca.adapters.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"/>
<c:simple-property name="stale-connection-checker-class-name" type="string" readOnly="false" required="false" description="An org.jboss.jca.adapters.jdbc.StaleConnectionChecker that provides a boolean isStaleConnection(SQLException e) method which if it it returns true will wrap the exception in an org.jboss.jca.adapters.jdbc.StaleConnectionException"/>
<c:simple-property name="valid-connection-checker-class-name" type="string" readOnly="false" required="false" description="An org.jboss.jca.adapters.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."/>
- <c:simple-property name="background-validation-millis" type="long" readOnly="false" required="false" description="The background-validation-minutes element specifies the amount of time, in minutes, that background validation will run. Changing this value require a server restart."/>
- <c:simple-property name="background-validation" type="boolean" readOnly="false" required="false" default="false" description="An element to specify that connections should be validated on a background thread versus being validated prior to use. Changing this value require a server restart."/>
+ <c:simple-property name="background-validation-millis" type="long" readOnly="false" required="false" defaultValue="600000" description="The background-validation-minutes element specifies the amount of time, in minutes, that background validation will run. Changing this value require a server restart."/>
+ <c:simple-property name="background-validation" type="boolean" readOnly="false" required="false" defaultValue="false" description="An element to specify that connections should be validated on a background thread versus being validated prior to use. Changing this value require a server restart."/>
<c:simple-property name="use-fast-fail" type="boolean" readOnly="false" required="false" description="Whether fail a connection allocation on the first connection if it is invalid (true) or keep trying until the pool is exhausted of all potential connections (false)"/>
<c:simple-property name="validate-on-match" type="boolean" readOnly="false" required="false" default="false" description="The validate-on-match element indicates whether or not connection level validation should be done when a connection factory attempts to match a managed connection for a given set. This is typically exclusive to the use of background validation"/>
<c:simple-property name="spy" type="boolean" readOnly="false" required="false" defaultValue="false" description="whatever spy or not the jdbc connection"/>
@@ -515,7 +515,7 @@
</c:property-options>
</c:simple-property>
- <c:simple-property name="prepared-statements-cacheSize" type="long" readOnly="true" required="false" description="The number of prepared statements per connection in an LRU cache"/>
+ <c:simple-property name="prepared-statements-cache-size" type="long" readOnly="true" required="false" description="The number of prepared statements per connection in an LRU cache"/>
<c:simple-property name="share-prepared-statements" type="boolean" readOnly="true" required="false" description="Whether to share prepare statements, i.e. whether asking for same statement twice without closing uses the same underlying prepared statement"/>
<c:simple-property name="track-statements" type="string" readOnly="true" required="false" description="Whether to check for unclosed statements when a connection is returned to the pool and result sets are closed when a statement is closed/return to the prepared statement cache. valid values are: false - do not track statements and results true - track statements and result sets and warn when they are not closed nowarn - track statements but do no warn about them being unclosed"/>
<c:simple-property name="allocation-retry" type="integer" readOnly="true" required="false" description="The allocation retry element indicates the number of times that allocating a connection should be tried before throwing an exception."/>
@@ -570,10 +570,10 @@
<c:simple-property name="url-selector-strategy-class-name" required="false" type="string" readOnly="true" description="A class that implements org.jboss.jca.adapters.jdbc.URLSelectorStrategy"/>
<c:simple-property name="use-java-context" required="false" type="boolean" readOnly="true" description="Setting this to false will bind the DataSource into global JNDI;"/>
<c:simple-property name="enabled" required="false" type="boolean" readOnly="true" description="Specifies if the datasource should be enabled"/>
- <c:simple-property name="max-pool-size" required="false" type="integer" readOnly="false" description="The max-pool-size element indicates the maximum number of connections for a pool. No more connections will be created in each sub-pool."/>
- <c:simple-property name="min-pool-size" required="false" type="integer" readOnly="false" description="The min-pool-size element 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."/>
- <c:simple-property name="pool-prefill" required="false" type="boolean" readOnly="false" description="Whether to attempt to prefill the connection pool. Changing this value require a server restart."/>
- <c:simple-property name="pool-use-strict-min" required="false" type="boolean" readOnly="false" description="Define if the min-pool-size should be considered a strictly."/>
+ <c:simple-property name="max-pool-size" required="false" type="integer" readOnly="false" defaultValue="20" description="The max-pool-size element indicates the maximum number of connections for a pool. No more connections will be created in each sub-pool."/>
+ <c:simple-property name="min-pool-size" required="false" type="integer" readOnly="false" defaultValue="0" description="The min-pool-size element 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."/>
+ <c:simple-property name="pool-prefill" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether to attempt to prefill the connection pool. Changing this value require a server restart."/>
+ <c:simple-property name="pool-use-strict-min" required="false" type="boolean" readOnly="false" defaultValue="false" description="Define if the min-pool-size should be considered a strictly."/>
<c:simple-property name="interleaving" required="false" type="boolean" readOnly="true" description="An element to enable interleaving for XA connection factories"/>
<c:simple-property name="no-tx-separate-pool" required="false" type="boolean" readOnly="true" description="Oracle does not like XA connections getting used both inside and outside a JTA transaction. To workaround the problem you can create separate sub-pools for the different context"/>
<c:simple-property name="pad-xid" required="false" type="boolean" readOnly="true" description="Should the Xid be padded"/>
@@ -596,13 +596,13 @@
<c:option value="EntirePool"/>
</c:property-options>
</c:simple-property>
- <c:simple-property name="prepared-statements-cacheSize" required="false" type="long" readOnly="true" description="The number of prepared statements per connection in an LRU cache"/>
+ <c:simple-property name="prepared-statements-cache-size" required="false" type="long" readOnly="true" description="The number of prepared statements per connection in an LRU cache"/>
<c:simple-property name="share-prepared-statements" required="false" type="boolean" readOnly="true" description="Whether to share prepare statements, i.e. whether asking for same statement twice without closing uses the same underlying prepared statement"/>
<c:simple-property name="track-statements" required="false" type="string" readOnly="true" description="Whether to check for unclosed statements when a connection is returned to the pool and result sets are closed when a statement is closed/return to the prepared statement cache. valid values are: false - do not track statements and results true - track statements and result sets and warn when they are not closed nowarn - track statements but do no warn about them being unclosed"/>
<c:simple-property name="allocation-retry" required="false" type="integer" readOnly="true" description="The allocation retry element indicates the number of times that allocating a connection should be tried before throwing an exception."/>
<c:simple-property name="allocation-retry-wait-millis" required="false" type="long" readOnly="true" description="he allocation retry wait millis element indicates the time in milliseconds to wait between retrying to allocate a connection."/>
- <c:simple-property name="blocking-timeout-wait-millis" required="false" type="long" readOnly="false" description="The blocking-timeout-millis element 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."/>
- <c:simple-property name="idle-timeout-minutes" required="false" type="long" readOnly="false" description="The idle-timeout-minutes elements 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. Changing this value require a server restart."/>
+ <c:simple-property name="blocking-timeout-wait-millis" required="false" type="long" readOnly="false" defaultValue="30000" description="The blocking-timeout-millis element 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."/>
+ <c:simple-property name="idle-timeout-minutes" required="false" type="long" readOnly="false" defaultValue="15" description="The idle-timeout-minutes elements 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. Changing this value require a server restart."/>
<c:simple-property name="query-timeout" required="false" type="long" readOnly="true" description="Any configured query timeout in seconds The default is no timeout"/>
<c:simple-property name="use-try-lock" required="false" type="long" readOnly="true" description="Any configured timeout for internal locks on the resource adapter objects in seconds"/>
<c:simple-property name="set-tx-query-timeout" required="false" type="boolean" readOnly="true" description="Whether to set the query timeout based on the time remaining until transaction timeout, any configured query timeout will be used if there is no transaction."/>
@@ -637,8 +637,8 @@
configuration
</c:map-property>
-->
- <c:simple-property name="background-validation-minutes" required="false" type="long" readOnly="false" description="The background-validation-minutes element specifies the amount of time, in minutes, that background validation will run. Changing this value require a server restart."/>
- <c:simple-property name="background-validation" required="false" type="boolean" readOnly="false" description="An element to specify that connections should be validated on a background thread versus being validated prior to use. Changing this value require a server restart."/>
+ <c:simple-property name="background-validation-minutes" required="false" type="long" readOnly="false" defaultValue="10" description="The background-validation-minutes element specifies the amount of time, in minutes, that background validation will run. Changing this value require a server restart."/>
+ <c:simple-property name="background-validation" required="false" type="boolean" readOnly="false" defaultValue="false" description="An element to specify that connections should be validated on a background thread versus being validated prior to use. Changing this value require a server restart."/>
<c:simple-property name="use-fast-fail" required="false" type="boolean" readOnly="false" description="Whether fail a connection allocation on the first connection if it is invalid (true) or keep trying until the pool is exhausted of all potential connections (false)"/>
<c:simple-property name="validate-on-match" required="false" type="boolean" readOnly="true" description="The validate-on-match element indicates whether or not connection level validation should be done when a connection factory attempts to match a managed connection for a given set. This is typically exclusive to the use of background validation"/>
<c:simple-property name="xa-resource-timeout" required="false" type="integer" readOnly="true" description="Passed to XAResource.setTransactionTimeout() Default is zero which does not invoke the setter. In seconds"/>
@@ -706,7 +706,7 @@
<c:option value="EntirePool"/>
</c:property-options>
</c:simple-property>
- <c:simple-property name="prepared-statements-cacheSize" required="false" type="long" readOnly="true" description="The number of prepared statements per connection in an LRU cache"/>
+ <c:simple-property name="prepared-statements-cache-size" required="false" type="long" readOnly="true" description="The number of prepared statements per connection in an LRU cache"/>
<c:simple-property name="share-prepared-statements" required="false" type="boolean" readOnly="true" description="Whether to share prepare statements, i.e. whether asking for same statement twice without closing uses the same underlying prepared statement"/>
<c:simple-property name="track-statements" required="false" type="string" readOnly="true" description="Whether to check for unclosed statements when a connection is returned to the pool and result sets are closed when a statement is closed/return to the prepared statement cache. valid values are: false - do not track statements and results true - track statements and result sets and warn when they are not closed nowarn - track statements but do no warn about them being unclosed"/>
<c:simple-property name="allocation-retry" required="false" type="integer" readOnly="true" description="The allocation retry element indicates the number of times that allocating a connection should be tried before throwing an exception."/>
commit e6e91058f3ac76c6458847bd66a8ee5c9c24493e
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Aug 29 02:20:24 2012 -0500
[BZ 847674] Updated all the wait methods for reload, shutdown, and restart to have the same design. All the methods now take into account possible exceptions for the test operation sent to the application server.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
index 27b1133..98a46d2 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
@@ -241,25 +241,36 @@ public abstract class BaseServerComponent<T extends ResourceComponent<?>> extend
return startServer();
}
- protected boolean waitUntilDown(OperationResult tmp) throws InterruptedException {
+ protected boolean waitUntilDown() throws InterruptedException {
boolean down=false;
int count=0;
+
while (!down) {
Operation op = new ReadAttribute(new Address(),"release-version");
- Result res = getASConnection().execute(op);
- if (!res.isSuccess()) { // If op succeeds, server is not down
- down=true;
- } else if (count > 20) {
- tmp.setErrorMessage("Was not able to shut down the server");
- return true;
+
+ try{
+ Result res = getASConnection().execute(op);
+ if (!res.isSuccess()) { // If op succeeds, server is not down
+ down = true;
+ } else if (count > 20) {
+ break;
+ }
+ } catch (Exception e) {
+ down = true;
}
+
if (!down) {
- Thread.sleep(1000); // Wait 1s
+ try {
+ Thread.sleep(1000); // Wait 1s
+ } catch (InterruptedException e) {
+ // ignore
+ }
}
count++;
}
- log.debug("waitUntilDown: Used " + count + " delay round(s) to shut down");
- return false;
+
+ log.debug("waitUntilDown: Used " + count + " delay round(s) to shut down. Server down=" + down);
+ return down;
}
/**
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java
index 565add2..7ea12b9 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java
@@ -92,8 +92,11 @@ public class HostControllerComponent<T extends ResourceComponent<?>> extends Bas
Result res = getASConnection().execute(op);
operationResult = postProcessResult(name, res);
- waitUntilDown(operationResult);
-
+ if (waitUntilDown()) {
+ operationResult.setSimpleResult("Success");
+ } else {
+ operationResult.setErrorMessage("Was not able to shut down the server.");
+ }
} else if (name.equals("installRhqUser")) {
operationResult = installManagementUser(parameters, pluginConfiguration);
} else {
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
index 573742e..778d127 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
@@ -163,39 +163,59 @@ public class StandaloneASComponent<T extends ResourceComponent<?>> extends BaseS
OperationResult operationResult = postProcessResult(name, res);
- if (name.equals("shutdown"))
- waitUntilDown(operationResult);
+ if (name.equals("shutdown")) {
+ if (waitUntilDown()) {
+ operationResult.setSimpleResult("Success");
+ } else {
+ operationResult.setErrorMessage("Was not able to shut down the server.");
+ }
+ }
- if (name.equals("reload"))
- waitUntilReloaded(operationResult);
+ if (name.equals("reload")) {
+ if (waitUntilReloaded()) {
+ operationResult.setSimpleResult("Success");
+ } else {
+ operationResult.setErrorMessage("Was not able to reload the server.");
+ }
+ }
context.getAvailabilityContext().requestAvailabilityCheck();
return operationResult;
}
- private void waitUntilReloaded(OperationResult operationResult) {
+ private boolean waitUntilReloaded() {
boolean reloaded = false;
int count = 0;
+
while (!reloaded) {
- try {
- Thread.sleep(2000); // Wait 2s
- } catch (InterruptedException e) {
- // Ignore
+ Operation op = new ReadAttribute(new Address(), "release-version");
+ try{
+ Result res = getASConnection().execute(op);
+ if (res.isSuccess() && !res.isReloadRequired()) {
+ reloaded = true;
+ } else if (count > 20) {
+ break;
+ }
+ } catch (Exception e) {
+ //do absolutely nothing
+ //if an exception is thrown that means the server is still reloading, so consider this
+ //a single failed attempt, equivalent to res.isSuccess == false
}
- Operation op = new ReadAttribute(new Address(), "release-version");
- Result res = getASConnection().execute(op);
- if (res.isSuccess() && !res.isReloadRequired()) {
- reloaded = true;
- } else if (count > 20) {
- operationResult.setErrorMessage("Was not able to reload the server");
- return;
+ if (!reloaded) {
+ try {
+ Thread.sleep(1000); // Wait 1s
+ } catch (InterruptedException e) {
+ // ignore
+ }
}
count++;
}
- log.debug("waitUntilReloaded: Used " + count + " delay round(s) to reload");
- return;
+
+ log.debug("waitUntilReloaded: Used " + count + " delay round(s) to reload. Reload=" + reloaded);
+
+ return reloaded;
}
@Override
commit 96602db100b087e36016b1aa6a2e39780b583898
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 23:33:45 2012 -0500
[BZ 852552] Adding special validation for the transaction subsystem.
The special case for this subsystem:
If [process-id-uuid] == true then do not send updates for [process-id-socket-binding], this property will be undefined by the AS7 on the next reload/restart
If [process-id-uuid] == false then allow AS7 to perform property validation * If [process-id-uuid] == false then send [process-id-socket-binding] value and allow AS7 to perform property validation
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/TransactionsComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/TransactionsComponent.java
new file mode 100644
index 0000000..102118b
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/TransactionsComponent.java
@@ -0,0 +1,62 @@
+/*
+ * 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.modules.plugins.jbossas7;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+
+/**
+ * Support for transactions subsystem configuration updates.
+ *
+ * The special case for this subsystem:
+ *
+ * If [process-id-uuid] == true then do not send updates for [process-id-socket-binding], this property
+ * will be undefined by the AS7 on the next server reload/restart
+ *
+ * If [process-id-uuid] == false then send [process-id-socket-binding] value and
+ * allow AS7 to perform property validation
+ *
+ *
+ * @author Stefan Negrea
+ */
+public class TransactionsComponent extends BaseComponent<ResourceComponent<?>> {
+
+ @Override
+ public void updateResourceConfiguration(ConfigurationUpdateReport report) {
+ Configuration config = report.getConfiguration();
+ ConfigurationDefinition configDef = context.getResourceType().getResourceConfigurationDefinition();
+
+ boolean processIdUuid = Boolean.valueOf(config.getSimpleValue("process-id-uuid"));
+ if (processIdUuid == true) {
+ //Do not even send the updates for [process-id-socket-binding] because the AS7 will
+ //undefine it during the next reload/restart.
+ //Also, sending null for [process-id-socket-binding] with [process-id-uuid] == true causes
+ //a validation error on the server.
+ configDef.getPropertyDefinitions().remove("process-id-socket-binding");
+ config.remove("process-id-socket-binding");
+ }
+
+ ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(configDef, getASConnection(), address);
+ delegate.updateResourceConfiguration(report);
+ }
+}
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 0f150a4..29ef057 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
@@ -8338,7 +8338,7 @@
<service name="Transactions Subsystem (Standalone)"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="TransactionsComponent"
singleton="true"
description="The transactions subsystem.">
@@ -8460,7 +8460,7 @@
<service name="Transactions Subsystem (Profile)"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="TransactionsComponent"
singleton="true"
description="The transactions subsystem.">
@@ -8516,7 +8516,7 @@
<service name="Transactions Subsystem (Managed)"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="TransactionsComponent"
singleton="true"
description="The transactions subsystem.">
commit b8d890aaf85b9d3f74eb60d1bad32af02d030759
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 23:01:08 2012 -0500
[BZ 852552] Add two resource types to the list of ignored resources for this integration test. Both of these resources have special requirements with regards to configuration updates.
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
index aad8739..824162a 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
@@ -86,6 +86,9 @@ public class ResourcesStandaloneServerTest extends AbstractJBossAS7PluginTest {
//will revisit after BZ 826542 is resolved
// ignoredResources.add("Authentication (Classic)");
+ ignoredResources.add("Memory Pool");
+ ignoredResources.add("Periodic Rotating File Handler");
+
Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
Resource server = getResourceByTypeAndKey(platform, StandaloneServerComponentTest.RESOURCE_TYPE,
StandaloneServerComponentTest.RESOURCE_KEY);
commit a31197fcd63548c6e49606525b9938c123e5ffb2
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 22:59:02 2012 -0500
[BZ 852552] Update socket binding group to not send at all port-offset for non-standalone servers.
Just setting port-offset to null was not enough since now all the unset properties are sent to the AS7 server. The property and property definition are now removed from updates sent host controllers.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SocketBindingGroupComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SocketBindingGroupComponent.java
index 00d28ca..573db2e 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SocketBindingGroupComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SocketBindingGroupComponent.java
@@ -2,6 +2,7 @@ package org.rhq.modules.plugins.jbossas7;
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.pluginapi.configuration.ConfigurationFacet;
import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
@@ -29,12 +30,14 @@ public class SocketBindingGroupComponent extends BaseComponent implements Config
public void updateResourceConfiguration(ConfigurationUpdateReport report) {
Configuration config = report.getConfiguration();
+ ConfigurationDefinition configDef = context.getResourceType().getResourceConfigurationDefinition();
+
if (!(context.getParentResourceComponent() instanceof StandaloneASComponent)) { // TODO what about managed servers
- config.put(new PropertySimple("port-offset",null));
+ configDef.getPropertyDefinitions().remove("port-offset");
+ config.remove("port-offset");
}
- super.updateResourceConfiguration(report);
-
-
+ ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(configDef, getASConnection(), address);
+ delegate.updateResourceConfiguration(report);
}
}
commit 91aaaf71e585022ca85f62e371a7d63ae554ff6d
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 22:55:05 2012 -0500
[BZ 852552] Create a separate distributed cache definition because this resource contains addtional properties not available for invalidation and replicate caches.
The diferrence between these caches was obvious only after the updates to always send unset properties. All these extra properties (which are null) were sent to the server causing failures for caches that do not have them in their definition.
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 81ddfe9..0f150a4 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
@@ -2002,7 +2002,7 @@
class="TemplatedComponent">
<plugin-configuration>
- <c:simple-property name="path" readOnly="true" default="distributed-cache|invalidation-cache|replicated-cache"/>
+ <c:simple-property name="path" readOnly="true" default="invalidation-cache|replicated-cache"/>
</plugin-configuration>
<resource-configuration>
@@ -2031,30 +2031,64 @@
<c:simple-property name="queue-flush-interval" required="false" type="long" readOnly="true" default="10" description="In ASYNC mode, this attribute controls how often the asynchronous thread used to flush the replication queue runs. This should be a positive integer which represents thread wakeup time in milliseconds."/>
<c:simple-property name="remote-timeout" required="false" type="long" readOnly="true" default="17500" description="In SYNC mode, the timeout (in ms) used to wait for an acknowledgment when making a remote call, after which the call is aborted and an exception is thrown."/>
<c:simple-property name="async-marshalling" required="false" type="boolean" readOnly="true" defaultValue="false" description="If enabled, this will cause marshalling of entries to be performed asynchronously. The default value is false."/>
- <c:simple-property name="l1-lifespan" required="false" type="long" readOnly="true" defaultValue="600000" description="Maximum lifespan of an entry placed in the L1 cache. This element configures the L1 cache behavior in 'distributed' caches instances. In any other cache modes, this element is ignored. The default value is 600000."/>
<c:simple-property name="module" required="false" type="string" readOnly="true" description="The module whose class loader should be used when building this cache's configuration."/>
- <c:simple-property name="owners" required="false" type="integer" readOnly="true" defaultValue="2" description="Number of cluster-wide replicas for each cache entry. The default value is 2."/>
- <c:simple-property name="virtual-nodes" required="false" type="integer" readOnly="true" defaultValue="1" description="Controls the number of virtual nodes per 'real' node. If numVirtualNodes is 1, then virtual nodes are disabled. The topology aware consistent hash must be used if you wish to take advantage of virtual nodes. A default of 1 is used. The default value is 1."/>
- <c:simple-property name="__type" displayName="Type of cache" required="true" readOnly="true" default="local-cache" description="Type of cache">
+ <c:simple-property name="__type" displayName="Type of cache" required="true" readOnly="true" default="invalidation-cache" description="Type of cache">
<c:property-options>
<c:option value="invalidation-cache"/>
- <c:option value="distributed-cache"/>
<c:option value="replicated-cache"/>
</c:property-options>
</c:simple-property>
<c:template name="Invalidation Cache" description="Invalidation Cache">
<c:simple-property name="__type" readOnly="true" default="invalidation-cache"/>
</c:template>
- <c:template name="Distributed Cache" description="Distributed Cache">
- <c:simple-property name="__type" readOnly="true" default="distributed-cache"/>
- </c:template>
<c:template name="Replicated Cache" description="Replicated Cache">
<c:simple-property name="__type" readOnly="true" default="replicated-cache"/>
</c:template>
</resource-configuration>
</service>
+ <service name="Distributed Cache (Managed Server)"
+ discovery="SubsystemDiscovery"
+ class="BaseComponent">
+
+ <plugin-configuration>
+ <c:simple-property name="path" readOnly="true" default="distributed-cache"/>
+ </plugin-configuration>
+
+ <resource-configuration>
+ <c:simple-property name="start" required="false" type="string" readOnly="true" default="LAZY" description="The cache start mode, which can be EAGER (immediate start) or LAZY (on-demand start).">
+ <c:property-options>
+ <c:option value="LAZY"/>
+ <c:option value="EAGER"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="batching" required="false" type="boolean" readOnly="true" default="false" description="If enabled, the invocation batching API will be made available for this cache."/>
+ <c:simple-property name="indexing" required="false" type="string" readOnly="true" default="NONE" description="If enabled, entries will be indexed when they are added to the cache. Indexes will be updated as entries change or are removed.">
+ <c:property-options>
+ <c:option value="NONE"/>
+ <c:option value="LOCAL"/>
+ <c:option value="ALL"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="jndi-name" required="false" type="string" readOnly="true" description="The jndi-name to which to bind this cache instance."/>
+ <c:simple-property name="mode" required="false" type="string" readOnly="true" default="SYNC" description="Sets the clustered cache mode, ASYNC for asynchronous operation, or SYNC for synchronous operation.">
+ <c:property-options>
+ <c:option value="SYNC"/>
+ <c:option value="ASYNC"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="queue-size" required="false" type="integer" readOnly="true" default="0" description="In ASYNC mode, this attribute can be used to trigger flushing of the queue when it reaches a specific threshold."/>
+ <c:simple-property name="queue-flush-interval" required="false" type="long" readOnly="true" default="10" description="In ASYNC mode, this attribute controls how often the asynchronous thread used to flush the replication queue runs. This should be a positive integer which represents thread wakeup time in milliseconds."/>
+ <c:simple-property name="remote-timeout" required="false" type="long" readOnly="true" default="17500" description="In SYNC mode, the timeout (in ms) used to wait for an acknowledgment when making a remote call, after which the call is aborted and an exception is thrown."/>
+ <c:simple-property name="async-marshalling" required="false" type="boolean" readOnly="true" defaultValue="false" description="If enabled, this will cause marshalling of entries to be performed asynchronously. The default value is false."/>
+ <c:simple-property name="l1-lifespan" required="false" type="long" readOnly="true" defaultValue="600000" description="Maximum lifespan of an entry placed in the L1 cache. This element configures the L1 cache behavior in 'distributed' caches instances. In any other cache modes, this element is ignored. The default value is 600000."/>
+ <c:simple-property name="module" required="false" type="string" readOnly="true" description="The module whose class loader should be used when building this cache's configuration."/>
+ <c:simple-property name="owners" required="false" type="integer" readOnly="true" defaultValue="2" description="Number of cluster-wide replicas for each cache entry. The default value is 2."/>
+ <c:simple-property name="virtual-nodes" required="false" type="integer" readOnly="true" defaultValue="1" description="Controls the number of virtual nodes per 'real' node. If numVirtualNodes is 1, then virtual nodes are disabled. The topology aware consistent hash must be used if you wish to take advantage of virtual nodes. A default of 1 is used. The default value is 1."/>
+ </resource-configuration>
+ </service>
+
<service name="Local Cache (Managed Server)"
discovery="SubsystemDiscovery"
class="BaseComponent"
@@ -11331,7 +11365,7 @@
creationDataType="configuration">
<plugin-configuration>
- <c:simple-property name="path" readOnly="true" default="distributed-cache|invalidation-cache|replicated-cache"/>
+ <c:simple-property name="path" readOnly="true" default="invalidation-cache|replicated-cache"/>
</plugin-configuration>
<resource-configuration>
@@ -11360,30 +11394,66 @@
<c:simple-property name="queue-flush-interval" required="false" type="long" readOnly="false" default="10" description="In ASYNC mode, this attribute controls how often the asynchronous thread used to flush the replication queue runs. This should be a positive integer which represents thread wakeup time in milliseconds."/>
<c:simple-property name="remote-timeout" required="false" type="long" readOnly="false" default="17500" description="In SYNC mode, the timeout (in ms) used to wait for an acknowledgment when making a remote call, after which the call is aborted and an exception is thrown."/>
<c:simple-property name="async-marshalling" required="false" type="boolean" readOnly="false" defaultValue="false" description="If enabled, this will cause marshalling of entries to be performed asynchronously. The default value is false."/>
- <c:simple-property name="l1-lifespan" required="false" type="long" readOnly="false" defaultValue="600000" description="Maximum lifespan of an entry placed in the L1 cache. This element configures the L1 cache behavior in 'distributed' caches instances. In any other cache modes, this element is ignored. The default value is 600000."/>
<c:simple-property name="module" required="false" type="string" readOnly="false" description="The module whose class loader should be used when building this cache's configuration."/>
- <c:simple-property name="owners" required="false" type="integer" readOnly="false" defaultValue="2" description="Number of cluster-wide replicas for each cache entry. The default value is 2."/>
- <c:simple-property name="virtual-nodes" required="false" type="integer" readOnly="false" defaultValue="1" description="Controls the number of virtual nodes per 'real' node. If numVirtualNodes is 1, then virtual nodes are disabled. The topology aware consistent hash must be used if you wish to take advantage of virtual nodes. A default of 1 is used. The default value is 1."/>
- <c:simple-property name="__type" displayName="Type of cache" required="true" readOnly="true" default="local-cache" description="Type of cache">
+ <c:simple-property name="__type" displayName="Type of cache" required="true" readOnly="true" default="invalidation-cache" description="Type of cache">
<c:property-options>
<c:option value="invalidation-cache"/>
- <c:option value="distributed-cache"/>
<c:option value="replicated-cache"/>
</c:property-options>
</c:simple-property>
<c:template name="Invalidation Cache" description="Invalidation Cache">
<c:simple-property name="__type" readOnly="true" default="invalidation-cache"/>
</c:template>
- <c:template name="Distributed Cache" description="Distributed Cache">
- <c:simple-property name="__type" readOnly="true" default="distributed-cache"/>
- </c:template>
<c:template name="Replicated Cache" description="Replicated Cache">
<c:simple-property name="__type" readOnly="true" default="replicated-cache"/>
</c:template>
</resource-configuration>
</service>
+ <service name="Distributed Cache"
+ discovery="SubsystemDiscovery"
+ class="BaseComponent"
+ createDeletePolicy="both"
+ creationDataType="configuration">
+
+ <plugin-configuration>
+ <c:simple-property name="path" readOnly="true" default="distributed-cache"/>
+ </plugin-configuration>
+
+ <resource-configuration>
+ <c:simple-property name="start" required="false" type="string" readOnly="false" default="LAZY" description="The cache start mode, which can be EAGER (immediate start) or LAZY (on-demand start).">
+ <c:property-options>
+ <c:option value="LAZY"/>
+ <c:option value="EAGER"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="batching" required="false" type="boolean" readOnly="false" default="false" description="If enabled, the invocation batching API will be made available for this cache."/>
+ <c:simple-property name="indexing" required="false" type="string" readOnly="false" default="NONE" description="If enabled, entries will be indexed when they are added to the cache. Indexes will be updated as entries change or are removed.">
+ <c:property-options>
+ <c:option value="NONE"/>
+ <c:option value="LOCAL"/>
+ <c:option value="ALL"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="jndi-name" required="false" type="string" readOnly="false" description="The jndi-name to which to bind this cache instance."/>
+ <c:simple-property name="mode" required="true" type="string" readOnly="false" default="SYNC" defaultValue="SYNC" description="Sets the clustered cache mode, ASYNC for asynchronous operation, or SYNC for synchronous operation.">
+ <c:property-options>
+ <c:option value="SYNC"/>
+ <c:option value="ASYNC"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="queue-size" required="false" type="integer" readOnly="false" default="0" description="In ASYNC mode, this attribute can be used to trigger flushing of the queue when it reaches a specific threshold."/>
+ <c:simple-property name="queue-flush-interval" required="false" type="long" readOnly="false" default="10" description="In ASYNC mode, this attribute controls how often the asynchronous thread used to flush the replication queue runs. This should be a positive integer which represents thread wakeup time in milliseconds."/>
+ <c:simple-property name="remote-timeout" required="false" type="long" readOnly="false" default="17500" description="In SYNC mode, the timeout (in ms) used to wait for an acknowledgment when making a remote call, after which the call is aborted and an exception is thrown."/>
+ <c:simple-property name="async-marshalling" required="false" type="boolean" readOnly="false" defaultValue="false" description="If enabled, this will cause marshalling of entries to be performed asynchronously. The default value is false."/>
+ <c:simple-property name="l1-lifespan" required="false" type="long" readOnly="false" defaultValue="600000" description="Maximum lifespan of an entry placed in the L1 cache. This element configures the L1 cache behavior in 'distributed' caches instances. In any other cache modes, this element is ignored. The default value is 600000."/>
+ <c:simple-property name="module" required="false" type="string" readOnly="false" description="The module whose class loader should be used when building this cache's configuration."/>
+ <c:simple-property name="owners" required="false" type="integer" readOnly="false" defaultValue="2" description="Number of cluster-wide replicas for each cache entry. The default value is 2."/>
+ <c:simple-property name="virtual-nodes" required="false" type="integer" readOnly="false" defaultValue="1" description="Controls the number of virtual nodes per 'real' node. If numVirtualNodes is 1, then virtual nodes are disabled. The topology aware consistent hash must be used if you wish to take advantage of virtual nodes. A default of 1 is used. The default value is 1."/>
+ </resource-configuration>
+ </service>
+
<service name="Local Cache"
discovery="SubsystemDiscovery"
class="BaseComponent"
commit 9320bfa050c332a5f89334fcf5606395e5ef9098
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 22:46:02 2012 -0500
[BZ 852552] Update mod-cluster property name to load-balancing-group. The "domain" alias no longer works for load-balancing-group causing configuration updates to fail with unknown domain property.
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 bef06ec..81ddfe9 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
@@ -168,7 +168,7 @@
<c:simple-property name="connector" required="true" type="string" readOnly="false" defaultValue="ajp" description="Name of the web connector used to communicate with the load balancer.">
<c:option-source target="resource" expression="type=Connector plugin=&pluginName;"/>
</c:simple-property>
- <c:simple-property name="domain" required="false" type="string" readOnly="false" description="loadBalancingGroup name."/>
+ <c:simple-property name="load-balancing-group" required="false" type="string" readOnly="false" description="loadBalancingGroup name."/>
</c:group>
<c:group name="context" displayName="Web Context Options">
commit 9f82d413e980967ea3fae7ffe2579c44cc29cbb7
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 22:44:05 2012 -0500
[BZ 852552] Removing properties from the Transport subresource because the resource definition no longer contains them.
Because unset properties are now always sent to the AS7 server, all these removed Transport properties were sent to the AS7 causing an unknown property failure.
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 6f13412..bef06ec 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
@@ -2099,9 +2099,6 @@
<c:simple-property name="cluster" required="false" type="string" readOnly="true" description="The name of the group communication cluster"/>
<c:simple-property name="executor" required="false" type="string" readOnly="true" description="The executor to use for the transport"/>
<c:simple-property name="lock-timeout" required="false" type="long" readOnly="true" defaultValue="240000" description="The timeout for locks for the transport. The default value is 240000."/>
- <c:simple-property name="machine" required="false" type="string" readOnly="true" description="A machine identifier for the transport"/>
- <c:simple-property name="rack" required="false" type="string" readOnly="true" description="A rack identifier for the transport"/>
- <c:simple-property name="site" required="false" type="string" readOnly="true" description="A site identifier for the transport"/>
<c:simple-property name="stack" required="false" type="string" readOnly="true" description="The jgroups stack to use for the transport"/>
</resource-configuration>
</service>
@@ -11431,9 +11428,6 @@
<c:simple-property name="cluster" required="false" type="string" readOnly="false" description="The name of the group communication cluster"/>
<c:simple-property name="executor" required="false" type="string" readOnly="false" description="The executor to use for the transport"/>
<c:simple-property name="lock-timeout" required="false" type="long" readOnly="false" defaultValue="240000" description="The timeout for locks for the transport. The default value is 240000."/>
- <c:simple-property name="machine" required="false" type="string" readOnly="false" description="A machine identifier for the transport"/>
- <c:simple-property name="rack" required="false" type="string" readOnly="false" description="A rack identifier for the transport"/>
- <c:simple-property name="site" required="false" type="string" readOnly="false" description="A site identifier for the transport"/>
<c:simple-property name="stack" required="false" type="string" readOnly="false" description="The jgroups stack to use for the transport"/>
</resource-configuration>
</service>
commit c1655d4d576311b9034a31b505e75981b1d6e720
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 22:39:35 2012 -0500
[BZ 852552] Send unset properties to AS7 as null.
Existing code was not sending updates for unset properties at all to AS7 making it impossible to unset (or set to empty) a property after it was set to something not null.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
index aad2105..f73ccf5 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
@@ -431,16 +431,25 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
private void createWriteAttributePropertySimple(CompositeOperation cop, PropertySimple property,
PropertyDefinitionSimple propertyDefinition, Address address) {
- // If the property value is null and the property is optional, skip too
- if (property.getStringValue() == null && !propertyDefinition.isRequired())
- return;
-
if (property.getName().endsWith(":ignore")) // Caller takes care
return;
if (propertyDefinition.isReadOnly() && !createChildRequested)
return;
+ //If the property value is null and the property is optional,
+ //then send default value or null to the server
+ if (property.getStringValue() == null && !propertyDefinition.isRequired()) {
+ String name = property.getName();
+ if (name.indexOf(':') != -1) {
+ name = name.substring(0, name.indexOf(":"));
+ }
+
+ Operation writeAttribute = new WriteAttribute(address, name, null);
+ cop.addStep(writeAttribute);
+ return;
+ }
+
SimpleEntry<String, Object> entry = this.preparePropertySimple(property, propertyDefinition);
Operation writeAttribute = new WriteAttribute(address, entry.getKey(), entry.getValue());
cop.addStep(writeAttribute);
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java
index 21e3d5f..48b6783 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java
@@ -59,7 +59,6 @@ public class ConfigurationUpdatingTest extends AbstractConfigurationHandlingTest
public void test1() throws Exception {
ConfigurationDefinition definition = loadDescriptor("simple1");
-
FakeConnection connection = new FakeConnection();
ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(definition, connection, null);
@@ -70,12 +69,22 @@ public class ConfigurationUpdatingTest extends AbstractConfigurationHandlingTest
CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, new Address());
- assert cop.numberOfSteps() == 1;
- Operation step1 = cop.step(0);
- assert step1.getOperation().equals("write-attribute");
- Map<String, Object> props = step1.getAdditionalProperties();
- assert props.size() == 2;
+ Assert.assertEquals(cop.numberOfSteps(), 2);
+ for (int i = 0; i < cop.numberOfSteps(); i++) {
+ Operation step = cop.step(0);
+ Assert.assertEquals(step.getOperation(), "write-attribute");
+ Map<String, Object> stepProps = step.getAdditionalProperties();
+ Assert.assertEquals(stepProps.size(), 2);
+
+ if (stepProps.get("name").equals("needed")) {
+ Assert.assertEquals(stepProps.get("value"), "test");
+ } else if (stepProps.get("name").equals("optional")) {
+ Assert.assertEquals(stepProps.get("value"), null);
+ } else {
+ Assert.fail("Unexepected property found!");
+ }
+ }
}
public void test2() throws Exception {
commit e1d2190442ddcfe023696fa59b040f78929a27c6
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 20:14:08 2012 -0500
[BZ 846400] Add validation for components that rely connectors and discovery group name. A compoment should have either the connector or discovery group configured, but not both.
This validation is handled by the AS7 server itself for new resource creation but the validation is missing for configuration updates. Without this validation code in place, the AS7 server accepts the commands, persists the configuration, but fails to reload or restart rendering the server unusable until the configuration file is manually edited. With this fix, the AS7 plugin will not send the configuration updates to the AS7 server unless they meet the descriptor requirements.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConnectorDiscoveryGroupValidatorComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConnectorDiscoveryGroupValidatorComponent.java
new file mode 100644
index 0000000..fab342f
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConnectorDiscoveryGroupValidatorComponent.java
@@ -0,0 +1,83 @@
+/*
+ * 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.modules.plugins.jbossas7;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
+import org.rhq.core.domain.configuration.PropertyList;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public class ConnectorDiscoveryGroupValidatorComponent extends BaseComponent<ResourceComponent<?>> {
+
+ @Override
+ public void updateResourceConfiguration(ConfigurationUpdateReport report) {
+ Configuration resourceConfiguration = report.getConfiguration();
+ ResourceType resourceType = this.context.getResourceType();
+
+ // we need to check that a connector XOR a discovery-group-name is given
+ int configuredItemsFound = 0;
+ String errorMessage = "";
+
+ if (resourceType.getName().equals("Connection Factory")
+ || resourceType.getName().equals("Pooled Connection Factory")) {
+
+ PropertyMap connector = resourceConfiguration.getMap("connector:collapsed");
+ if (connector != null) {
+ String name = connector.getSimpleValue("name:0", "");
+ if (!name.isEmpty()) {
+ configuredItemsFound++;
+ }
+ }
+
+ errorMessage = "You need to provide either a connector name OR a discovery-group-name. ";
+ } else if (resourceType.getName().equals("Bridge") || resourceType.getName().equals("Cluster Connection")) {
+
+ PropertyList staticConnectors = resourceConfiguration.getList("static-connectors:nullable");
+ if (staticConnectors != null) {
+ if (!staticConnectors.getList().isEmpty()) {
+ configuredItemsFound++;
+ }
+ }
+
+ errorMessage = "You need to provide either static connectors name OR a discovery-group-name. ";
+ }
+
+ String discoveryGroup = resourceConfiguration.getSimpleValue("discovery-group-name", "");
+ if (!discoveryGroup.isEmpty()) {
+ configuredItemsFound++;
+ }
+
+ if (configuredItemsFound != 1) {
+ errorMessage += (configuredItemsFound == 0) ? "You provided none." : "You provided both.";
+ report.setErrorMessage(errorMessage);
+ report.setStatus(ConfigurationUpdateStatus.FAILURE);
+ } else {
+ super.updateResourceConfiguration(report);
+ }
+ }
+}
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HornetQComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HornetQComponent.java
index dad90bc..cd791fa 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HornetQComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HornetQComponent.java
@@ -21,9 +21,7 @@ package org.rhq.modules.plugins.jbossas7;
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.resource.CreateResourceStatus;
-import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pluginapi.inventory.CreateResourceReport;
/**
@@ -43,31 +41,6 @@ public class HornetQComponent extends TemplatedSubResourcesComponent {
return report;
}
- ResourceType resourceType = report.getResourceType();
- if (resourceType.getName().equals("Connection-Factory")) {
- // we need to check that a connector XOR a discovery-group-name is given
- int found = 0;
- PropertyMap connector = resourceConfiguration.getMap("connector:collapsed");
-
- if (connector != null) {
-
- String name = connector.getSimpleValue("name:0", "");
- if (!name.isEmpty())
- found++;
- }
- String discoveryGroup = resourceConfiguration.getSimpleValue("discovery-group-name", "");
- if (!discoveryGroup.isEmpty())
- found++;
-
- if (found == 0 || found == 2) {
- String errorMessage = "You need to provide either a connector name OR a discovery-group-name. You provided ";
- errorMessage += (found == 0) ? "none" : "both";
- report.setErrorMessage(errorMessage);
- report.setStatus(CreateResourceStatus.FAILURE);
- return report;
- }
- }
-
report = super.createResource(report);
return report;
}
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JmsComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JmsComponent.java
index 8b6eb12..1ede55e 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JmsComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JmsComponent.java
@@ -21,16 +21,13 @@ package org.rhq.modules.plugins.jbossas7;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
import org.rhq.core.domain.configuration.PropertyList;
-import org.rhq.core.domain.configuration.PropertyMap;
-import org.rhq.core.domain.resource.CreateResourceStatus;
-import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
/**
* Component class for the JMS subsystem
* @author Heiko W. Rupp
*/
-public class JmsComponent extends BaseComponent {
+public class JmsComponent extends ConnectorDiscoveryGroupValidatorComponent {
@Override
public void updateResourceConfiguration(ConfigurationUpdateReport report) {
@@ -43,31 +40,8 @@ public class JmsComponent extends BaseComponent {
return;
}
- ResourceType resourceType = context.getResourceType();
- if (resourceType.getName().equals("Connection-Factory")) {
- // we need to check that a connector XOR a discovery-group-name is given
- int found = 0;
- PropertyMap connector = resourceConfiguration.getMap("connector:collapsed");
-
- if (connector != null) {
-
- String name = connector.getSimpleValue("name:0", "");
- if (!name.isEmpty())
- found++;
- }
- String discoveryGroup = resourceConfiguration.getSimpleValue("discovery-group-name", "");
- if (!discoveryGroup.isEmpty())
- found++;
-
- if (found == 0 || found == 2) {
- String errorMessage = "You need to provide either a connector name OR a discovery-group-name. You provided ";
- errorMessage += (found == 0) ? "none" : "both";
- report.setErrorMessage(errorMessage);
- report.setStatus(ConfigurationUpdateStatus.FAILURE);
- return;
- }
- }
-
+ //defer the rest of the validation for connector and discovery group name to
+ //the base class
super.updateResourceConfiguration(report);
}
}
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 8143d04..6f13412 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
@@ -4654,7 +4654,7 @@
<service name="Cluster Connection (Managed Server)"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="ConnectorDiscoveryGroupValidatorComponent"
createDeletePolicy="neither">
<plugin-configuration>
@@ -4784,7 +4784,7 @@
<service name="Bridge (Managed Server)"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="ConnectorDiscoveryGroupValidatorComponent"
createDeletePolicy="neither">
<plugin-configuration>
@@ -6804,7 +6804,7 @@
<service name="Cluster Connection (Profile)"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="ConnectorDiscoveryGroupValidatorComponent"
createDeletePolicy="both">
<plugin-configuration>
@@ -6893,7 +6893,7 @@
<service name="Bridge (Profile)"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="ConnectorDiscoveryGroupValidatorComponent"
createDeletePolicy="both">
<plugin-configuration>
@@ -12855,7 +12855,7 @@
<service name="Cluster Connection"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="ConnectorDiscoveryGroupValidatorComponent"
createDeletePolicy="both">
<plugin-configuration>
@@ -12985,7 +12985,7 @@
<service name="Bridge"
discovery="SubsystemDiscovery"
- class="BaseComponent"
+ class="ConnectorDiscoveryGroupValidatorComponent"
createDeletePolicy="both">
<plugin-configuration>
commit e96ce182758719f86364bdc7a2e73c287dddbe4c
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 28 15:22:40 2012 -0500
[BZ 852534] Collapsed maps with null keys should be set to null. Attempting to send maps with null values to the application server results in validation errors.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
index 8286f17..aad2105 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
@@ -628,10 +628,14 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
throw new IllegalArgumentException("Member names in a :collapsed map must end in :0 and :1");
}
- Map<String, Object> resultMap = new HashMap<String, Object>();
- resultMap.put(key, value);
+ if (key != null) {
+ Map<String, Object> resultMap = new HashMap<String, Object>();
+ resultMap.put(key, value);
- return resultMap;
+ return resultMap;
+ } else {
+ return null;
+ }
}
commit 9fda60f21e354f3b33a1ecf85b81cae19e0af1af
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Tue Aug 28 14:34:23 2012 +0200
[BZ 850818 - Globally uncaught exception on clicking OK button while adding CLI Script alert notification to the alert definition] Added the check whether the repository has been picked
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java
index f63eb55..b212043 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java
@@ -403,6 +403,11 @@ public class CliNotificationSenderForm extends AbstractNotificationSenderForm {
}
private void validatePackage(final AsyncCallback<Void> callback) {
+ if (config.selectedRepo == null) {
+ repoSelector.setIcons(failureIcon);
+ callback.onFailure(null);
+ return;
+ }
getConfiguration().put(new PropertySimple(PROP_REPO_ID, config.selectedRepo.getId()));
if (packageSelector.getSelectedIndex() == 0) {
commit f3f26d0a85bf71fad532424b6267a331bd048136
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Aug 27 14:42:26 2012 -0700
[BZ 848501] - IE8 rendering of resource measurement time overlaid on the actual metric name
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
index c27e626..8a0898d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
@@ -290,6 +290,7 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet {
StaticTextItem value = AbstractActivityView
.newTextItem(convertedValue);
value.setVAlign(VerticalAlignment.TOP);
+ value.setAlign(Alignment.RIGHT);
row.setItems(graphContainer, link, value);
row.setWidth100();
commit b8a6a496d40915abb22fdd87753aec0c131ed95d
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Fri Aug 24 10:21:20 2012 -0500
[BZ 849964] Increase the operation timeout to 30 seconds to avoid cases where the host is under heavy load thus making all managed server operations take longer than the default 10 seconds.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java
index d26f54e..e7fcd5b 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java
@@ -271,7 +271,7 @@ public class ManagedASComponent extends BaseComponent<HostControllerComponent<?>
}
}
- Result res = getASConnection().execute(op);
+ Result res = getASConnection().execute(op, 30);
OperationResult opRes;
if (res.isSuccess()) {
commit 97867e2b4b241fa5ea33d0f439b1026914def5be
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Thu Aug 23 16:55:00 2012 +0200
[BZ 851239 - Globally uncaught exception on clicking the link Bundles->Repositories->JBoss Patches] Defensive programming - check for null/empty list -> exception is not thrown
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java
index 6eaa263..1f2f660 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java
@@ -42,7 +42,11 @@ import org.rhq.core.domain.bundle.Bundle;
import org.rhq.core.domain.criteria.BundleCriteria;
import org.rhq.core.domain.tagging.Tag;
import org.rhq.core.domain.util.PageList;
-import org.rhq.enterprise.gui.coregui.client.*;
+import org.rhq.enterprise.gui.coregui.client.BookmarkableView;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.IconEnum;
+import org.rhq.enterprise.gui.coregui.client.ViewId;
+import org.rhq.enterprise.gui.coregui.client.ViewPath;
import org.rhq.enterprise.gui.coregui.client.bundle.BundleTopView;
import org.rhq.enterprise.gui.coregui.client.bundle.deploy.BundleDeployWizard;
import org.rhq.enterprise.gui.coregui.client.bundle.deployment.BundleDeploymentView;
@@ -286,6 +290,11 @@ public class BundleView extends LocatableVLayout implements BookmarkableView {
}
public void onSuccess(PageList<Bundle> result) {
+ if (result == null || result.isEmpty()) {
+ CoreGUI.getMessageCenter().notify(
+ new Message(MSG.view_bundle_list_error4(), Message.Severity.Error));
+ return;
+ }
Bundle bundle = result.get(0);
viewBundle(bundle, viewPath.getCurrent());
}
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index cfa1f6d..9681ea1 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -413,10 +413,10 @@ filter_from_date = From
filter_to_date = To
group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
-search_invalid_search_expression = Invalid search expression.
-search_failed_to_save_search = Failed to Save Search: {0}
search_failed_to_retrieve_saved_search = Failed to retrieve saved search
search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
+search_failed_to_save_search = Failed to Save Search: {0}
+search_invalid_search_expression = Invalid search expression.
search_name_your_search = name you search
search_successfully_saved_search = Successfully Saved Search: {0}
util_ancestry_parentAncestry = Parent Ancestry for:
@@ -1127,6 +1127,7 @@ view_bundle_list_destinationsCount = Destinations Count
view_bundle_list_error1 = Failed to load bundle to deploy [{0}]
view_bundle_list_error2 = Failed to get a single bundle to deploy [{0}]
view_bundle_list_error3 = Failed to load bundle
+view_bundle_list_error4 = No bundles found in this repository
view_bundle_list_loadFailure = Failed to load the bundle to be deployed [{0}]
view_bundle_list_loadWithLatestFailure = Failed to load bundle with the latest version data
view_bundle_list_singleLoadFailure = Failed to get a single bundle to be deployed [{0}]
@@ -1182,7 +1183,7 @@ view_configEdit_error_3 = Cannot add property named [{0}]. The property name is
view_configEdit_files = Files
view_configEdit_hideAll = Hide All
view_configEdit_jumpToSection = Jump to Section
-view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
view_configEdit_msg_1 = Added property [{0}] to the set.
view_configEdit_msg_2 = Removed properties from the set.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index 5be0d57..b2a842d 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -1146,6 +1146,7 @@ view_bundle_list_destinationsCount = Počet cílů
view_bundle_list_error1 = Nepodařilo se načíst balík k nasazení [{0}]
view_bundle_list_error2 = Nepodařilo se získat 1 balík k nasazení [{0}]
view_bundle_list_error3 = Nepodařilo se získat balík
+view_bundle_list_error3 = V tomto repozitáři nejsou žádné balíky
view_bundle_list_loadFailure = Nepodařilo se získat balík k nasazení [{0}]
view_bundle_list_loadWithLatestFailure = Nepodařilo se získat balík s poslední verzí
view_bundle_list_singleLoadFailure = Nepodařilo se získat 1 balík k nasazení [{0}]
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index d39f16a..4fe89d0 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -397,10 +397,10 @@ filter_from_date = Von
filter_to_date = Bis
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} der {1} Gruppenmitglieder haben eine ''{2}'' Ressource
-##search_invalid_search_expression = Invalid search expression.
-##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
+##search_failed_to_save_search = Failed to Save Search: {0}
+##search_invalid_search_expression = Invalid search expression.
##search_name_your_search = name you search
##search_successfully_saved_search = Successfully Saved Search: {0}
util_disambiguationReportDecorator_pluginSuffix = ({0} Plugin)
@@ -1013,6 +1013,7 @@ view_bundle_list_destinationsCount = Anzahl Ziele
##view_bundle_list_error1 = Failed to load bundle to deploy [{0}]
##view_bundle_list_error2 = Failed to get a single bundle to deploy [{0}]
view_bundle_list_error3 = Konnte das Bundle nicht laden
+##view_bundle_list_error4 = No bundles found in this repository
##view_bundle_list_loadFailure = Failed to load the bundle to be deployed [{0}]
##view_bundle_list_loadWithLatestFailure = Failed to load bundle with the latest version data
##view_bundle_list_singleLoadFailure = Failed to get a single bundle to be deployed [{0}]
@@ -1066,7 +1067,7 @@ view_configEdit_confirm_2 = Sind Sie sicher dass sie diese Zeile löschen wollen
view_configEdit_files = Dateien
view_configEdit_hideAll = Alle verbergen
view_configEdit_jumpToSection = Zum Abschnitt springen
-##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
view_configEdit_msg_1 = Eigentschaft [{0}] zur Menge hinzugefügt
##view_configEdit_msg_2 = Removed properties from the set.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index 6c2044a..e2e25e8 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -1123,6 +1123,7 @@ view_bundle_list_destinationsCount = 宛先数
view_bundle_list_error1 = [{0}] をデプロイするためのバンドルのロードに失敗しました
view_bundle_list_error2 = [{0}] をデプロイするための単一バンドルの取得に失敗しました
view_bundle_list_error3 = バンドルのロードに失敗しました
+##view_bundle_list_error4 = No bundles found in this repository
view_bundle_list_loadFailure = デプロイされるバンドル [{0}] のロードに失敗しました
view_bundle_list_loadWithLatestFailure = 最新バージョンデータを持つバンドルのロードに失敗しました
view_bundle_list_singleLoadFailure = デプロイされる単一バンドル [{0}] の取得に失敗しました
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 9f00c55..e3f044f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -416,10 +416,10 @@ favorites_resources = Recursos Favoritos
##filter_to_date = To
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
-##search_invalid_search_expression = Invalid search expression.
-##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
+##search_failed_to_save_search = Failed to Save Search: {0}
+##search_invalid_search_expression = Invalid search expression.
##search_name_your_search = name you search
##search_successfully_saved_search = Successfully Saved Search: {0}
util_ancestry_parentAncestry = Ancestral para:
@@ -1133,6 +1133,7 @@ view_bundle_list_destinationsCount = Soma das Destina\u00E7\u00F5es
view_bundle_list_error1 = Falha ao carregar bundle [{0}] para implantar
view_bundle_list_error2 = Falha ao obter um \u00FAnico bundle [{0}] para deploy
view_bundle_list_error3 = Falha ao carregar o bundle
+##view_bundle_list_error4 = No bundles found in this repository
view_bundle_list_loadFailure = Falha ao carregar o bundle [{0}] para ser implantado
view_bundle_list_loadWithLatestFailure = Falha ao carregar o bundle com os dados da \u00FAltima vers\u00E3o
view_bundle_list_singleLoadFailure = Falha ao obter um \u00FAnico bundle [{0}] para ser implantado
@@ -1188,7 +1189,7 @@ view_configEdit_error_3 = N\u00E3o f\u00F3 poss\u00EDvel adicionar a propriedade
view_configEdit_files = Arquivos
view_configEdit_hideAll = Ocultar todos
view_configEdit_jumpToSection = Ir direto para a Sele\u00E7\u00E3o
-##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
view_configEdit_msg_1 = Propriedade [{0}] adicionada ao conjunto.
view_configEdit_msg_2 = Propriedades removidas do conjunto.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 25671e1..e27ce16 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -2464,6 +2464,7 @@ view_admin_downloads_cli_version = Версия CLI
##view_admin_downloads_connectors_none = No connectors are available for download
##view_alert_details_field_resource_ancestry = Resource Ancestry
##view_alert_details_field_watched_resource = Watched Resource
+##view_bundle_list_error4 = No bundles found in this repository
##view_bundle_revertWizard_getInfoStep_revertDeployDescFull = [REVERT From] {0} [REVERT To] {1}
##view_configEdit_property = Property
##view_configEdit_unset = Unset?
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 827e01b..2de43cc 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -405,10 +405,10 @@ favorites_resources = \u8d44\u6e90\u6536\u85cf\u5939
##filter_to_date = To
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = \u9664\u53bb {1},{0}\u7684\u7ec4\u6210\u5458\u62e5\u6709 \u4e00\u4e2a''{2}''\u8d44\u6e90
-##search_invalid_search_expression = Invalid search expression.
-##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
+##search_failed_to_save_search = Failed to Save Search: {0}
+##search_invalid_search_expression = Invalid search expression.
##search_name_your_search = name you search
##search_successfully_saved_search = Successfully Saved Search: {0}
util_ancestry_parentAncestry = Parent Ancestry for:
@@ -1117,6 +1117,7 @@ view_bundle_list_destinationsCount = \u76ee\u7684\u5730\u6570
view_bundle_list_error1 = Failed to load bundle to deploy [{0}]
view_bundle_list_error2 = Failed to get a single bundle to deploy [{0}]
view_bundle_list_error3 = \u52a0\u8f7dbundle\u5931\u8d25
+##view_bundle_list_error4 = No bundles found in this repository
view_bundle_list_loadFailure = Failed to load the bundle to be deployed [{0}]
view_bundle_list_loadWithLatestFailure = Failed to load bundle with the latest version data
view_bundle_list_singleLoadFailure = Failed to get a single bundle to be deployed [{0}]
@@ -1172,7 +1173,7 @@ view_configEdit_error_3 = \u65e0\u6cd5\u6dfb\u52a0\u540d\u4e3a[{0}]\u7684\u5c5e\
view_configEdit_files = \u6587\u4ef6
view_configEdit_hideAll = \u9690\u85cf\u6240\u6709
view_configEdit_jumpToSection = \u8df3\u81f3\u6a21\u5757
-##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_maxBoundsExceeded = Cannot add another entry because the maximum size bounds has been met: {0}
##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
view_configEdit_msg_1 = \u589e\u52a0\u5c5e\u6027 [{0}]\u5230\u96c6\u5408.
view_configEdit_msg_2 = \u79fb\u9664\u96c6\u5408\u5185\u6240\u6709\u7684\u5c5e\u6027.
commit 8fb35be5c92397b282a582c754c6b71b8b277a60
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Aug 23 12:08:11 2012 +0200
Duplicating all the tests that use scripting language to have both javascript and python versions.
diff --git a/modules/enterprise/binding/pom.xml b/modules/enterprise/binding/pom.xml
index 7d37053..37959d2 100644
--- a/modules/enterprise/binding/pom.xml
+++ b/modules/enterprise/binding/pom.xml
@@ -45,6 +45,13 @@
</dependency>
<dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-scripting-python</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
<groupId>${project.groupId}</groupId>
<artifactId>rhq-core-domain</artifactId>
<version>${project.version}</version>
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java
index c3d5450..cf93afb 100644
--- a/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java
@@ -40,19 +40,24 @@ import org.rhq.bindings.util.PackageFinder;
*
* @author Lukas Krejci
*/
-@Test
-public class ScriptEngineTest {
+public class ScriptEngineTest extends ScriptedTestBase {
private static StandardBindings EMPTY_BINDINGS = new StandardBindings(new PrintWriter(System.out), new FakeRhqFacade());
@Test
- public void testFactory() throws ScriptException, IOException {
+ public void testFactory_javascript() throws ScriptException, IOException {
ScriptEngine engine = getScriptEngine();
assertNotNull(engine);
}
@Test
- public void testSandbox() throws ScriptException, IOException {
+ public void testFactory_python() throws ScriptException, IOException {
+ ScriptEngine engine = getScriptEngine();
+ assertNotNull(engine);
+ }
+
+ @Test
+ public void testSandbox_javascript() throws ScriptException, IOException {
ScriptEngine sandbox = getSecuredScriptEngine();
try {
@@ -76,7 +81,44 @@ public class ScriptEngineTest {
}
@Test
- public void testStandardBindings() throws ScriptException, IOException {
+ public void testSandbox_python() throws Exception {
+ ScriptEngine sandbox = getSecuredScriptEngine();
+
+ try {
+ sandbox.eval("import java.lang as foo\nfoo.System.exit(1)");
+ } catch (Exception e) {
+ assertSecurityExceptionPresent(e);
+ }
+
+ try {
+ //try hard to get to the System.exit()
+ sandbox.eval(
+ "import java.lang as l\n" +
+ "import java.lang.reflect as r\n" +
+ "import java.beans as b\n" +
+ "cls = l.Class.forName('java.lang.System')\n" +
+ "params = r.Array.newInstance(l.Class.forName('java.lang.Object'), 1)\n" +
+ "params[0] = l.Integer.valueOf('1')\n" +
+ "st = b.Statement(cls, 'exit', params)\n" +
+ "st.execute()");
+
+ } catch (Exception e) {
+ assertSecurityExceptionPresent(e);
+ }
+ }
+
+ @Test
+ public void testStandardBindings_javascript() throws ScriptException, IOException {
+ ScriptEngine scriptEngine = getScriptEngine();
+
+ for(String var : EMPTY_BINDINGS.keySet()) {
+ boolean hasVar = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE).containsKey(var);
+ assertTrue(hasVar, "The variable '" + var + "' is not present in the script context but should be.");
+ }
+ }
+
+ @Test
+ public void testStandardBindings_python() throws Exception {
ScriptEngine scriptEngine = getScriptEngine();
for(String var : EMPTY_BINDINGS.keySet()) {
@@ -86,13 +128,11 @@ public class ScriptEngineTest {
}
private ScriptEngine getScriptEngine() throws ScriptException, IOException {
- return ScriptEngineFactory.getScriptEngine("javascript", new PackageFinder(Collections.<File> emptyList()),
- EMPTY_BINDINGS);
+ return getScriptEngine(new PackageFinder(Collections.<File> emptyList()), EMPTY_BINDINGS);
}
private ScriptEngine getSecuredScriptEngine() throws ScriptException, IOException {
- return ScriptEngineFactory.getSecuredScriptEngine("javascript",
- new PackageFinder(Collections.<File> emptyList()), EMPTY_BINDINGS, new StandardScriptPermissions());
+ return getSecuredScriptEngine(new PackageFinder(Collections.<File> emptyList()), EMPTY_BINDINGS, new StandardScriptPermissions());
}
private void assertSecurityExceptionPresent(Throwable t) {
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptedTestBase.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptedTestBase.java
new file mode 100644
index 0000000..9bf09b5
--- /dev/null
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptedTestBase.java
@@ -0,0 +1,220 @@
+/*
+ * 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.bindings;
+
+import static org.testng.Assert.fail;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.security.PermissionCollection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+import org.testng.IHookCallBack;
+import org.testng.IHookable;
+import org.testng.ITestContext;
+import org.testng.ITestNGMethod;
+import org.testng.ITestResult;
+import org.testng.annotations.AfterClass;
+
+import org.rhq.bindings.util.PackageFinder;
+
+/**
+ * This is a base class for tests that need to test the some functionality using
+ * the scripting languages.
+ * <p>
+ * It enforces the naming convention for the tests:
+ * <code>
+ * @Test
+ * public void myTestMethod_language() ...
+ * </code>
+ * The language is to be replaced with the name of the scripting language that the test method
+ * uses (e.g. javacript, python). This class then makes sure that each test exists for all
+ * the scripting languages that are present on the classpath.
+ * <p>
+ * This class also provides the {@link #getScriptEngine(PackageFinder, StandardBindings)} and
+ * {@link #getSecuredScriptEngine(PackageFinder, StandardBindings, PermissionCollection)} methods
+ * that, if invoked from within a test method call-chain, will return the script engine for the
+ * correct language under test (determined by the test method name suffix).
+ *
+ * @author Lukas Krejci
+ */
+public abstract class ScriptedTestBase implements IHookable {
+
+ private String currentLanguage;
+
+ @AfterClass
+ public void checkTestImplsForEachLanguage(ITestContext ctx) {
+ Set<Method> methods = getAllTestMethods(getClass(), ctx);
+
+ Set<String> supportedLanguages = ScriptEngineFactory.getSupportedLanguages();
+
+ Map<String, Set<String>> methodBaseNamesByLanguage = new HashMap<String, Set<String>>();
+
+ for (String lang : supportedLanguages) {
+ methodBaseNamesByLanguage.put(lang, new HashSet<String>());
+ }
+
+ Set<Method> invalidTestMethods = new HashSet<Method>();
+
+ for (Method m : methods) {
+ //check that the method name ends with one of the supported language names
+ boolean valid = false;
+ for (String lang : supportedLanguages) {
+ String suffix = "_" + lang;
+
+ if (!m.getName().endsWith(suffix)) {
+ continue;
+ }
+
+ //now put the method "basename" into our mapping array
+ String baseName = m.getName().substring(0, m.getName().lastIndexOf("_"));
+ methodBaseNamesByLanguage.get(lang).add(baseName);
+
+ valid = true;
+ break;
+ }
+
+ if (!valid) {
+ invalidTestMethods.add(m);
+ }
+ }
+
+ Set<String> missingTests = new HashSet<String>();
+
+ //now check that all languages have all test methods
+ for (Map.Entry<String, Set<String>> a : methodBaseNamesByLanguage.entrySet()) {
+ for (Map.Entry<String, Set<String>> b : methodBaseNamesByLanguage.entrySet()) {
+ String alang = a.getKey();
+ String blang = b.getKey();
+ Set<String> amethods = a.getValue();
+ Set<String> bmethods = b.getValue();
+
+ if (alang.equals(blang)) {
+ continue;
+ }
+
+ addMissing(amethods, bmethods, alang, missingTests);
+ addMissing(bmethods, amethods, blang, missingTests);
+ }
+ }
+
+ if (!invalidTestMethods.isEmpty() || !missingTests.isEmpty()) {
+ StringBuilder msg = new StringBuilder("Scripted test " + getClass() + " is invalid:\n");
+
+ if (!invalidTestMethods.isEmpty()) {
+ msg.append("Invalid method names:\n");
+ for (Method m : invalidTestMethods) {
+ msg.append(m.getName()).append("\n");
+ }
+ }
+
+ if (!missingTests.isEmpty()) {
+ msg.append("\nMissing tests for languages:\n");
+ for (String m : missingTests) {
+ msg.append(m).append("\n");
+ }
+ }
+
+ fail(msg.toString());
+ }
+ }
+
+ @Override
+ public final void run(IHookCallBack callBack, ITestResult testResult) {
+ String methodName = testResult.getMethod().getMethodName();
+ int underScoreIdx = methodName.lastIndexOf('_');
+ if (underScoreIdx >= 0 && underScoreIdx < methodName.length() - 1) {
+ currentLanguage = methodName.substring(underScoreIdx + 1);
+ } else {
+ currentLanguage = null;
+ }
+
+ callBack.runTestMethod(testResult);
+
+ currentLanguage = null;
+ }
+
+ /**
+ * Returns a new script engine implementation for the current test method.
+ * <p>
+ * The script engine implementation is determined based on the test method's name
+ * suffix.
+ * <p>
+ * E.g. if the test method ends with "_javascript", this method will return the javascript
+ * script engine.
+ * <p>
+ * This method is calling {@link ScriptEngineFactory#getScriptEngine(String, PackageFinder, StandardBindings)}
+ * but determines the "language" parameter for you.
+ *
+ * @param packageFinder the package finder to use for the script engine initialization
+ * @param bindings the bindings to use in the script engine
+ * @return the script engine
+ * @throws ScriptException
+ * @throws IOException
+ */
+ protected ScriptEngine getScriptEngine(PackageFinder packageFinder, StandardBindings bindings)
+ throws ScriptException, IOException {
+
+ return ScriptEngineFactory.getScriptEngine(currentLanguage, packageFinder, bindings);
+ }
+
+ /**
+ * Similar to {@link #getScriptEngine(PackageFinder, StandardBindings)} but returns the
+ * secured version of the script engine.
+ *
+ * @param packageFinder the package finder to use for the script engine initialization
+ * @param bindings the bindings to use in the script engine
+ * @param perms the permissions to run the scripts with
+ * @return the script engine
+ * @throws ScriptException
+ * @throws IOException
+ */
+ protected ScriptEngine getSecuredScriptEngine(PackageFinder packageFinder, StandardBindings bindings,
+ PermissionCollection perms) throws ScriptException, IOException {
+
+ return ScriptEngineFactory.getSecuredScriptEngine(currentLanguage, packageFinder, bindings, perms);
+ }
+
+ private static Set<Method> getAllTestMethods(Class<?> cls, ITestContext ctx) {
+ HashSet<Method> ret = new HashSet<Method>();
+ for (ITestNGMethod m : ctx.getAllTestMethods()) {
+ if (m.getTestClass().getRealClass().equals(cls)) {
+ ret.add(m.getConstructorOrMethod().getMethod());
+ }
+ }
+
+ return ret;
+ }
+
+ private static void addMissing(Set<String> methods, Set<String> referenceMethods, String lang, Set<String> missing) {
+ for (String m : referenceMethods) {
+ if (!methods.contains(m)) {
+ String fullName = m + "_" + lang;
+ missing.add(fullName);
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java
index 1d7f657..97753e3 100644
--- a/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java
@@ -26,118 +26,247 @@ package org.rhq.bindings.util;
import static org.testng.Assert.fail;
import java.io.File;
+import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
-import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import org.rhq.bindings.FakeRhqFacade;
-import org.rhq.bindings.ScriptEngineFactory;
+import org.rhq.bindings.ScriptedTestBase;
import org.rhq.bindings.StandardBindings;
-public class ScriptAssertTest {
+public class ScriptAssertTest extends ScriptedTestBase {
- private ScriptEngine engine;
+ private ScriptEngine getScriptEngine() {
+ try {
+ return getScriptEngine(new PackageFinder(Collections.<File> emptyList()), new StandardBindings(
+ new PrintWriter(System.out), new FakeRhqFacade()));
+ } catch (ScriptException e) {
+ fail("Could not get the script engine.", e);
+ return null;
+ } catch (IOException e) {
+ fail("Could not get the script engine.", e);
+ return null;
+ }
+ }
- @BeforeTest
- public void verifyScriptEngineIsAvailable() throws Exception {
- StandardBindings bindings = new StandardBindings(new PrintWriter(System.out), new FakeRhqFacade());
- engine = ScriptEngineFactory.getScriptEngine("javascript", new PackageFinder(Collections.<File> emptyList()),
- bindings);
+ @Test
+ public void testAssertExists_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "var a = 1; assertExists('a');", "assertExists should succeed for a defined variable.");
+ testThrowsAssertion(engine, "assertExists('foo')", "assertExists should fail for an undefined variable.");
+ testWorks(engine, "function func() { return 42 }; assertExists('func');",
+ "assertExists should succeed for a defined function.");
}
@Test
- public void testAssertExists() {
- testWorks("var a = 1; assertExists('a');", "assertExists should succeed for a defined variable.");
- testThrowsAssertion("assertExists('foo')", "assertExists should fail for an undefined variable.");
- testWorks("function func() { return 42 }; assertExists('func');",
+ public void testAssertExists_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "a = 1\n" + "assertExists('a')", "assertExists should succeed for a defined variable.");
+ testThrowsAssertion(engine, "assertExists('foo')", "assertExists should fail for an undefined variable.");
+ testWorks(engine, "def func():\n" + " return 42\n" + "assertExists('func')",
"assertExists should succeed for a defined function.");
}
@Test
- public void testAssertTrue() {
- testWorks("var a = true; assertTrue(a);", "assertTrue of a true variable should succeed");
- testWorks("assertTrue(1 == 1)", "assertTrue on a true boolean expression should succeed");
- testThrowsAssertion("var a = false; assertTrue(a)", "assertTrue should fail on a false variable");
- testThrowsAssertion("assertTrue(1 == 2)", "assertTrue should fail on a false boolean expression");
+ public void testAssertTrue_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "var a = true; assertTrue(a);", "assertTrue of a true variable should succeed");
+ testWorks(engine, "assertTrue(1 == 1)", "assertTrue on a true boolean expression should succeed");
+ testThrowsAssertion(engine, "var a = false; assertTrue(a)", "assertTrue should fail on a false variable");
+ testThrowsAssertion(engine, "assertTrue(1 == 2)", "assertTrue should fail on a false boolean expression");
+ }
+
+ @Test
+ public void testAssertTrue_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "a = True\n" + "assertTrue(a)", "assertTrue of a true variable should succeed");
+ testWorks(engine, "assertTrue(1 == 1)", "assertTrue on a true boolean expression should succeed");
+ testThrowsAssertion(engine, "a = False\n" + "assertTrue(a)", "assertTrue should fail on a false variable");
+ testThrowsAssertion(engine, "assertTrue(1 == 2)", "assertTrue should fail on a false boolean expression");
+ }
+
+ @Test
+ public void testAssertFalse_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "var a = false; assertFalse(a)", "assertFalse of a false variable should succeed");
+ testWorks(engine, "assertFalse(1 == 2)", "assertFalse on a false boolean expression should succeed");
+ testThrowsAssertion(engine, "var a = true; assertFalse(a)", "assertFalse should fail on a true variable");
+ testThrowsAssertion(engine, "assertFalse(1 == 1)", "assertFalse should fail on a true boolean expression");
}
-
+
@Test
- public void testAssertFalse() {
- testWorks("var a = false; assertFalse(a);", "assertFalse of a false variable should succeed");
- testWorks("assertFalse(1 == 2)", "assertFalse on a false boolean expression should succeed");
- testThrowsAssertion("var a = true; assertFalse(a)", "assertFalse should fail on a true variable");
- testThrowsAssertion("assertFalse(1 == 1)", "assertFalse should fail on a true boolean expression");
+ public void testAssertFalse_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "a = False\n" + "assertFalse(a)", "assertFalse of a false variable should succeed");
+ testWorks(engine, "assertFalse(1 == 2)", "assertFalse on a false boolean expression should succeed");
+ testThrowsAssertion(engine, "a = True\n" + "assertFalse(a)", "assertFalse should fail on a true variable");
+ testThrowsAssertion(engine, "assertFalse(1 == 1)", "assertFalse should fail on a true boolean expression");
}
-
+
@Test
- public void testAssertNull() {
- testWorks("assertNull(foo)", "assertNull should succeed on an undefined variable");
- testWorks("var foo = null; assertNull(foo);", "assertNull should succeed on a null variable");
- testWorks("assertNull(null)", "assertNull should succeed on a null literal");
- testThrowsAssertion("assertNull(1)", "assertNull should fail on a number");
- testThrowsAssertion("var foo = '1'; assertNull(foo)", "assertNull should fail on a non-null variable");
+ public void testAssertNull_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "var foo = null; assertNull(foo);", "assertNull should succeed on a null variable");
+ testWorks(engine, "assertNull(null)", "assertNull should succeed on a null literal");
+ testThrowsAssertion(engine, "assertNull(1)", "assertNull should fail on a number");
+ testThrowsAssertion(engine, "var foo = '1'; assertNull(foo)", "assertNull should fail on a non-null variable");
}
-
+
@Test
- public void testAssertNotNull() {
- testWorks("assertNotNull(1)", "assertNotNull should succeed on a number");
- testWorks("var foo = '1'; assertNotNull(foo)", "assertNotNull should succeed on a non-null variable");
- testThrowsAssertion("assertNotNull(foo)", "assertNotNull should fail on an undefined variable");
- testThrowsAssertion("var foo = null; assertNotNull(foo);", "assertNotNull should fail on a null variable");
- testThrowsAssertion("assertNotNull(null)", "assertNotNull should fail on a null literal");
+ public void testAssertNull_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "foo = None\n" + "assertNull(foo)", "assertNull should succeed on a null variable");
+ testWorks(engine, "assertNull(None)", "assertNull should succeed on a null literal");
+ testThrowsAssertion(engine, "assertNull(1)", "assertNull should fail on a number");
+ testThrowsAssertion(engine, "foo = '1'\n" + "assertNull(foo)", "assertNull should fail on a non-null variable");
}
-
+
@Test
- public void testAssertEquals_Numbers() {
- testWorks("assertEquals(1, 1)", "1 == 1");
- testWorks("assertEquals(1.0, 1)", "1.0 == 1");
- testWorks("assertEquals(1.0, 1.0)", "1.0 == 1.0");
- testThrowsAssertion("assertEquals(1, 2)", "1 == 2");
+ public void testAssertNotNull_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertNotNull(1)", "assertNotNull should succeed on a number");
+ testWorks(engine, "var foo = '1'; assertNotNull(foo)", "assertNotNull should succeed on a non-null variable");
+ testThrowsAssertion(engine, "assertNotNull(foo)", "assertNotNull should fail on an undefined variable");
+ testThrowsAssertion(engine, "var foo = null; assertNotNull(foo);",
+ "assertNotNull should fail on a null variable");
+ testThrowsAssertion(engine, "assertNotNull(null)", "assertNotNull should fail on a null literal");
}
-
+
@Test
- public void testAssertEquals_Arrays() {
- testWorks("assertEquals(['a', 'b'], ['a', 'b'])", "native array comparison");
- testThrowsAssertion("assertEquals(['a', 'b'], ['c', 'd'])", "native array comparison with difference");
+ public void testAssertNotNull_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertNotNull(1)", "assertNotNull should succeed on a number");
+ testWorks(engine, "foo = '1'\n" + "assertNotNull(foo)", "assertNotNull should succeed on a non-null variable");
+ testThrowsAssertion(engine, "assertNotNull(foo)", "assertNotNull should fail on an undefined variable");
+ testThrowsAssertion(engine, "foo = None\n" + "assertNotNull(foo);",
+ "assertNotNull should fail on a null variable");
+ testThrowsAssertion(engine, "assertNotNull(None)", "assertNotNull should fail on a null literal");
}
@Test
- public void testAssertEquals_Collections() {
- testWorks("a = new java.util.ArrayList; " + "b = new java.util.ArrayList; " + "a.add('a'); " + "b.add('a'); "
- + "assertEquals(a, b)", "ArrayList comparison");
- testThrowsAssertion("a = new java.util.ArrayList; " + "b = new java.util.ArrayList; " + "a.add('a'); "
+ public void testAssertEquals_Numbers_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertEquals(1, 1)", "1 == 1");
+ testWorks(engine, "assertEquals(1.0, 1)", "1.0 == 1");
+ testWorks(engine, "assertEquals(1.0, 1.0)", "1.0 == 1.0");
+ testThrowsAssertion(engine, "assertEquals(1, 2)", "1 == 2");
+ }
+
+ @Test
+ public void testAssertEquals_Numbers_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertEquals(1, 1)", "1 == 1");
+ //Python distinguishes between ints and floats, so this
+ //won't work (even though "1.0 == 1" returns true in pure python)
+ //testWorks(engine, "assertEquals(1.0, 1)", "1.0 == 1");
+ testWorks(engine, "assertEquals(1.0, 1.0)", "1.0 == 1.0");
+ testThrowsAssertion(engine, "assertEquals(1, 2)", "1 == 2");
+ }
+
+ @Test
+ public void testAssertEquals_Arrays_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertEquals(['a', 'b'], ['a', 'b'])", "native array comparison");
+ testThrowsAssertion(engine, "assertEquals(['a', 'b'], ['c', 'd'])", "native array comparison with difference");
+ }
+
+ @Test
+ public void testAssertEquals_Arrays_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertEquals(['a', 'b'], ['a', 'b'])", "native array comparison");
+ testThrowsAssertion(engine, "assertEquals(['a', 'b'], ['c', 'd'])", "native array comparison with difference");
+ }
+
+ @Test
+ public void testAssertEquals_Collections_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "a = new java.util.ArrayList; " + "b = new java.util.ArrayList; " + "a.add('a'); "
+ + "b.add('a'); " + "assertEquals(a, b)", "ArrayList comparison");
+ testThrowsAssertion(engine, "a = new java.util.ArrayList; " + "b = new java.util.ArrayList; " + "a.add('a'); "
+ "b.add('b'); " + "assertEquals(a, b)", "ArrayList comparison with difference");
}
@Test
- public void testAssertEqualsNoOrder() {
- testWorks("assertEqualsNoOrder(['a', 'b'], ['b', 'a'])", "native array comparison");
+ public void testAssertEquals_Collections_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "import java.util as u\n" + "a = u.ArrayList()\n" + "b = u.ArrayList()\n" + "a.add('a')\n"
+ + "b.add('a')\n" + "assertEquals(a, b)", "ArrayList comparison");
+ testThrowsAssertion(engine, "import java.util as u\n" + "a = u.ArrayList()\n" + "b = u.ArrayList()\n" + "a.add('a')\n"
+ + "b.add('b')\n" + "assertEquals(a, b)", "ArrayList comparison with difference");
}
@Test
- public void testAssertSame() {
- testWorks("var a = '1'; assertSame(a, a)", "assertSame should succeed comparing one variable");
- testWorks("var a = '1'; b = a; assertSame(a, b)", "asserSame should succeed comparing 2 references of the same object");
- testWorks("assertSame(null, null);", "assertSame should succeed on null values");
- testThrowsAssertion("var a = '1'; b = '2'; assertSame(a, b)", "assertSame should fail comparing 2 different variables");
- testThrowsAssertion("var a = 1; assertSame(a, null)", "assertSame should fail comparing non-null variable with a null value");
+ public void testAssertEqualsNoOrder_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertEqualsNoOrder(['a', 'b'], ['b', 'a'])", "native array comparison");
}
-
+
+ @Test
+ public void testAssertEqualsNoOrder_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "assertEqualsNoOrder(['a', 'b'], ['b', 'a'])", "native array comparison");
+ }
+
@Test
- public void testAssertNotSame() {
- testThrowsAssertion("var a = '1'; assertNotSame(a, a)", "assertNotSame should fail comparing one variable");
- testThrowsAssertion("var a = '1'; b = a; assertNotSame(a, b)", "asserNotSame should fail comparing 2 references of the same object");
- testThrowsAssertion("assertNotSame(null, null);", "assertNotSame should fail on null values");
- testWorks("var a = '1'; b = '2'; assertNotSame(a, b)", "assertNotSame should succeed comparing 2 different variables");
- testWorks("var a = 1; assertNotSame(a, null)", "assertNotSame should succeed comparing non-null variable with a null value");
+ public void testAssertSame_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "var a = '1'; assertSame(a, a)", "assertSame should succeed comparing one variable");
+ testWorks(engine, "var a = '1'; b = a; assertSame(a, b)",
+ "asserSame should succeed comparing 2 references of the same object");
+ testWorks(engine, "assertSame(null, null);", "assertSame should succeed on null values");
+ testThrowsAssertion(engine, "var a = '1'; b = '2'; assertSame(a, b)",
+ "assertSame should fail comparing 2 different variables");
+ testThrowsAssertion(engine, "var a = 1; assertSame(a, null)",
+ "assertSame should fail comparing non-null variable with a null value");
}
-
- private void testWorks(String script, String message) {
+
+ @Test
+ public void testAssertSame_python() {
+ ScriptEngine engine = getScriptEngine();
+ testWorks(engine, "a = '1'\n" + "assertSame(a, a)", "assertSame should succeed comparing one variable");
+ testWorks(engine, "a = '1'\n" + "b = a\n" + "assertSame(a, b)",
+ "asserSame should succeed comparing 2 references of the same object");
+ testWorks(engine, "assertSame(None, None)", "assertSame should succeed on null values");
+ testThrowsAssertion(engine, "a = '1'\n" + "b = '2'\n" + "assertSame(a, b)",
+ "assertSame should fail comparing 2 different variables");
+ testThrowsAssertion(engine, "a = 1\n" + "assertSame(a, None)",
+ "assertSame should fail comparing non-null variable with a null value");
+ }
+
+ @Test
+ public void testAssertNotSame_javascript() {
+ ScriptEngine engine = getScriptEngine();
+ testThrowsAssertion(engine, "var a = '1'; assertNotSame(a, a)",
+ "assertNotSame should fail comparing one variable");
+ testThrowsAssertion(engine, "var a = '1'; b = a; assertNotSame(a, b)",
+ "asserNotSame should fail comparing 2 references of the same object");
+ testThrowsAssertion(engine, "assertNotSame(null, null);", "assertNotSame should fail on null values");
+ testWorks(engine, "var a = '1'; b = '2'; assertNotSame(a, b)",
+ "assertNotSame should succeed comparing 2 different variables");
+ testWorks(engine, "var a = 1; assertNotSame(a, null)",
+ "assertNotSame should succeed comparing non-null variable with a null value");
+ }
+
+ @Test
+ public void testAssertNotSame_python() {
+ ScriptEngine engine = getScriptEngine();
+ testThrowsAssertion(engine, "a = '1'\n" + "assertNotSame(a, a)",
+ "assertNotSame should fail comparing one variable");
+ testThrowsAssertion(engine, "a = '1'\n" + "b = a\n" + "assertNotSame(a, b)",
+ "asserNotSame should fail comparing 2 references of the same object");
+ testThrowsAssertion(engine, "assertNotSame(None, None)", "assertNotSame should fail on null values");
+ testWorks(engine, "a = '1'\n" + "b = '2'\n" + "assertNotSame(a, b)",
+ "assertNotSame should succeed comparing 2 different variables");
+ testWorks(engine, "a = 1\n" + "assertNotSame(a, None)",
+ "assertNotSame should succeed comparing non-null variable with a null value");
+ }
+
+ private void testWorks(ScriptEngine engine, String script, String message) {
try {
engine.eval(script);
} catch (ScriptException e) {
@@ -145,7 +274,7 @@ public class ScriptAssertTest {
}
}
- private void testThrowsAssertion(String script, String message) {
+ private void testThrowsAssertion(ScriptEngine engine, String script, String message) {
try {
engine.eval(script);
} catch (ScriptException e) {
commit e21a7eb14096c4b23b638ff9028eb04857710e64
Author: John Sanda <jsanda(a)Johns-MacBook-Pro.local>
Date: Wed Aug 22 15:22:43 2012 -0400
[BZ 802796] Do not report entire stack trace for display in UI
After some discussion it has been decied to *not* display the entire stack trace in the
resource creation error message. Instead we will display the new, detailed error message
along with the more brief exception message that reports the plugin component method in
which the time out occurred. The full stack trace can still however be obtained from the
agent logs with DEBUG logging enabled.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java
index b3c65bd..8d34e9f 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java
@@ -163,8 +163,15 @@ public class CreateResourceRunner implements Callable, Runnable {
status = CreateResourceStatus.TIMED_OUT;
errorMessage = "The time out has been exceeded; however, the deployment may have been successful. You " +
"may want to run a discovery scan to see if the deployment did complete successfully. Also consider " +
- "using a higher time out value for future deployments.\n\nRoot Cause:\n";
- errorMessage += ThrowableUtil.getStackAsString(e);
+ "using a higher time out value for future deployments.";
+
+ if (log.isDebugEnabled()) {
+ log.debug("Failed to create resource for " + report + ". " + errorMessage, e);
+ } else {
+ log.info("Failed to create resource for " + report + ". " + errorMessage, e);
+ }
+
+ errorMessage += "\n\nRoot Cause:\n" + e.getMessage();
} catch (Throwable t) {
status = CreateResourceStatus.FAILURE;
errorMessage = ThrowableUtil.getStackAsString(t);
commit 5ffd6e1eb155bf0208690cce526fb18b832ba344
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue Aug 21 16:04:42 2012 -0400
Make drift def sync more efficient, and possibly avoid an NPE that was
seen intermittently.
- DriftServerServiceImpl.getDriftDefinitions() now only generates
Map entries for resources with drift definitions, avoiding unnecessary
list creation and subsequent processing.
- Added jdoc to that effect
- Changed private DriftSyncManager.syncConfigs() to syncDriftDefinitions
for clarity.
diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/drift/DriftServerService.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/drift/DriftServerService.java
index a6df831..1b2d048 100644
--- a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/drift/DriftServerService.java
+++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/drift/DriftServerService.java
@@ -121,6 +121,11 @@ public interface DriftServerService {
@Asynchronous
void repeatChangeSet(int resourceId, String driftDefName, int version);
+ /**
+ * @param resourceIds The resourceIds for which to fetch definitions.
+ * @return A Map from resourceId to its list of DriftDefinitions. Resources without DriftDefinitions are not included
+ * in the Map.
+ */
Map<Integer, List<DriftDefinition>> getDriftDefinitions(Set<Integer> resourceIds);
DriftSnapshot getCurrentSnapshot(int driftDefinitionId);
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java
index b24849b..5f4ec36 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java
@@ -111,11 +111,11 @@ public class DriftSyncManager {
synchronizer = synchronizerFactory.getRuntimeSynchronizer(driftMgr);
}
- syncConfigs(synchronizer, resourceIds);
+ syncDriftDefinitions(synchronizer, resourceIds);
syncContent(synchronizer);
}
- private void syncConfigs(DriftSynchronizer synchronizer, Set<Integer> resourceIds) {
+ private void syncDriftDefinitions(DriftSynchronizer synchronizer, Set<Integer> resourceIds) {
log.info("Starting server sync for drift definitions...");
long startTime = System.currentTimeMillis();
@@ -127,15 +127,15 @@ public class DriftSyncManager {
int totalAdded = 0;
for (Integer resourceId : driftDefs.keySet()) {
- Set<DriftDefinition> resourceConfigsOnServer = new TreeSet<DriftDefinition>(comparator);
- resourceConfigsOnServer.addAll(driftDefs.get(resourceId));
+ Set<DriftDefinition> driftDefinitionsOnServer = new TreeSet<DriftDefinition>(comparator);
+ driftDefinitionsOnServer.addAll(driftDefs.get(resourceId));
List<DriftDefinition> deletedDefs = synchronizer.getDeletedDefinitions(resourceId,
- resourceConfigsOnServer);
+ driftDefinitionsOnServer);
totalDeleted += deletedDefs.size();
synchronizer.purgeFromLocalInventory(resourceId, deletedDefs);
- List<DriftDefinition> addedDefs = synchronizer.getAddedDefinitions(resourceId, resourceConfigsOnServer);
+ List<DriftDefinition> addedDefs = synchronizer.getAddedDefinitions(resourceId, driftDefinitionsOnServer);
totalAdded += addedDefs.size();
synchronizer.addToLocalInventory(resourceId, addedDefs);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftServerServiceImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftServerServiceImpl.java
index b22caa7..b206b54 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftServerServiceImpl.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftServerServiceImpl.java
@@ -84,17 +84,19 @@ public class DriftServerServiceImpl implements DriftServerService {
Subject overlord = getSubjectManager().getOverlord();
PageList<DriftDefinition> definitions = getDriftManager().findDriftDefinitionsByCriteria(overlord, criteria);
- Map<Integer, List<DriftDefinition>> map = new HashMap<Integer, List<DriftDefinition>>();
- for (Integer resourceId : resourceIds) {
- map.put(resourceId, new ArrayList<DriftDefinition>());
- }
- for (DriftDefinition c : definitions) {
- List<DriftDefinition> list = map.get(c.getResource().getId());
- list.add(c);
- map.put(c.getResource().getId(), list);
+ Map<Integer, List<DriftDefinition>> result = new HashMap<Integer, List<DriftDefinition>>();
+
+ for (DriftDefinition driftDef : definitions) {
+ Integer resourceId = driftDef.getResource().getId();
+ List<DriftDefinition> list = result.get(resourceId);
+ if (null == list) {
+ list = new ArrayList<DriftDefinition>();
+ result.put(resourceId, list);
+ }
+ list.add(driftDef);
}
- return map;
+ return result;
}
@Override
commit 1b9503fa343a8ae8add7a65757a7e21a96186a5b
Author: John Sanda <jsanda(a)redhat.com>
Date: Tue Aug 21 14:03:14 2012 -0400
Delete any old copy of AS 7 zip file to force download
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index a640c0541..ecd2295 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -303,6 +303,7 @@
</condition>
<property name="as7.zipfile"
location="${java.io.tmpdir}/jboss-${as7.product}-${as7.version}.zip"/>
+ <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"/>
commit d5ddeaababea5b8ba7573d4dc752c1636ae52f65
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Aug 21 09:38:38 2012 -0700
Remove Opera browser support from GWT compile. Will speed up compile times from elimination of 7 language permutations.
diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index a4b08b0..82292eb 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -43,17 +43,15 @@
ie9: IE9 (although for smartgwt we fallback to IE8)
ie8: IE8
- gecko: FF1 (NOTE: Support for this was dropped in GWT 2.1.)
gecko1_8: FF2 and later
safari: Safari/Chrome
- opera: Opera
*NOTE*: Since we specify the meta "X-UA-Compatible: IE=IE8" HTTP header in CoreGUI.html, IE9 and later
will emulate IE8.
Multiple agents can be specified as a comma-delimited list, as demonstrated by the default
value below.
-->
- <gwt.userAgent>ie8,ie9,gecko1_8,safari,opera</gwt.userAgent>
+ <gwt.userAgent>ie8,ie9,gecko1_8,safari</gwt.userAgent>
<!-- Change this to "true" via the mvn command line or your ~/.m2/settings.xml to speed
up gwt compilation. -->
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index c5c4391..f797482 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -11,11 +11,6 @@
<inherits name='com.smartgwt.SmartGwt' />
<inherits name="com.smartgwt.tools.SmartGwtTools"/>
- <!-- TODO: Consider uncommenting this instead of enabling compression in Tomcat's server.xml once we upgrade to GWT
- 2.1 or later. -->
- <!-- precompress .html, .js, and .css files -->
- <!--<inherits name="com.google.gwt.precompress.Precompress"/>-->
-
<inherits name='ca.nanometrics.gflot.GFlot'/>
@@ -66,7 +61,6 @@
ie9: IE9 (new support for IE9 with GWT 2.3.0+)
gecko1_8: FF2 and later
safari: Safari/Chrome
- opera: Opera
*NOTE*: Since we specify the meta "X-UA-Compatible: IE=IE8" HTTP header in CoreGUI.html, IE9 and later
will emulate IE8 (although the gwt IE9 js libs will still get loaded).
commit 963a082f73dd9cc4656998029bac99317b648424
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Tue Aug 21 15:21:55 2012 +0200
[BZ 818083 - [IE 8.0] GUI components not aligned properly on monitoring tab] Added invisible form item on the right side
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java
index 8bad3dd..9b39faa 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java
@@ -24,10 +24,12 @@ import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
+import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.widgets.form.fields.ButtonItem;
import com.smartgwt.client.widgets.form.fields.CheckboxItem;
import com.smartgwt.client.widgets.form.fields.DateTimeItem;
import com.smartgwt.client.widgets.form.fields.SelectItem;
+import com.smartgwt.client.widgets.form.fields.SpacerItem;
import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
@@ -62,6 +64,7 @@ public abstract class AbstractMeasurementRangeEditor extends LocatableDynamicFor
private boolean displayEnableButton = false;
private boolean displayRangeItemGrouping = false;
protected CheckboxItem enableRangeItem;
+ private SpacerItem space;
private ButtonItem setButton;
public static String ENABLE_RANGE_ITEM = "ENABLE_RANGE_ITEM";
@@ -83,8 +86,9 @@ public abstract class AbstractMeasurementRangeEditor extends LocatableDynamicFor
public AbstractMeasurementRangeEditor(String locatorId) {
super(locatorId);
- setNumCols(12);
+ setNumCols(10);
setWrapItemTitles(false);
+ setAlign(Alignment.LEFT);
}
/**
@@ -106,7 +110,6 @@ public abstract class AbstractMeasurementRangeEditor extends LocatableDynamicFor
setGroupTitle("Filter by: Time");
}
enableRangeItem = new CheckboxItem(ENABLE_RANGE_ITEM, "");
- enableRangeItem.setStartRow(true);
enableRangeItem.setShowTitle(false);
enableRangeItem.setShowLabel(false);
enableRangeItem.addChangeHandler(new ChangeHandler() {
@@ -119,35 +122,24 @@ public abstract class AbstractMeasurementRangeEditor extends LocatableDynamicFor
//combobox of last items
simpleLastValuesItem = new SelectItem(SIMPLE_VALUE_ITEM, MSG.view_measureRange_last());
- simpleLastValuesItem.setStartRow(false);
- simpleLastValuesItem.setEndRow(false);
simpleLastValuesItem.setValueMap(lastValues);
- simpleLastValuesItem.setWidth("*");
- simpleLastValuesItem.setRedrawOnChange(true);
+ simpleLastValuesItem.setTitleAlign(Alignment.LEFT);
//combobox of units of time
simpleLastUnitsItem = new SelectItem(SIMPLE_UNIT_ITEM);
- simpleLastUnitsItem.setStartRow(false);
- simpleLastUnitsItem.setEndRow(false);
simpleLastUnitsItem.setValueMap(lastUnits);
simpleLastUnitsItem.setShowTitle(false);
- simpleLastUnitsItem.setWidth("*");
- simpleLastUnitsItem.setRedrawOnChange(true);
//time range start from
advancedStartItem = new DateTimeItem(ADVANCED_START_ITEM, MSG.view_measureRange_start());
- advancedStartItem.setStartRow(false);
- advancedStartItem.setEndRow(false);
+ advancedStartItem.setTitleAlign(Alignment.LEFT);
//time range end
advancedEndItem = new DateTimeItem(ADVANCED_END_ITEM, MSG.common_title_end());
- advancedEndItem.setStartRow(false);
- advancedEndItem.setEndRow(false);
setButton = new ButtonItem(SET_ITEM, MSG.common_button_set());
setButton.setStartRow(false);
setButton.setEndRow(false);
- setButton.setShowTitle(false);
setButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
@@ -167,30 +159,31 @@ public abstract class AbstractMeasurementRangeEditor extends LocatableDynamicFor
advancedSimpleButton = new ButtonItem(ADVANCED_BUTTON_ITEM, MSG.common_button_advanced());
advancedSimpleButton.setStartRow(false);
advancedSimpleButton.setEndRow(false);
- advancedSimpleButton.setShowTitle(false);
advancedSimpleButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent clickEvent) {
advanced = !advanced;
update();
}
});
+
+ space = new SpacerItem();
+ space.setWidth(300);
MetricRangePreferences metricRangePrefs = getMetricRangePreferences();
if (metricRangePrefs != null) {
advanced = (metricRangePrefs.explicitBeginEnd);
}
-
+
if (displaySetButton) {
setItems(simpleLastValuesItem, simpleLastUnitsItem, advancedStartItem, advancedEndItem, setButton,
- advancedSimpleButton);
+ advancedSimpleButton, space);
} else {//not displaying Set button
if (displayEnableButton) {
setItems(enableRangeItem, simpleLastValuesItem, simpleLastUnitsItem, advancedStartItem,
- advancedEndItem, advancedSimpleButton);
- setNumCols(9);//extend to encompass expanded
+ advancedEndItem, advancedSimpleButton, space);
} else {
setItems(simpleLastValuesItem, simpleLastUnitsItem, advancedStartItem, advancedEndItem,
- advancedSimpleButton);
+ advancedSimpleButton, space);
}
}
update();
commit 2f1ce1944b3307fa790225f91889fc642abfcc0e
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Aug 21 10:57:28 2012 +0200
[BZ 840662] - Python scripting is now bundled by default with RHQ.
It can be excluded by explicitely switching off the "bundle-additional-script-languages" profile.
E.g. mvn clean install -P '!bundle-additional-script-languages'
diff --git a/modules/enterprise/remoting/cli/pom.xml b/modules/enterprise/remoting/cli/pom.xml
index 3924ff0..e0e4243 100644
--- a/modules/enterprise/remoting/cli/pom.xml
+++ b/modules/enterprise/remoting/cli/pom.xml
@@ -34,6 +34,13 @@
</dependency>
<dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-scripting-javascript</artifactId>
+ <version>${project.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
<groupId>${project.groupId}</groupId>
<artifactId>rhq-core-domain</artifactId>
<version>${project.version}</version>
@@ -131,6 +138,7 @@
<property name="persistence-api.version" value="${persistence-api.version}" />
<property name="rhq.client.build.exclude.cli.jar" value="${rhq.client.build.exclude.cli.jar}" />
<property name="rhq.client.build.include.client.jar" value="${rhq.client.build.include.client.jar}" />
+ <property name="rhq.bundle-additional-script-languages" value="${rhq.bundle-additional-script-languages}"/>
</ant>
</target>
</configuration>
@@ -220,6 +228,25 @@
<profiles>
+ <!-- NOTE: this profile HAS TO have the same activation policy as the profile with the same name in the root pom.xml of RHQ -->
+ <profile>
+ <id>bundle-additional-script-languages</id>
+ <activation>
+ <property>
+ <name>java.home</name>
+ </property>
+ </activation>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-scripting-python</artifactId>
+ <version>${project.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+
<!-- Unlike most of RHQ, this module requires JDK6, so replace the Java 5 bootclasspath that was added to the compiler args by the root POM with a bootclasspath based on the java.home sysprop (which should be Java 6 or later if the enforcer plugin did its job). -->
<profile>
<id>check-java-api</id>
diff --git a/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml b/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
index 808bd82..715bd9b 100644
--- a/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
+++ b/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
@@ -70,6 +70,15 @@
<copy file="${settings.localRepository}/org/rhq/rhq-scripting-api/${project.version}/rhq-scripting-api-${project.version}.jar" tofile="${lib.home}/rhq-scripting-api-${project.version}.jar" verbose="true" />
<copy file="${settings.localRepository}/org/rhq/rhq-scripting-javascript/${project.version}/rhq-scripting-javascript-${project.version}.jar" tofile="${lib.home}/rhq-scripting-javascript-${project.version}.jar" verbose="true" />
+
+ <echo>*** Including additional script languages: ${rhq.bundle-additional-script-languages}</echo>
+ <!-- Copy all the additional script language support jars if we are told to do so -->
+ <copy todir="${lib.home}" verbose="true">
+ <fileset dir="${settings.localRepository}/org/rhq">
+ <include if="${rhq.bundle-additional-script-languages}" name="**/rhq-scripting-python-${project.version}.jar"/>
+ </fileset>
+ <mapper type="flatten" />
+ </copy>
</target>
<target name="prepare-samples-dir">
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index 38ead44..adbe85a 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -22,6 +22,8 @@
<groupId>org.mozilla</groupId>
<artifactId>rhino</artifactId>
<version>1.7R4</version>
+ <!-- we actually repackage Rhino inside our jar -->
+ <scope>provided</scope>
</dependency>
</dependencies>
diff --git a/modules/enterprise/scripting/pom.xml b/modules/enterprise/scripting/pom.xml
index c786cdc..f439f11 100644
--- a/modules/enterprise/scripting/pom.xml
+++ b/modules/enterprise/scripting/pom.xml
@@ -17,11 +17,12 @@
</modules>
<profiles>
+ <!-- NOTE: this profile HAS TO have the same activation policy as the profile with the same name in the root pom.xml of RHQ -->
<profile>
- <id>experimental</id>
+ <id>bundle-additional-script-languages</id>
<activation>
<property>
- <name>experimental-script-languages</name>
+ <name>java.home</name>
</property>
</activation>
diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
index 39d3895..4b34699 100644
--- a/modules/enterprise/scripting/python/pom.xml
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -21,6 +21,8 @@
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.5.2</version>
+ <!-- we actually repackage jython inside our jar -->
+ <scope>provided</scope>
</dependency>
</dependencies>
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index 10b613e..0bed079 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -447,6 +447,26 @@
<profiles>
+ <!-- NOTE: this profile HAS TO have the same activation policy as the profile with the same name in the root pom.xml of RHQ -->
+ <profile>
+ <id>bundle-additional-script-languages</id>
+ <activation>
+ <property>
+ <!-- we want this always active but activeByDefault doesn't work -->
+ <!-- see http://maven.apache.org/guides/introduction/introduction-to-profiles.html -->
+ <name>java.home</name>
+ </property>
+ </activation>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-scripting-python</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </profile>
+
<profile>
<id>bundle-plugins</id>
<activation>
diff --git a/pom.xml b/pom.xml
index 36b9c62..f6bd80d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1171,6 +1171,25 @@
<profiles>
+ <!-- NOTE: This profile is extended upon in several other submodules.
+ If you need to change its activation policy, make sure to do that in
+ *ALL* the modules that define this profile. -->
+ <profile>
+ <id>bundle-additional-script-languages</id>
+ <activation>
+ <property>
+ <!-- we want this always active but activeByDefault doesn't work -->
+ <!-- see http://maven.apache.org/guides/introduction/introduction-to-profiles.html -->
+ <name>java.home</name>
+ </property>
+ </activation>
+
+ <!-- Can be used to pass a flag down to deployment composing ANT scripts and somesuch -->
+ <properties>
+ <rhq.bundle-additional-script-languages>true</rhq.bundle-additional-script-languages>
+ </properties>
+ </profile>
+
<profile>
<id>ojdbc-driver</id>
<activation>
commit 851461ab89dac1da41b9c85ae1d87eac54de2ef3
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon Aug 20 14:42:06 2012 -0500
[BZ 830841] Added a descriptive error message for cases where content is not available for a resource. The user is asked to try again in a few minutes if content was deployed recently since the deploy and discovery process might still be running.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
index 0199c77..7361fe8 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
@@ -576,19 +576,25 @@ public class ResourceClientProxy {
InstalledPackage installedPackage = getBackingContent();
- if (fileName == null )
- fileName = installedPackage.getPackageVersion().getFileName();
-
- File file = new File(fileName);
+ if (installedPackage != null) {
+ if (fileName == null) {
+ fileName = installedPackage.getPackageVersion().getFileName();
+ }
- byte[] data = remoteClient.getProxy(ContentManagerRemote.class).getPackageBytes(
- remoteClient.getSubject(), resourceClientProxy.resourceId, installedPackage.getId());
+ File file = new File(fileName);
- FileOutputStream fos = new FileOutputStream(file);
- try {
- fos.write(data);
- } finally {
- fos.close();
+ byte[] data = remoteClient.getProxy(ContentManagerRemote.class).getPackageBytes(
+ remoteClient.getSubject(), resourceClientProxy.resourceId, installedPackage.getId());
+
+ FileOutputStream fos = new FileOutputStream(file);
+ try {
+ fos.write(data);
+ } finally {
+ fos.close();
+ }
+ } else {
+ throw new RuntimeException(
+ "Content not available in the content repository. If you recently deployed content to this resource, then the content repository has not yet received the content or content information. The content for a resource is available only after the deployment and discovery process completes. Please try again in a few minutes.");
}
}
commit 414ccdf3fd964dc6d64abe511ec02f4e9170aa40
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Aug 20 14:59:13 2012 -0400
[Bug 849751 - RFE: protect resource tree from direct navigation to a resource with many siblings]
Apply the new ResourceManager.findResourcesByCriteriaBounded() method
to getResourceLineageAndSiblings() in order to similarly bound the initial
tree building fetch. Currently getResourceLineageAndSiblings() will use
the defaults applied to findResourcesByCriteriaBounded(), although we may
find that providing separate overrides will be useful.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
index 0fe906a..a016f8e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
@@ -113,6 +113,7 @@ import org.rhq.core.domain.resource.group.composite.AutoGroupComposite;
import org.rhq.core.domain.server.PersistenceUtility;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
import org.rhq.core.util.IntExtractor;
import org.rhq.core.util.collection.ArrayUtils;
import org.rhq.enterprise.server.RHQConstants;
@@ -796,14 +797,16 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage
// If the ancestor is not locked, include viewable children.
if (!ancestor.isLocked() || ancestor.getResource() == parent) {
- // Get all viewable committed children.
- PageList<Resource> children = findChildResourcesByCategoryAndInventoryStatus(subject,
- ancestor.getResource(), null, InventoryStatus.COMMITTED, PageControl.getUnlimitedInstance());
+ // Get viewable committed children, but bounded to ensure it's not an overwhelming return set
+ ResourceCriteria criteria = new ResourceCriteria();
+ criteria.addFilterParentResourceId(ancestor.getResource().getId());
+ criteria.addSortName(PageOrdering.ASC);
+ List<Resource> children = findResourcesByCriteriaBounded(subject, criteria, 0, 0);
// Remove any that are in the lineage to avoid repeated handling.
children.removeAll(rawResourceLineage);
for (Resource child : children) {
- // Ensure the parentResource field is fetched.
- //noinspection ConstantConditions
+ // Ensure the parentResource field is fetched. (do this here and not via criteria.fetchParentResource
+ // because that option would require inventory manager perm)
child.getParentResource().getId();
// The query only returned viewable children, so the composite should not be locked.
boolean isLocked = false;
commit 722b5c83eac64fd145863a154147f9bb0e1cf67a
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Aug 20 14:24:29 2012 -0400
trivial - fix some DriftManager logging
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java
index 0924288..8b54320 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java
@@ -479,7 +479,7 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
@Override
public void updateDriftDetection(int resourceId, DriftDefinition driftDefinition) {
- log.info("Recived request to update schedule for " + toString(resourceId, driftDefinition));
+ log.info("Received request to update schedule for " + toString(resourceId, driftDefinition));
DriftDetectionSchedule updatedSchedule = schedulesQueue.update(resourceId, driftDefinition);
if (updatedSchedule == null) {
@@ -696,7 +696,7 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
case pluginConfiguration: {
baseLocation = resource.getPluginConfiguration().getSimpleValue(baseDirValueName, null);
if (baseLocation == null) {
- throw new IllegalArgumentException("Cannot determine the bundle base deployment location - "
+ throw new IllegalArgumentException("Cannot determine the base directory - "
+ "there is no plugin configuration setting for [" + baseDirValueName + "]");
}
break;
@@ -704,7 +704,7 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
case resourceConfiguration: {
baseLocation = resource.getResourceConfiguration().getSimpleValue(baseDirValueName, null);
if (baseLocation == null) {
- throw new IllegalArgumentException("Cannot determine the bundle base deployment location - "
+ throw new IllegalArgumentException("Cannot determine the base directory - "
+ "there is no resource configuration setting for [" + baseDirValueName + "]");
}
break;
commit 155c66f5fa5ac816de6ce8693875cc746f80096d
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Aug 20 09:31:13 2012 -0700
[BZ 848529 - Creating a domain deployment spins and never uploads the WAR on IE8]. IE8 had issues registering the listener when the upload was complete. This was a regression caused by smartgwt3.0 upgrade.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/DynamicCallbackFormImplIE8.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/DynamicCallbackFormImplIE8.java
new file mode 100644
index 0000000..89c1615
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/DynamicCallbackFormImplIE8.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.rhq.enterprise.gui.coregui.client.components.upload;
+
+import com.google.gwt.dom.client.Element;
+
+/**
+ * Implementation class used by {@link com.google.gwt.user.client.ui.FormPanel}.
+ */
+public class DynamicCallbackFormImplIE8 extends DynamicCallbackFormImpl {
+
+ @Override
+ public native void hookEvents(Element iframe,
+ DynamicCallbackFormImplHost listener) /*-{
+ if (iframe) {
+ iframe.onreadystatechange = function() {
+ // If there is no __formAction yet, this is a spurious onreadystatechange
+ // generated when the iframe is first added to the DOM.
+ if (!iframe.__formAction)
+ return;
+
+ if (iframe.readyState == 'complete') {
+ // If the iframe's contentWindow has not navigated to the expected action
+ // url, then it must be an error, so we ignore it.
+ listener.@org.rhq.enterprise.gui.coregui.client.components.upload.DynamicCallbackFormImplHost::onFrameLoad()();
+ }
+ };
+ }
+ }-*/;
+
+ @Override
+ public native void unhookEvents(Element iframe) /*-{
+ if (iframe)
+ iframe.onreadystatechange = null;
+ }-*/;
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index 78db5af..c5c4391 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -39,6 +39,12 @@
<when-type-is class="org.rhq.enterprise.gui.coregui.client.components.upload.DynamicCallbackFormImpl"/>
</replace-with>
+ <!-- Special case for IE8 where upload onsubmit handlers need special registration code from other browsers -->
+ <replace-with class="org.rhq.enterprise.gui.coregui.client.components.upload.DynamicCallbackFormImplIE8">
+ <when-type-is class="org.rhq.enterprise.gui.coregui.client.components.upload.DynamicCallbackFormImpl"/>
+ <when-property-is name="user.agent" value="ie8"/>
+ </replace-with>
+
<generate-with class="org.rhq.enterprise.gui.coregui.user.rebind.rpc.TrackingServiceInterfaceProxyGenerator">
<when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService"/>
commit dc966bdbe0ef18915cba3a1cdd69c4167f5bd4c1
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri Aug 10 15:29:53 2012 -0700
Removed unused methods from ImageManager.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
index e50fe14..a15857e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
@@ -403,9 +403,6 @@ public class ImageManager {
return "subsystems/availability/availability_yellow_16.png";
}
- public static String getAvailabilityYellowLargeIcon() {
- return "subsystems/availability/availability_yellow_24.png";
- }
public static String getAvailBarImagePath(AvailabilityType availType) {
@@ -437,13 +434,6 @@ public class ImageManager {
return "subsystems/alert/Flag_blue_16.png";
}
- public static String getAlertLargeIcon() {
- return "subsystems/alert/Flag_blue_24.png";
- }
-
- public static String getAlertEditIcon() {
- return "subsystems/alert/Edit_Alert.png";
- }
public static String getMetricEditIcon() {
return "subsystems/monitor/Edit_Metric.png";
@@ -551,9 +541,6 @@ public class ImageManager {
return "subsystems/event/" + severity.name() + "_16.png";
}
- public static String getEventLargeIcon() {
- return "subsystems/event/Events_24.png";
- }
public static String getEventIcon() {
return "subsystems/event/Events_16.png";
@@ -563,45 +550,25 @@ public class ImageManager {
return "subsystems/monitor/Monitor_16.png";
}
- public static String getMonitorLargeIcon() {
- return "subsystems/monitor/Monitor_24.png";
- }
public static String getMonitorFailedIcon() {
return "subsystems/monitor/Monitor_failed_16.png";
}
- public static String getMonitorFailedLargeIcon() {
- return "subsystems/monitor/Monitor_failed_24.png";
- }
-
- public static String getOperationLargeIcon() {
- return "subsystems/control/Operation_24.png";
- }
-
public static String getOperationIcon() {
return "subsystems/control/Operation_16.png";
}
- public static String getActivityPackageLargeIcon() {
- return "subsystems/content/Package_24.png";
- }
public static String getActivityPackageIcon() {
return "subsystems/content/Package_16.png";
}
- public static String getBundleLargeIcon() {
- return "subsystems/content/Content_24.png";
- }
public static String getBundleIcon() {
return "subsystems/content/Content_16.png";
}
- public static String getConfigureLargeIcon() {
- return "subsystems/configure/Configure_24.png";
- }
public static String getConfigureIcon() {
return "subsystems/configure/Configure_16.png";
commit 8732f82745b97897372ce0d00a9b3ac0773fedea
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Aug 20 11:46:10 2012 -0400
Add unit test for new ResourceManager.findResourcesByCriteriaBounded().
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/LargeGroupCriteriaTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/LargeGroupCriteriaTest.java
index 93bb887..323cf5c 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/LargeGroupCriteriaTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/LargeGroupCriteriaTest.java
@@ -21,17 +21,21 @@ 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;
@@ -189,6 +193,57 @@ public class LargeGroupCriteriaTest extends LargeGroupTestBase {
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();
commit 8cd529eb7b04e785ded5c7a3fb6e633e6bc90cc4
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Aug 20 10:25:47 2012 -0400
Reformat only!
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java
index f0fe5b7..deac357 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java
@@ -113,102 +113,89 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase {
assert errors.size() == 0;
}
-
public void testResourceLineage() throws Exception {
- // given a resource id for the leaf resource in a resource hierarchy
- int leafResourceId = givenASampleResourceHierarchy();
+ // given a resource id for the leaf resource in a resource hierarchy
+ int leafResourceId = givenASampleResourceHierarchy();
- // when
- List<Resource> resourceLineage = resourceManager.getResourceLineage(leafResourceId);
+ // 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());
+
+ // 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--) {
+ 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, "",
+ 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 {
+ 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);
+ } 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 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();
@@ -257,7 +244,7 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase {
resourceManager.uninventoryResourceAsyncWork(superuser, deletedResourceId);
}
em.flush();
-
+
ResourceType type = em.find(ResourceType.class, resource.getResourceType().getId());
System.out.println("Removing " + type + "...");
em.remove(type);
commit 5d472dceb665ec2e4b8b8c528c59c8c8b354d40d
Author: John Sanda <jsanda(a)redhat.com>
Date: Mon Aug 20 11:39:51 2012 -0400
[BZ 848893] Only hide empty groups for availability queries/searches
This regression was introduced during the work for BZ 826493. While
testing the changes for this commit, I came across another, related
issue where an empty compatible group does not show up in the compatible
groups view. It does however show up in the mixed groups view. An empty
mixed group appears in the mixed group view. This issue is already
logged under BZ 708929.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
index e269475..a799311 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
@@ -50,7 +50,6 @@ import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
@@ -125,12 +124,16 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
processResponse(request.getRequestId(), response);
}
- private PageList<ResourceGroupComposite> filterEmptyMemberGroups(PageList<ResourceGroupComposite> result){
+ private PageList<ResourceGroupComposite> applyAvailabilitySearchFilter(
+ PageList<ResourceGroupComposite> result){
+ if (!isAvailabilitySearch(criteria)) {
+ return result;
+ }
PageList<ResourceGroupComposite> pageList = new PageList<ResourceGroupComposite>(result.getPageControl());
for (ResourceGroupComposite rgc : result) {
- if (rgc.getExplicitCount() > 0 ){
+ if (rgc.getExplicitCount() > 0) {
pageList.add(rgc);
}
}
@@ -139,7 +142,7 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
}
public void onSuccess(PageList<ResourceGroupComposite> result) {
- PageList<ResourceGroupComposite> filteredResult = filterEmptyMemberGroups(result);
+ PageList<ResourceGroupComposite> filteredResult = applyAvailabilitySearchFilter(result);
response.setData(buildRecords(filteredResult));
response.setTotalRows(filteredResult.getTotalSize()); // for paging to work we have to specify size of full result set
processResponse(request.getRequestId(), response);
@@ -147,6 +150,10 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
});
}
+ private boolean isAvailabilitySearch(ResourceGroupCriteria criteria) {
+ return criteria.getSearchExpression() != null && criteria.getSearchExpression().startsWith("availability");
+ }
+
@Override
protected ResourceGroupCriteria getFetchCriteria(final DSRequest request) {
ResourceGroupCriteria criteria = new ResourceGroupCriteria();
commit c62b143dd5f065b54caf6692d3c04929d8b4539f
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Fri Aug 17 14:30:35 2012 -0500
[BZ 841684] Add config option to the wrapper script.
diff --git a/modules/enterprise/agent/src/etc/rhq-agent-wrapper.sh b/modules/enterprise/agent/src/etc/rhq-agent-wrapper.sh
index 68d1856..f03c83a 100755
--- a/modules/enterprise/agent/src/etc/rhq-agent-wrapper.sh
+++ b/modules/enterprise/agent/src/etc/rhq-agent-wrapper.sh
@@ -246,6 +246,44 @@ case "$1" in
fi
;;
+'config')
+ prepare_pid_dir
+
+ if [ "$_RUNNING" = "1" ]; then
+ echo "Cannot run config - please stop the agent before running config"
+ echo $_STATUS
+ exit 0
+ fi
+
+ echo "Configure RHQ Agent..."
+
+ # Determine the command to execute when starting the agent
+ if [ -z "$RHQ_AGENT_START_COMMAND" ]; then
+ # Find out where the agent start script is located
+ _START_SCRIPT="${RHQ_AGENT_HOME}/bin/rhq-agent.sh"
+
+ if [ ! -f "$_START_SCRIPT" ]; then
+ echo "ERROR! Cannot find the RHQ Agent start script"
+ echo "Not found: $_START_SCRIPT"
+ exit 1
+ fi
+ debug_wrapper_msg "Start script found here: $_START_SCRIPT"
+
+ RHQ_AGENT_START_COMMAND="${_START_SCRIPT}"
+ fi
+
+ RHQ_AGENT_CMDLINE_OPTS="--cleanconfig --nostart --daemon --setup --advanced"
+ export RHQ_AGENT_CMDLINE_OPTS
+
+ # start the agent now!
+ if [ -n "$RHQ_AGENT_DEBUG" ] && [ "$RHQ_AGENT_DEBUG" != "false" ]; then
+ debug_wrapper_msg "Executing agent with command: ${RHQ_AGENT_START_COMMAND} ${RHQ_AGENT_CMDLINE_OPTS}"
+ fi
+
+ . $RHQ_AGENT_START_COMMAND
+
+ ;;
+
'stop')
prepare_pid_dir
@@ -326,7 +364,7 @@ case "$1" in
exit $?
;;
*)
- echo "Usage: $0 { start | stop | kill | restart | status }"
+ echo "Usage: $0 { start | stop | kill | restart | status | config }"
exit 1
;;
esac
commit 30c5e81759f5166873e49fd3486614c282203f47
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Fri Aug 17 19:20:48 2012 +0200
[BZ 834353] - Distinguish between BRMS 5.(1|2).0 and EWP 5.1.x by looking
for BRMS specific jars in the client directory.
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstallationInfo.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstallationInfo.java
index cae73f3..a45237d 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstallationInfo.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstallationInfo.java
@@ -23,6 +23,7 @@
package org.rhq.plugins.jbossas5.helper;
import java.io.File;
+import java.io.FilenameFilter;
import java.io.IOException;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
@@ -43,11 +44,11 @@ public class JBossInstallationInfo {
private static final String EPP_IMPL_VERSION_PREFIX = "JBoss-EPP";
private static final ComparableVersion VERSION_4_2 = new ComparableVersion("4.2");
- private final JBossProductType productType;
- private final String version;
- private final String defaultBindAddress;
- private final boolean isEap;
- private final String majorVersion;
+ private JBossProductType productType;
+ private String version;
+ private String defaultBindAddress;
+ private boolean isEap;
+ private String majorVersion;
public JBossInstallationInfo(File installationDir) throws IOException {
File binDir = new File(installationDir, "bin");
@@ -63,11 +64,47 @@ public class JBossInstallationInfo {
if (-1 == majorVersionIndex) {
throw new RuntimeException("Unexpected run.jar implementation version, can't parse: " + this.version);
}
+
+ fixProductTypeAndVersion(jarManifestAttributes, installationDir);
+
this.defaultBindAddress = getDefaultServerName(this.version);
this.isEap = determineEap(jarManifestAttributes);
this.majorVersion = version.substring(0, version.indexOf('.'));
}
+ /**
+ * Tries to make sense of the mess of JBoss product versioning.
+ *
+ * @param jarManifestAttributes
+ * @param installationDir
+ */
+ private void fixProductTypeAndVersion(Attributes jarManifestAttributes, File installationDir) {
+ //the main mess is with BRMS < 5.3.0 being advertised as EWP
+ if (productType == JBossProductType.EWP && version.startsWith("5.1")) {
+ //this still can be a BRMS server... We can check that by looking for drools jars
+ //in the client. Brittle you say? Yes, of course ;)
+ File client = new File(installationDir, "client");
+ if (client.exists() && client.isDirectory()) {
+ boolean containsBrmsJars = false;
+
+ for(String file : client.list()) {
+ if (file.endsWith("BRMS.jar")) {
+ containsBrmsJars = true;
+ break;
+ }
+ }
+
+ if (containsBrmsJars) {
+ productType = JBossProductType.BRMS;
+ if ("5.1.1".equals(version)) {
+ //BRMS 5.2.0 is based on EWP 5.1.1
+ version = "5.2.0";
+ }
+ }
+ }
+ }
+ }
+
public JBossProductType getProductType() {
return this.productType;
}
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java
index de5d837..312ea80 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java
@@ -54,7 +54,12 @@ public enum JBossProductType {
/**
* Determines the product type (AS, EAP, EWP, or SOA) based on the Implementation-Title MANIFEST.MF attribute.
- *
+ * <p>
+ * Note that this method is <b>NOT</b> always correct about the actual version of the product, because
+ * certain version of certain products don't advertise the correct product/version in the manifest.
+ * <p>
+ * Use {@link JBossInstallationInfo} for a more thorough detection of the type and version of a product.
+ *
* @param attributes the attributes from a manifest file (typically run.jar or jboss-j2ee.jar)
*
* @return the product type (AS, EAP, EWP, or SOA)
commit 32ad4e17b0f75fcccb84107e01956a519175670f
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Fri Aug 17 09:09:04 2012 -0500
[BZ 848800] Adding back old constructor signature for backwards compatibility reasons. Marked the old constructor as deprecated.
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java
index af18723..c5e85bb 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java
@@ -59,6 +59,19 @@ public class CreateChildResourceFacetDelegate implements CreateChildResourceFace
this.parentResourceContext = parentResourceContext;
}
+ /**
+ * @deprecated This constructor is deprecated because it does not handle properly the SHA256 computation for
+ * exploded content. If used, this constructor will lead to a calculation of the SHA256 for exploded content
+ * based on exploded files. This method of computation is not preferred due to changes in content archive
+ * matching. Replaced by (@link {@link #CreateChildResourceFacetDelegate(ProfileServiceComponent, ResourceContext)}
+ *
+ * @param component component
+ */
+ @Deprecated
+ public CreateChildResourceFacetDelegate(ProfileServiceComponent component) {
+ this.component = component;
+ }
+
public CreateResourceReport createResource(CreateResourceReport createResourceReport) {
// ProfileServiceFactory.refreshCurrentProfileView();
ResourceType resourceType = createResourceReport.getResourceType();
commit f0f52f180b65682996586b4a0438a1865cae8381
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Aug 16 16:06:57 2012 -0400
Adding perftest scenario support to help test bug 784571
diff --git a/modules/plugins/perftest/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/perftest/src/main/resources/META-INF/rhq-plugin.xml
index 72fae98..7a34f7e 100644
--- a/modules/plugins/perftest/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/perftest/src/main/resources/META-INF/rhq-plugin.xml
@@ -114,6 +114,14 @@
</resource-configuration>
</service>
+ <service name="service-gamma" class="PerfTestComponent" discovery="PerfTestDiscoveryComponent" description="Omega Service Gamma">
+ <plugin-configuration>
+ <c:simple-property name="gamma-property0"/>
+ </plugin-configuration>
+
+ <metric displayName="Gamma Metric 0" property="gamma-metric0" defaultOn="false"/>
+ </service>
+
</server>
<!-- try to make server-a and its children representative of "average" resources -->
diff --git a/modules/plugins/perftest/src/main/resources/configurable-7.xml b/modules/plugins/perftest/src/main/resources/configurable-7.xml
new file mode 100644
index 0000000..8c6051f
--- /dev/null
+++ b/modules/plugins/perftest/src/main/resources/configurable-7.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+
+<scenario xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:jboss.org:rhq-perftest">
+
+ <!--
+ Sets up "omega servers" that have three kinds of child services, "alpha", "beta" and "gamma".
+
+ This is currently for simple services, not all of the service featured are exposed, only numeric metrics.
+
+ Example:
+
+ -Drhq.perftest.scenario=configurable-7
+ -Drhq.perftest.server-omega-count=10
+ -Drhq.perftest.service-alpha-count=25
+ -Drhq.perftest.service-beta-count=2
+ -Drhq.perftest.service-gamma-count=10
+ -->
+
+ <resource type="server-omega">
+ <simpleResourceGenerator property="rhq.perftest.server-omega-count"/>
+ <simpleNumericMeasurementGenerator/>
+ </resource>
+
+ <resource type="service-alpha">
+ <simpleResourceGenerator property="rhq.perftest.service-alpha-count"/>
+ <simpleNumericMeasurementGenerator/>
+ </resource>
+
+ <resource type="service-beta">
+ <simpleResourceGenerator property="rhq.perftest.service-beta-count"/>
+ <simpleNumericMeasurementGenerator/>
+ </resource>
+
+ <resource type="service-gamma">
+ <simpleResourceGenerator property="rhq.perftest.service-gamma-count"/>
+ <simpleNumericMeasurementGenerator/>
+ </resource>
+
+</scenario>
commit 1ace95e35c4684847526df65f46e8ae4c559b92e
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu Aug 16 16:03:47 2012 -0400
BZ 844217 - do not "hardcode" the deployment directory at discovery time, but make it a trait so that changes the user is making will be relected.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
index 6eb19f6..573742e 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
@@ -18,7 +18,9 @@
*/
package org.rhq.modules.plugins.jbossas7;
+import java.io.File;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
@@ -27,6 +29,7 @@ import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.Property;
import org.rhq.core.domain.configuration.PropertyList;
import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.measurement.MeasurementDataTrait;
import org.rhq.core.domain.measurement.MeasurementReport;
import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
@@ -37,6 +40,7 @@ import org.rhq.core.pluginapi.operation.OperationResult;
import org.rhq.modules.plugins.jbossas7.json.Address;
import org.rhq.modules.plugins.jbossas7.json.Operation;
import org.rhq.modules.plugins.jbossas7.json.ReadAttribute;
+import org.rhq.modules.plugins.jbossas7.json.ReadResource;
import org.rhq.modules.plugins.jbossas7.json.Result;
/**
@@ -65,6 +69,8 @@ public class StandaloneASComponent<T extends ResourceComponent<?>> extends BaseS
collectConfigTrait(report, request);
} else if (requestName.equals("multicastAddress")) {
collectMulticastAddressTrait(report, request);
+ } else if (requestName.equals("deployDir")) {
+ resolveDeployDir(report,request);
} else {
leftovers.add(request); // handled below
}
@@ -73,6 +79,62 @@ public class StandaloneASComponent<T extends ResourceComponent<?>> extends BaseS
super.getValues(report, leftovers);
}
+ /**
+ * Try to determine the deployment directory (usually $as/standalone/deployments ).
+ * For JDG we return fake data, as JDG does not have such a directory.
+ * @param report Measurement report to tack the value on
+ * @param request Measurement request with the schedule id to use
+ */
+ private void resolveDeployDir(MeasurementReport report, MeasurementScheduleRequest request) {
+
+ if ("JDG".equals(pluginConfiguration.getSimpleValue("productType","AS7"))) {
+ log.debug("This is a JDG server, so there is no deployDir");
+ MeasurementDataTrait trait = new MeasurementDataTrait(request,"- not applicable to JDG -");
+ report.addData(trait);
+ return;
+ }
+
+ // So we have an AS7/EAP6
+ Address scanner = new Address("subsystem=deployment-scanner,scanner=default");
+ ReadResource op = new ReadResource(scanner);
+ Result res = getASConnection().execute(op);
+ if (res.isSuccess()) {
+ Map<String,String> scannerMap = (Map<String, String>) res.getResult();
+ String path = scannerMap.get("path");
+ String relativeTo = scannerMap.get("relative-to");
+ File basePath = resolveRelativePath(relativeTo);
+
+ // It is safe to use File.separator, as the agent we are running in, will also lay down the plugins
+ String deployDir = new File(basePath, path).getAbsolutePath();
+
+ MeasurementDataTrait trait = new MeasurementDataTrait(request,deployDir);
+ report.addData(trait);
+ }
+ else {
+ log.error("No default deployment scanner was found, returning no value");
+ }
+ }
+
+ private File resolveRelativePath(String relativeTo) {
+
+ Address addr = new Address("path",relativeTo);
+ ReadResource op = new ReadResource(addr);
+ Result res = getASConnection().execute(op);
+ if (res.isSuccess()) {
+ Map<String,String> pathMap = (Map<String, String>) res.getResult();
+ String path = pathMap.get("path");
+ String relativeToProp = pathMap.get("relative-to");
+ if (relativeToProp==null)
+ return new File(path);
+ else {
+ File basePath = resolveRelativePath(relativeToProp);
+ return new File(basePath, path);
+ }
+ }
+ log.warn("The requested path property " + relativeTo + " is not registered in the server, so not resolving it.");
+ return new File(relativeTo);
+ }
+
@Override
protected Address getServerAddress() {
return getAddress();
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java
index 9d93300..efa814d 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java
@@ -84,13 +84,6 @@ public class StandaloneASDiscovery extends BaseProcessDiscovery {
DiscoveredResourceDetails resourceDetails = super.buildResourceDetails(discoveryContext, process, commandLine);
Configuration pluginConfig = resourceDetails.getPluginConfiguration();
- // Set deployment directory, which only exists for standalone servers
- String baseDir = pluginConfig.getSimpleValue("baseDir");
- if (baseDir != null) {
- File deployDir = new File(baseDir, "deployments");
- pluginConfig.put(new PropertySimple("deployDir", deployDir.getPath()));
- }
-
return resourceDetails;
}
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 638f542..8143d04 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
@@ -1164,7 +1164,6 @@
<c:simple-property name="baseDir" type="file" description="Base directory for server content" displayName="Base Directory" readOnly="true" required="false"/>
<c:simple-property name="configDir" type="file" description="Base configuration directory" displayName="Configuration Directory" readOnly="true" required="false"/>
<c:simple-property name="logDir" type="file" description="the directory where log files will be written for this server" displayName="Log Directory" readOnly="true" required="false"/>
- <c:simple-property name="deployDir" type="file" description="Deploy directory for standalone servers" displayName="Deployment directory" readOnly="true" required="false"/>
<c:simple-property name="productType" type="string" readOnly="true" required="false" description="Server product type (e.g. AS or EAP)"/>
&startScriptPluginConfigGroup;
@@ -1224,6 +1223,8 @@
<metric property="config-file" dataType="trait" displayName="Server Config File" displayType="summary" defaultInterval="3600000"
description="The name of the server configuration file this server is using"/>
+ <metric property="deployDir" dataType="trait" displayName="Deploy Directory" defaultInterval="600000" defaultOn="true"
+ description="The deployment directory for bundles (usually 'standalone/deployments'"/>
<event name="logEntry" description="an entry in a log file"/>
@@ -1321,14 +1322,14 @@
name="Template-Deploy Files"
description="Monitor standalone deployment dir for drift. ">
<basedir>
- <value-context>pluginConfiguration</value-context>
+ <value-context>measurementTrait</value-context>
<value-name>deployDir</value-name>
</basedir>
</drift-definition>
<bundle-target>
<destination-base-dir name="Deploy Directory" description="The deployment directory for a standalone server">
- <value-context>pluginConfiguration</value-context>
+ <value-context>measurementTrait</value-context>
<value-name>deployDir</value-name>
</destination-base-dir>
</bundle-target>
commit 2e9bce71d9e26e1a7034650a56f6d3118b20ebaa
Author: John Sanda <jsanda(a)redhat.com>
Date: Thu Aug 16 13:18:09 2012 -0400
[BZ 826604] fix parsing of quoted named args
This commit addresses the parsing problems of using quoted strings with
named arguments.
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index c7f6bbf..e068272 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@ -431,6 +431,7 @@ public class ClientMain {
boolean keep_going = true;
boolean isScriptFileCommand = false;
+ boolean isNamedArgs = false;
// we don't want to parse numbers and we want ' to be a normal word
// character
@@ -471,12 +472,39 @@ public class ClientMain {
isScriptFileCommand = true;
}
args.add(strtok.sval);
+ if (strtok.sval.equals("--args-style=named")) {
+ isNamedArgs = true;
+ }
} else if (nextToken == '\"' || nextToken == '\'') {
args.add(strtok.sval);
} else if ((nextToken == java.io.StreamTokenizer.TT_EOF) || (nextToken == java.io.StreamTokenizer.TT_EOL)) {
keep_going = false;
}
}
+
+ if (isNamedArgs) {
+ List<String> newArgs = new ArrayList<String>();
+ int namedArgsIndex = args.indexOf("--args-style=named");
+
+ for (int i = 0; i <= namedArgsIndex; ++i) {
+ newArgs.add(args.get(i));
+ }
+
+ String namedArg = null;
+ for (int i = namedArgsIndex + 1; i < args.size(); ++i) {
+ if (namedArg == null && args.get(i).endsWith("=")) {
+ namedArg = args.get(i);
+ } else if (namedArg != null) {
+ newArgs.add(args.get(i - 1) + args.get(i));
+ namedArg = null;
+ } else {
+ newArgs.add(args.get(i));
+ }
+ }
+
+ return newArgs.toArray(new String[newArgs.size()]);
+ }
+
return args.toArray(new String[args.size()]);
}
commit 30a6818e7ae101dc8df7edc198c5ee9ac790683e
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Aug 16 12:39:22 2012 -0400
[Bug 784571 - Resource tree not complete when more than 200 children]
We decided not to allow an unlimited number of child resources be returned
when expanding a node in the tree. But there are major problems with
simply limiting the children to 200. This is what we do today, and the
results are unordered. Meaning you can lose any number of resources of
any types and it is not possible to know what you are missing. And we don't
indicate that the tree is incomplete. If we add ordering (alphabetical by
resource name) you still lose any number of resources, but always the same
ones. In this way it is much easier to realize that you are missing
child resources (and/or entire child types) because the resources returned
obviously stop as some lexigraphical point.
Still, we don't want to allow an unbounded fetch in the GUI. The solution
here is to move the unbounded fetch to the server side and to introduce
SLSB support to prune the results and return the pruned child set. In this
way we can limit the max child resources while returning a much more
reasonable resource set.
The way it works is as follows: There are two variable in use:
maxResources
Will not return more than this number of resources. If the original fetch
exceeds maxResources then maxResourcesByType will be enforced. If, after
trimming by type, maxResources is still exceeded, then the tail
resources (assuming a sorted set) will be removed to enforce the limit.
If <=0 the default (currently set to 1000) will be used.
maxResourcesByType
If maxResources is exceeded by the initial result set then members of each
type will be trimmed down to meet this limit.
If <=0 the default (currently set to 200) will be used.
The defaults may change after this check-in based on testing results. The
GUI will not set these values in the fetch, so the defaults will be applied.
The default values can be overriden (and applied to all fetches/sessions) by
setting the following system properties (in rhq-server.properties and restarting):
rhq.server.findResourcesByCriteriaBounded.maxResources
rhq.server.findResourcesByCriteriaBounded.maxResourcesByType
So, this allows us to:
- Avoid an unbounded fetch.
- Have any distribution of child resources of various types as long as the
maxResources limit is not exceeded.
- Apply an even and understandable pruning when necessary.
It does not yet allow us to indicate in the tree which resource types have
been pruned. This will be a future enhancement and tracked as
https://bugzilla.redhat.com/show_bug.cgi?id=848853.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java
index 59d96c6..1cdc64c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java
@@ -70,6 +70,9 @@ public interface ResourceGWTService extends RemoteService {
PageList<Resource> findResourcesByCriteria(ResourceCriteria criteria) throws RuntimeException;
+ List<Resource> findResourcesByCriteriaBounded(ResourceCriteria criteria, int maxResources, int maxResourcesByType)
+ throws RuntimeException;
+
PageList<ResourceComposite> findResourceCompositesByCriteria(ResourceCriteria criteria) throws RuntimeException;
List<ResourceError> findResourceErrors(int resourceId) throws RuntimeException;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
index 5c58a70..b6a5f5f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
@@ -44,8 +44,7 @@ import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceSubCategory;
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.domain.util.PageOrdering;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.ViewChangedException;
@@ -159,12 +158,16 @@ public class ResourceTreeDatasource extends DataSource {
} else {
Log.debug("ResourceTreeDatasource: Loading Resource [" + parentResourceId + "]...");
+ // This fetch limits the number of resources that can be returned to protect against fetching a massive
+ // number of children for a parent. Doing so may cause an unacceptably slow tree rendering, too much vertical
+ // scroll, or perhaps even hang the gui if it consumed too many resources. To see all children the
+ // user will need to visit the Inventory->Children view for the resource.
ResourceCriteria criteria = new ResourceCriteria();
criteria.addFilterParentResourceId(Integer.parseInt(parentResourceId));
- // we don't need sorting since we get everything and the tree nodes are already sorted
- criteria.setPageControl(PageControl.getUnlimitedInstance());
+ // we must sort the results to ensure that if cropped we at least show the same results each time
+ criteria.addSortName(PageOrdering.ASC);
- resourceService.findResourcesByCriteria(criteria, new AsyncCallback<PageList<Resource>>() {
+ resourceService.findResourcesByCriteriaBounded(criteria, -1, -1, new AsyncCallback<List<Resource>>() {
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_loadFailed_children(), caught);
response.setStatus(RPCResponse.STATUS_FAILURE);
@@ -173,7 +176,7 @@ public class ResourceTreeDatasource extends DataSource {
loadingLabel.hide();
}
- public void onSuccess(PageList<Resource> result) {
+ public void onSuccess(List<Resource> result) {
processIncomingData(result, response, requestId);
}
});
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java
index 17ccd78..4ee821b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java
@@ -145,6 +145,20 @@ public class ResourceGWTServiceImpl extends AbstractGWTServiceImpl implements Re
}
}
+ public List<Resource> findResourcesByCriteriaBounded(ResourceCriteria criteria, int maxResources,
+ int maxResourcesByType) throws RuntimeException {
+ try {
+ List<Resource> result = resourceManager.findResourcesByCriteriaBounded(getSessionSubject(), criteria,
+ maxResources, maxResourcesByType);
+
+ ObjectFilter.filterFieldsInCollection(result, importantFieldsSet);
+
+ return SerialUtility.prepare(result, "ResourceService.findResourcesByCriteriaBounded");
+ } catch (Throwable t) {
+ throw getExceptionToThrowToClient(t);
+ }
+ }
+
public PageList<ResourceComposite> findResourceCompositesByCriteria(ResourceCriteria criteria)
throws RuntimeException {
try {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
index dce2e23..0fe906a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
@@ -24,6 +24,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
@@ -142,6 +143,9 @@ import org.rhq.enterprise.server.util.QueryUtility;
public class ResourceManagerBean implements ResourceManagerLocal, ResourceManagerRemote {
private final Log log = LogFactory.getLog(ResourceManagerBean.class);
+ private final static String BOUNDED_MAX_RESOURCES = "1000";
+ private final static String BOUNDED_MAX_RESOURCES_BY_TYPE = "200";
+
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
private EntityManager entityManager;
@@ -2472,6 +2476,70 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage
return results;
}
+ @Override
+ public List<Resource> findResourcesByCriteriaBounded(Subject subject, ResourceCriteria criteria, int maxResources,
+ int maxResourcesByType) {
+
+ // find all of the requested resources but don't return them until they meet our bounded return requirements
+ // maintain any requested sorting
+ criteria.clearPaging();
+
+ // perform the requested criteria query
+ PageList<Resource> results = findResourcesByCriteria(subject, criteria);
+
+ // If not specified use the default maxResources
+ if (maxResources <= 0) {
+ try {
+ maxResources = Integer.parseInt(System.getProperty(
+ "rhq.server.findResourcesByCriteriaBounded.maxResources", BOUNDED_MAX_RESOURCES));
+ } catch (NumberFormatException e) {
+ }
+ if (maxResources <= 0) {
+ maxResources = Integer.parseInt(BOUNDED_MAX_RESOURCES);
+ }
+ }
+
+ if (results.getTotalSize() <= maxResources) {
+ return results;
+ }
+
+ // If not specified use the default maxResourcesByType
+ if (maxResourcesByType <= 0) {
+ try {
+ maxResourcesByType = Integer.parseInt(System.getProperty(
+ "rhq.server.findResourcesByCriteriaBounded.maxResourcesByType", BOUNDED_MAX_RESOURCES_BY_TYPE));
+ } catch (NumberFormatException e) {
+ }
+ if (maxResourcesByType <= 0) {
+ maxResourcesByType = Integer.parseInt(BOUNDED_MAX_RESOURCES_BY_TYPE);
+ }
+ }
+
+ // We need to trim the returned resources, enforce maxResourcesByType
+ Map<Integer, Integer> typeCounts = new HashMap<Integer, Integer>();
+
+ for (Iterator<Resource> i = results.iterator(); i.hasNext();) {
+ Resource r = i.next();
+ Integer typeId = r.getResourceType().getId();
+ Integer count = typeCounts.get(typeId);
+ if (null == count) {
+ count = 0;
+ }
+ typeCounts.put(typeId, ++count);
+ if (count > maxResourcesByType) {
+ i.remove();
+ }
+ }
+
+ // If after we've trimmed all types the results are still more than maxSize then we need to just chop
+ // keeping the most important (presumably the beginning of the list, if it's sorted)
+ while (maxResources < results.size()) {
+ results.remove(maxResources);
+ }
+
+ return results;
+ }
+
public Resource getPlaformOfResource(Subject subject, int resourceId) {
Resource resource = null;
Resource parent = null;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java
index fc075be..f555116 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java
@@ -446,6 +446,24 @@ public interface ResourceManagerLocal {
*/
public void updateAncestry(Subject subject, int resourceId);
+ /**
+ * This method exists to support the GUI resource tree, by not returning an unlimited number of resources
+ * but instead bounding the returned size. Note, this routine does not offer paging and any PageControl set in
+ * the Criteria is ignored. This is for use when paging is not required or possible, such as in a tree.
+ *
+ * @param subject
+ * @param criteria
+ * @param maxResources Will not return more than this number of resources. If the original fetch exceeds maxResources
+ * then maxResourcesByType will be enforced. If, after trimming by type, maxResources is still exceeded, then the least
+ * significant resources (the tail, assuming a sorted set) will be removed to enforce the limit. If <=0 the default
+ * will be used.
+ * @param maxResourcesByType If maxResources is exceeded by the initial result set then members of each type will be
+ * trimmed down to meet this limit. If <=0 the default will be used.
+ * @return The resulting resources, trimmed if necessary to meet the specify sizing bounds.
+ */
+ List<Resource> findResourcesByCriteriaBounded(Subject subject, ResourceCriteria criteria, int maxResources,
+ int maxResourcesByType);
+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// The following are shared with the Remote Interface
commit 10ad78d37ed54185afee537929c7411f0f40b694
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Thu Aug 16 11:03:47 2012 -0500
[BZ 824818] Removing required from keepalive-time because the validation rules on AS7 are too complex and not consistent with the resource definition.
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 a1eb285..638f542 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
@@ -2516,16 +2516,15 @@
</plugin-configuration>
<metric property="current-thread-count" description="The current number of threads in the pool."/>
- <metric property="keepalive-time:time" description="The time"/>
<metric property="largest-thread-count" description="The largest number of threads that have ever simultaneously been in the pool."/>
<metric property="rejected-count" description="The number of tasks that have been passed to the handoff-executor (if one is specified) or discarded."/>
<resource-configuration>
<c:simple-property name="allow-core-timeout" required="false" type="boolean" readOnly="true" defaultValue="false" displayName="Allow Core Timeout" description="Whether core threads may time out. The default value is false."/>
<c:simple-property name="core-threads:expr" required="false" type="integer" readOnly="true" displayName="Core Threads" description="The core thread pool size which is smaller than the maximum pool size. If undefined, the core thread pool size is the same as the maximum thread pool size."/>
- <c:map-property name="keepalive-time" required="true" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="true" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="true" description="The time unit"/>
+ <c:map-property name="keepalive-time" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
+ <c:simple-property name="time" type="long" readOnly="true" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="true" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="integer" readOnly="true" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" displayName="Name" description="The name of the thread pool."/>
@@ -2544,16 +2543,15 @@
</plugin-configuration>
<metric property="current-thread-count" description="The current number of threads in the pool."/>
- <metric property="keepalive-time:time" description="The time"/>
<metric property="largest-thread-count" description="The largest number of threads that have ever simultaneously been in the pool."/>
<metric property="rejected-count" description="The number of tasks that have been passed to the handoff-executor (if one is specified) or discarded."/>
<resource-configuration>
<c:simple-property name="allow-core-timeout" required="false" type="boolean" readOnly="true" defaultValue="false" displayName="Allow Core Timeout" description="Whether core threads may time out. The default value is false."/>
<c:simple-property name="core-threads:expr" required="false" type="integer" readOnly="true" displayName="Core Threads" description="The core thread pool size which is smaller than the maximum pool size. If undefined, the core thread pool size is the same as the maximum thread pool size."/>
- <c:map-property name="keepalive-time" required="true" readOnly="true" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="true" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="true" description="The time unit"/>
+ <c:map-property name="keepalive-time" readOnly="true" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
+ <c:simple-property name="time" type="long" readOnly="true" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="true" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="integer" readOnly="true" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" displayName="Name" description="The name of the thread pool."/>
@@ -2856,15 +2854,14 @@
<metric property="active-count" description="The approximate number of threads that are actively executing tasks."/>
<metric property="completed-task-count" description="The approximate total number of tasks that have completed execution."/>
<metric property="current-thread-count" description="The current number of threads in the pool."/>
- <metric property="keepalive-time:time" description="The time"/>
<metric property="largest-thread-count" description="The largest number of threads that have ever simultaneously been in the pool."/>
<metric property="rejected-count" description="The number of tasks that have been rejected."/>
<metric property="task-count" description="The approximate total number of tasks that have ever been scheduled for execution."/>
<resource-configuration>
<c:map-property name="keepalive-time" readOnly="true" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="true" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="true" description="The time unit"/>
+ <c:simple-property name="time" type="long" readOnly="true" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="true" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" displayName="Max Threads" required="false" type="string" readOnly="true" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="The name of the thread pool."/>
@@ -3081,8 +3078,8 @@
<resource-configuration>
<c:map-property name="keepalive-time" readOnly="false" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" readOnly="false" type="long" description="The time"/>
- <c:simple-property name="unit" required="true" readOnly="false" type="string" description="The time unit"/>
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="string" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="The name of the thread pool."/>
@@ -5499,9 +5496,9 @@
<resource-configuration>
<c:simple-property name="allow-core-timeout" required="false" type="boolean" readOnly="false" defaultValue="false" displayName="Allow Core Timeout" description="Whether core threads may time out. The default value is false."/>
<c:simple-property name="core-threads:expr" required="false" type="integer" readOnly="false" displayName="Core Threads" description="The core thread pool size which is smaller than the maximum pool size. If undefined, the core thread pool size is the same as the maximum thread pool size."/>
- <c:map-property name="keepalive-time" required="true" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="false" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="false" description="The time unit"/>
+ <c:map-property name="keepalive-time" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="integer" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" displayName="Name" description="The name of the thread pool."/>
@@ -5523,9 +5520,9 @@
<resource-configuration>
<c:simple-property name="allow-core-timeout" required="false" type="boolean" readOnly="false" defaultValue="false" displayName="Allow Core Timeout" description="Whether core threads may time out. The default value is false."/>
<c:simple-property name="core-threads:expr" required="false" type="integer" readOnly="false" displayName="Core Threads" description="The core thread pool size which is smaller than the maximum pool size. If undefined, the core thread pool size is the same as the maximum thread pool size."/>
- <c:map-property name="keepalive-time" required="true" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="false" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="false" description="The time unit"/>
+ <c:map-property name="keepalive-time" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="integer" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" displayName="Name" description="The name of the thread pool."/>
@@ -5711,8 +5708,8 @@
<resource-configuration>
<c:map-property name="keepalive-time" readOnly="false" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="false" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="false" description="The time unit"/>
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="false" type="string" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="The name of the thread pool."/>
@@ -5927,8 +5924,8 @@
<resource-configuration>
<c:map-property name="keepalive-time" readOnly="false" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" readOnly="false" type="long" description="The time"/>
- <c:simple-property name="unit" required="true" readOnly="false" type="string" description="The time unit"/>
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="string" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="The name of the thread pool."/>
@@ -10269,16 +10266,15 @@
</plugin-configuration>
<metric property="current-thread-count" description="The current number of threads in the pool."/>
- <metric property="keepalive-time:time" description="The time"/>
<metric property="largest-thread-count" description="The largest number of threads that have ever simultaneously been in the pool."/>
<metric property="rejected-count" description="The number of tasks that have been passed to the handoff-executor (if one is specified) or discarded."/>
<resource-configuration>
<c:simple-property name="allow-core-timeout" required="false" type="boolean" readOnly="false" defaultValue="false" displayName="Allow Core Timeout" description="Whether core threads may time out. The default value is false."/>
<c:simple-property name="core-threads:expr" required="false" type="integer" readOnly="false" displayName="Core Threads" description="The core thread pool size which is smaller than the maximum pool size. If undefined, the core thread pool size is the same as the maximum thread pool size."/>
- <c:map-property name="keepalive-time" required="true" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="false" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="false" description="The time unit"/>
+ <c:map-property name="keepalive-time" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="integer" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" displayName="Name" description="The name of the thread pool."/>
@@ -10298,16 +10294,15 @@
</plugin-configuration>
<metric property="current-thread-count" description="The current number of threads in the pool."/>
- <metric property="keepalive-time:time" description="The time"/>
<metric property="largest-thread-count" description="The largest number of threads that have ever simultaneously been in the pool."/>
<metric property="rejected-count" description="The number of tasks that have been passed to the handoff-executor (if one is specified) or discarded."/>
<resource-configuration>
<c:simple-property name="allow-core-timeout" required="false" type="boolean" readOnly="false" defaultValue="false" displayName="Allow Core Timeout" description="Whether core threads may time out. The default value is false."/>
<c:simple-property name="core-threads:expr" required="false" type="integer" readOnly="false" displayName="Core Threads" description="The core thread pool size which is smaller than the maximum pool size. If undefined, the core thread pool size is the same as the maximum thread pool size."/>
- <c:map-property name="keepalive-time" required="true" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="false" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="false" description="The time unit"/>
+ <c:map-property name="keepalive-time" displayName="Keepalive Time" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="integer" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" displayName="Name" description="The name of the thread pool."/>
@@ -10863,8 +10858,8 @@
<resource-configuration>
<c:map-property name="keepalive-time" readOnly="false" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" readOnly="false" type="long" description="The time"/>
- <c:simple-property name="unit" required="true" readOnly="false" type="string" description="The time unit"/>
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="true" type="string" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="The name of the thread pool."/>
@@ -10942,8 +10937,8 @@
<resource-configuration>
<c:map-property name="keepalive-time" readOnly="false" description="Used to specify the amount of time that pool threads should be kept running when idle; if not specified, threads will run until the executor is shut down.">
- <c:simple-property name="time" required="true" type="long" readOnly="false" description="The time"/>
- <c:simple-property name="unit" required="true" type="string" readOnly="false" description="The time unit"/>
+ <c:simple-property name="time" type="long" readOnly="false" description="The time"/>
+ <c:simple-property name="unit" type="string" readOnly="false" description="The time unit"/>
</c:map-property>
<c:simple-property name="max-threads:expr" required="false" type="string" readOnly="false" displayName="Max Threads" description="The maximum thread pool size."/>
<c:simple-property name="name" required="false" type="string" readOnly="true" description="The name of the thread pool."/>
commit 8000e712dd98fd8ee8e1ff52940e15b07f11e782
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Wed Aug 15 20:13:14 2012 +0200
[BZ 845277] - quick fix: removed the doctype declaration and removed overcasting to int
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
index 3da090a..8445a46 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
@@ -312,7 +312,7 @@ public abstract class AbstractMetricGraphView extends LocatableVLayout {
for (MeasurementDataNumericHighLowComposite d : data) {
if (!Double.isNaN(d.getValue())) {
- handler.add(new DataPoint(d.getTimestamp(), (int) d.getValue()));
+ handler.add(new DataPoint(d.getTimestamp(), d.getValue()));
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
index a0a4d2a..6a78aab 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
+++ b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
@@ -1,4 +1,3 @@
-<!DOCTYPE html>
<html>
<head>
<!-- this forces us to emulate IE8 "quirks" mode regardless of IE browser version. It:
commit 5d243b30f5315f18329f6f4fa9db22ae47eb32bd
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Wed Aug 15 19:42:24 2012 +0200
[BZ 845277 - JBoss ON dashboard shows messed metric graph on IE 8/9] Version of gflot upgraded to 2.4.2 (it contains the excanvas library for IE8/9 support of HTML canvas el.), version of sparkline upgraded to 2.0, version of jquery upgraded to 1.7.2
diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index e3aca30..a4b08b0 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -143,9 +143,10 @@
to provide jquery explcitly for jquery.sparkline support. See CoreGUI.gwt.xml for the jquery.sparkline
declaration and coregui/webapp/js for the lib inclusion.) -->
<dependency>
- <groupId>ca.nanometrics</groupId>
+ <groupId>com.googlecode.gflot</groupId>
<artifactId>gflot</artifactId>
- <version>1.0.0</version>
+ <version>2.4.2</version>
+ <scope>provided</scope>
</dependency>
@@ -283,8 +284,8 @@
<configuration>
<noServer>true</noServer>
<inplace>false</inplace>
- <!-- <logLevel>INFO' -bindAddress 0.0.0.0 -logLevel 'INFO</logLevel> -->
- <logLevel>INFO</logLevel>
+<!-- <logLevel>INFO' -bindAddress 0.0.0.0 -logLevel 'INFO</logLevel> -->
+ <logLevel>INFO</logLevel>
<runTarget>${coreGuiRunTarget}</runTarget>
<extraJvmArgs>${gwt-plugin.extraJvmArgs}</extraJvmArgs>
<localWorkers>${gwt-plugin.localWorkers}</localWorkers>
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
index 224125d..3da090a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
@@ -23,14 +23,15 @@ import java.util.List;
import ca.nanometrics.gflot.client.Axis;
import ca.nanometrics.gflot.client.DataPoint;
-import ca.nanometrics.gflot.client.PlotItem;
import ca.nanometrics.gflot.client.PlotModel;
-import ca.nanometrics.gflot.client.PlotPosition;
import ca.nanometrics.gflot.client.SeriesHandler;
import ca.nanometrics.gflot.client.SimplePlot;
import ca.nanometrics.gflot.client.event.PlotHoverListener;
+import ca.nanometrics.gflot.client.event.PlotItem;
+import ca.nanometrics.gflot.client.event.PlotPosition;
import ca.nanometrics.gflot.client.jsni.Plot;
import ca.nanometrics.gflot.client.options.AxisOptions;
+import ca.nanometrics.gflot.client.options.GlobalSeriesOptions;
import ca.nanometrics.gflot.client.options.GridOptions;
import ca.nanometrics.gflot.client.options.LineSeriesOptions;
import ca.nanometrics.gflot.client.options.PlotOptions;
@@ -201,9 +202,11 @@ public abstract class AbstractMetricGraphView extends LocatableVLayout {
PlotModel model = new PlotModel();
PlotOptions plotOptions = new PlotOptions();
- plotOptions.setDefaultLineSeriesOptions(new LineSeriesOptions().setLineWidth(1).setShow(true));
- plotOptions.setDefaultPointsOptions(new PointsSeriesOptions().setRadius(2).setShow(true));
- plotOptions.setDefaultShadowSize(0);
+ GlobalSeriesOptions globalSeriesOptions = new GlobalSeriesOptions();
+ globalSeriesOptions.setLineSeriesOptions(new LineSeriesOptions().setLineWidth(1).setShow(true));
+ globalSeriesOptions.setPointsOptions(new PointsSeriesOptions().setRadius(2).setShow(true));
+ globalSeriesOptions.setShadowSize(0);
+ plotOptions.setGlobalSeriesOptions(globalSeriesOptions);
// You need make the grid hoverable <<<<<<<<<
plotOptions
@@ -308,10 +311,12 @@ public abstract class AbstractMetricGraphView extends LocatableVLayout {
SeriesHandler handler = model.addSeries(definition.getDisplayName(), "#007f00");
for (MeasurementDataNumericHighLowComposite d : data) {
- handler.add(new DataPoint(d.getTimestamp(), d.getValue()));
+ if (!Double.isNaN(d.getValue())) {
+ handler.add(new DataPoint(d.getTimestamp(), (int) d.getValue()));
+ }
}
- plotOptions.setYAxisOptions(new AxisOptions().setTicks(5).setLabelWidth(70)
+ plotOptions.addYAxisOptions(new AxisOptions().setTicks(5).setLabelWidth(70)
.setTickFormatter(new TickFormatter() {
public String formatTickValue(double v, Axis axis) {
return MeasurementConverterClient.format(v, definition.getUnits(), true);
@@ -323,7 +328,7 @@ public abstract class AbstractMetricGraphView extends LocatableVLayout {
int xTicks = getDefaultWidth() / 140;
- plotOptions.setXAxisOptions(new AxisOptions().setTicks(xTicks).setMinimum(min).setMaximum(max)
+ plotOptions.addXAxisOptions(new AxisOptions().setTicks(xTicks).setMinimum(min).setMaximum(max)
.setTickFormatter(new TickFormatter() {
public String formatTickValue(double tickValue, Axis axis) {
com.google.gwt.i18n.client.DateTimeFormat dateFormat = DateTimeFormat
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java
index edc1611..330eaf0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java
@@ -24,15 +24,16 @@ import java.util.Set;
import ca.nanometrics.gflot.client.Axis;
import ca.nanometrics.gflot.client.DataPoint;
-import ca.nanometrics.gflot.client.PlotItem;
import ca.nanometrics.gflot.client.PlotModel;
import ca.nanometrics.gflot.client.PlotModelStrategy;
-import ca.nanometrics.gflot.client.PlotPosition;
import ca.nanometrics.gflot.client.SeriesHandler;
import ca.nanometrics.gflot.client.SimplePlot;
import ca.nanometrics.gflot.client.event.PlotHoverListener;
+import ca.nanometrics.gflot.client.event.PlotItem;
+import ca.nanometrics.gflot.client.event.PlotPosition;
import ca.nanometrics.gflot.client.jsni.Plot;
import ca.nanometrics.gflot.client.options.AxisOptions;
+import ca.nanometrics.gflot.client.options.GlobalSeriesOptions;
import ca.nanometrics.gflot.client.options.GridOptions;
import ca.nanometrics.gflot.client.options.LineSeriesOptions;
import ca.nanometrics.gflot.client.options.PlotOptions;
@@ -133,9 +134,11 @@ public class LiveGraphView extends LocatableVLayout {
PlotModel model = new PlotModel();
PlotOptions plotOptions = new PlotOptions();
- plotOptions.setDefaultLineSeriesOptions(new LineSeriesOptions().setLineWidth(1).setShow(true));
- plotOptions.setDefaultPointsOptions(new PointsSeriesOptions().setRadius(2).setShow(true));
- plotOptions.setDefaultShadowSize(0);
+ GlobalSeriesOptions globalSeriesOptions = new GlobalSeriesOptions();
+ globalSeriesOptions.setLineSeriesOptions(new LineSeriesOptions().setLineWidth(1).setShow(true));
+ globalSeriesOptions.setPointsOptions(new PointsSeriesOptions().setRadius(2).setShow(true));
+ globalSeriesOptions.setShadowSize(0);
+ plotOptions.setGlobalSeriesOptions(globalSeriesOptions);
// You need make the grid hoverable <<<<<<<<<
plotOptions
@@ -258,7 +261,7 @@ public class LiveGraphView extends LocatableVLayout {
dataLoader.scheduleRepeating(1000);
- plotOptions.setYAxisOptions(new AxisOptions().setLabelWidth(70).setTicks(5)
+ plotOptions.addYAxisOptions(new AxisOptions().setLabelWidth(70).setTicks(5)
.setTickFormatter(new TickFormatter() {
public String formatTickValue(double v, Axis axis) {
return MeasurementConverterClient.format(v, definition.getUnits(), true);
@@ -268,7 +271,7 @@ public class LiveGraphView extends LocatableVLayout {
min = System.currentTimeMillis();
max = System.currentTimeMillis() + (1000L * 60);
- plotOptions.setXAxisOptions(new AxisOptions().setTicks(8).setTickFormatter(new TickFormatter() {
+ plotOptions.addXAxisOptions(new AxisOptions().setTicks(8).setTickFormatter(new TickFormatter() {
public String formatTickValue(double tickValue, Axis axis) {
DateTimeFormat dateFormat = DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_MEDIUM);
return dateFormat.format(new Date((long) tickValue));
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index 614e6f7..78db5af 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -46,12 +46,10 @@
<!-- External javascript libraries -->
<!-- jquery.sparkline requires jquery. We don't explicitly provide jquery here because it is already
- embedded in the GFlot JAR (the charting lib used for GraphPortlet). Furthermore, GFlot 1.0.0 requires
- its older, embedded version of jquery (1.3.2). Fortunately, sparkline is compatible with this older version.
- We will need to provide jquery explicitly (like the commented version below) if we remove GFlot.
- <script src="/coregui/js/jquery-1.4.4.js"/>
+ embedded in the GFlot JAR (the charting lib used for GraphPortlet). Furthermore, GFlot 2.4.2 requires
+ the version of jquery (1.7.2).
-->
- <script src="/coregui/js/jquery.sparkline-1.6.js"/>
+ <script src="/coregui/js/jquery.sparkline-2.0.min.js"/>
<!--
Limit compilation to your preferred browser(s) to speed up compile time.
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
index 2c6e285..a0a4d2a 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
+++ b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<!-- this forces us to emulate IE8 "quirks" mode regardless of IE browser version. It:
@@ -21,7 +22,8 @@
document.write("<meta name='gwt:property' content='locale="+lang +"'>");
}
</script>
-
+ <script src="/coregui/js/jquery-1.7.2.min.js"/>
+
<title>RHQ</title>
<link rel="icon" type="image/png" href="/images/favicon.png" />
<link rel="apple-touch-icon" href="/images/favicon.png" />
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.7.2.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.7.2.min.js
new file mode 100644
index 0000000..16ad06c
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery-1.7.2.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.7.2 jquery.com | jquery.org/license */
+(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;
for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e
+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];
if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?
c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a
,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(
c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return th
is;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArra
y:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=a
rguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.a
ttachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(
q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:func
tion(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){v
ar d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b
)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.s
hift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progr
ess:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=ar
guments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.ge
tAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","
t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><
td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.
style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].dat
a)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return
b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a
!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(
){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.
each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.e
ach(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.val
Hooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!
==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:fu
nction(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a
,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.op
tSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(
+a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,gu
id:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p
.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArr
ay(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(ar
guments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);
return c.result}},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var
d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(
!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.cont
ains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this.
_just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!
="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"
**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):thi
s.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[]
,d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]
!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=
o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u
00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++)
{c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&
(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){re
turn a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toL
owerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,
j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f===
"$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compa
reDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.
ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagNam
e(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\
]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){va
r d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.co
ntains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,t
his)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNode
s)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|me
ta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a
))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&
this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f
+.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,"
"):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return
this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragm
ents[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e)
{var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]
&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+
.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch
(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,
f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=fun
ction(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement
("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.na
me,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String
,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once mem
ory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d
.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error
:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var
g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.
async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-Wit
h"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3)
,a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:functi
on(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidd
en");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue
===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.proto
type={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!=
=b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this
.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,l
eft:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position
==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFuncti
on(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(
d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-1.6.js b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-1.6.js
deleted file mode 100644
index d60cf18..0000000
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-1.6.js
+++ /dev/null
@@ -1,1271 +0,0 @@
-/**
-*
-* jquery.sparkline.js
-*
-* v1.6
-* (c) Splunk, Inc
-* Contact: Gareth Watts (gareth(a)splunk.com)
-* http://omnipotent.net/jquery.sparkline/
-*
-* Generates inline sparkline charts from data supplied either to the method
-* or inline in HTML
-*
-* Compatible with Internet Explorer 6.0+ and modern browsers equipped with the canvas tag
-* (Firefox 2.0+, Safari, Opera, etc)
-*
-* License: New BSD License
-*
-* Copyright (c) 2010, Splunk Inc.
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without modification,
-* are permitted provided that the following conditions are met:
-*
-* * Redistributions of source code must retain the above copyright notice,
-* this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above copyright notice,
-* this list of conditions and the following disclaimer in the documentation
-* and/or other materials provided with the distribution.
-* * Neither the name of Splunk Inc nor the names of its contributors may
-* be used to endorse or promote products derived from this software without
-* specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
-* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
-*
-* Usage:
-* $(selector).sparkline(values, options)
-*
-* If values is undefined or set to 'html' then the data values are read from the specified tag:
-* <p>Sparkline: <span class="sparkline">1,4,6,6,8,5,3,5</span></p>
-* $('.sparkline').sparkline();
-* There must be no spaces in the enclosed data set
-*
-* Otherwise values must be an array of numbers or null values
-* <p>Sparkline: <span id="sparkline1">This text replaced if the browser is compatible</span></p>
-* $('#sparkline1').sparkline([1,4,6,6,8,5,3,5])
-* $('#sparkline2').sparkline([1,4,6,null,null,5,3,5])
-*
-* Values can also be specified in an HTML comment, or as a values attribute:
-* <p>Sparkline: <span class="sparkline"><!--1,4,6,6,8,5,3,5 --></span></p>
-* <p>Sparkline: <span class="sparkline" values="1,4,6,6,8,5,3,5"></span></p>
-* $('.sparkline').sparkline();
-*
-* For line charts, x values can also be specified:
-* <p>Sparkline: <span class="sparkline">1:1,2.7:4,3.4:6,5:6,6:8,8.7:5,9:3,10:5</span></p>
-* $('#sparkline1').sparkline([ [1,1], [2.7,4], [3.4,6], [5,6], [6,8], [8.7,5], [9,3], [10,5] ])
-*
-* By default, options should be passed in as teh second argument to the sparkline function:
-* $('.sparkline').sparkline([1,2,3,4], {type: 'bar'})
-*
-* Options can also be set by passing them on the tag itself. This feature is disabled by default though
-* as there's a slight performance overhead:
-* $('.sparkline').sparkline([1,2,3,4], {enableTagOptions: true})
-* <p>Sparkline: <span class="sparkline" sparkType="bar" sparkBarColor="red">loading</span></p>
-* Prefix all options supplied as tag attribute with "spark" (configurable by setting tagOptionPrefix)
-*
-* Supported options:
-* lineColor - Color of the line used for the chart
-* fillColor - Color used to fill in the chart - Set to '' or false for a transparent chart
-* width - Width of the chart - Defaults to 3 times the number of values in pixels
-* height - Height of the chart - Defaults to the height of the containing element
-* chartRangeMin - Specify the minimum value to use for the Y range of the chart - Defaults to the minimum value supplied
-* chartRangeMax - Specify the maximum value to use for the Y range of the chart - Defaults to the maximum value supplied
-* chartRangeClip - Clip out of range values to the max/min specified by chartRangeMin and chartRangeMax
-* chartRangeMinX - Specify the minimum value to use for the X range of the chart - Defaults to the minimum value supplied
-* chartRangeMaxX - Specify the maximum value to use for the X range of the chart - Defaults to the maximum value supplied
-* composite - If true then don't erase any existing chart attached to the tag, but draw
-* another chart over the top - Note that width and height are ignored if an
-* existing chart is detected.
-* tagValuesAttribute - Name of tag attribute to check for data values - Defaults to 'values'
-* enableTagOptions - Whether to check tags for sparkline options
-* tagOptionPrefix - Prefix used for options supplied as tag attributes - Defaults to 'spark'
-*
-* There are 7 types of sparkline, selected by supplying a "type" option of 'line' (default),
-* 'bar', 'tristate', 'bullet', 'discrete', 'pie' or 'box'
-* line - Line chart. Options:
-* spotColor - Set to '' to not end each line in a circular spot
-* minSpotColor - If set, color of spot at minimum value
-* maxSpotColor - If set, color of spot at maximum value
-* spotRadius - Radius in pixels
-* lineWidth - Width of line in pixels
-* normalRangeMin
-* normalRangeMax - If set draws a filled horizontal bar between these two values marking the "normal"
-* or expected range of values
-* normalRangeColor - Color to use for the above bar
-* drawNormalOnTop - Draw the normal range above the chart fill color if true
-* defaultPixelsPerValue - Defaults to 3 pixels of width for each value in the chart
-*
-* bar - Bar chart. Options:
-* barColor - Color of bars for postive values
-* negBarColor - Color of bars for negative values
-* zeroColor - Color of bars with zero values
-* nullColor - Color of bars with null values - Defaults to omitting the bar entirely
-* barWidth - Width of bars in pixels
-* colorMap - Optional mappnig of values to colors to override the *BarColor values above
-* can be an Array of values to control the color of individual bars
-* barSpacing - Gap between bars in pixels
-* zeroAxis - Centers the y-axis around zero if true
-*
-* tristate - Charts values of win (>0), lose (<0) or draw (=0)
-* posBarColor - Color of win values
-* negBarColor - Color of lose values
-* zeroBarColor - Color of draw values
-* barWidth - Width of bars in pixels
-* barSpacing - Gap between bars in pixels
-* colorMap - Optional mappnig of values to colors to override the *BarColor values above
-* can be an Array of values to control the color of individual bars
-*
-* discrete - Options:
-* lineHeight - Height of each line in pixels - Defaults to 30% of the graph height
-* thesholdValue - Values less than this value will be drawn using thresholdColor instead of lineColor
-* thresholdColor
-*
-* bullet - Values for bullet graphs msut be in the order: target, performance, range1, range2, range3, ...
-* options:
-* targetColor - The color of the vertical target marker
-* targetWidth - The width of the target marker in pixels
-* performanceColor - The color of the performance measure horizontal bar
-* rangeColors - Colors to use for each qualitative range background color
-*
-* pie - Pie chart. Options:
-* sliceColors - An array of colors to use for pie slices
-* offset - Angle in degrees to offset the first slice - Try -90 or +90
-*
-* box - Box plot. Options:
-* raw - Set to true to supply pre-computed plot points as values
-* values should be: low_outlier, low_whisker, q1, median, q3, high_whisker, high_outlier
-* When set to false you can supply any number of values and the box plot will
-* be computed for you. Default is false.
-* showOutliers - Set to true (default) to display outliers as circles
-* outlierIRQ - Interquartile range used to determine outliers. Default 1.5
-* boxLineColor - Outline color of the box
-* boxFillColor - Fill color for the box
-* whiskerColor - Line color used for whiskers
-* outlierLineColor - Outline color of outlier circles
-* outlierFillColor - Fill color of the outlier circles
-* spotRadius - Radius of outlier circles
-* medianColor - Line color of the median line
-* target - Draw a target cross hair at the supplied value (default undefined)
-*
-*
-*
-* Examples:
-* $('#sparkline1').sparkline(myvalues, { lineColor: '#f00', fillColor: false });
-* $('.barsparks').sparkline('html', { type:'bar', height:'40px', barWidth:5 });
-* $('#tristate').sparkline([1,1,-1,1,0,0,-1], { type:'tristate' }):
-* $('#discrete').sparkline([1,3,4,5,5,3,4,5], { type:'discrete' });
-* $('#bullet').sparkline([10,12,12,9,7], { type:'bullet' });
-* $('#pie').sparkline([1,1,2], { type:'pie' });
-*/
-
-
-(function($) {
-
- /*
- * Default configuration settings
- */
- var defaults = {
- // Settings common to most/all chart types
- common: {
- type : 'line',
- lineColor : '#00f',
- fillColor : '#cdf',
- defaultPixelsPerValue : 3,
- width : 'auto',
- height : 'auto',
- composite : false,
- tagValuesAttribute: 'values',
- tagOptionsPrefix: 'spark',
- enableTagOptions: false
- },
- // Defaults for line charts
- line: {
- spotColor : '#f80',
- spotRadius : 1.5,
- minSpotColor : '#f80',
- maxSpotColor : '#f80',
- lineWidth: 1,
- normalRangeMin : undefined,
- normalRangeMax : undefined,
- normalRangeColor : '#ccc',
- drawNormalOnTop: false,
- chartRangeMin : undefined,
- chartRangeMax : undefined,
- chartRangeMinX : undefined,
- chartRangeMaxX : undefined
- },
- // Defaults for bar charts
- bar: {
- barColor : '#00f',
- negBarColor : '#f44',
- zeroColor: undefined,
- nullColor: undefined,
- zeroAxis : undefined,
- barWidth : 4,
- barSpacing : 1,
- chartRangeMax: undefined,
- chartRangeMin: undefined,
- chartRangeClip: false,
- colorMap : undefined
- },
- // Defaults for tristate charts
- tristate: {
- barWidth : 4,
- barSpacing : 1,
- posBarColor: '#6f6',
- negBarColor : '#f44',
- zeroBarColor : '#999',
- colorMap : {}
- },
- // Defaults for discrete charts
- discrete: {
- lineHeight: 'auto',
- thresholdColor: undefined,
- thresholdValue : 0,
- chartRangeMax: undefined,
- chartRangeMin: undefined,
- chartRangeClip: false
- },
- // Defaults for bullet charts
- bullet: {
- targetColor : 'red',
- targetWidth : 3, // width of the target bar in pixels
- performanceColor : 'blue',
- rangeColors : ['#D3DAFE', '#A8B6FF', '#7F94FF' ],
- base : undefined // set this to a number to change the base start number
- },
- // Defaults for pie charts
- pie: {
- sliceColors : ['#f00', '#0f0', '#00f']
- },
- // Defaults for box plots
- box: {
- raw: false,
- boxLineColor: 'black',
- boxFillColor: '#cdf',
- whiskerColor: 'black',
- outlierLineColor: '#333',
- outlierFillColor: 'white',
- medianColor: 'red',
- showOutliers: true,
- outlierIQR: 1.5,
- spotRadius: 1.5,
- target: undefined,
- targetColor: '#4a2',
- chartRangeMax: undefined,
- chartRangeMin: undefined
- }
- };
-
- // Provide a cross-browser interface to a few simple drawing primitives
- var VCanvas_base, VCanvas_canvas, VCanvas_vml;
- $.fn.simpledraw = function(width, height, use_existing) {
- if (use_existing && this[0].VCanvas) {
- return this[0].VCanvas;
- }
- if (width === undefined) {
- width=$(this).innerWidth();
- }
- if (height === undefined) {
- height=$(this).innerHeight();
- }
- if ($.browser.hasCanvas) {
- return new VCanvas_canvas(width, height, this);
- } else if ($.browser.msie) {
- return new VCanvas_vml(width, height, this);
- } else {
- return false;
- }
- };
-
- var pending = [];
-
-
- $.fn.sparkline = function(uservalues, userOptions) {
- return this.each(function() {
- var options = new $.fn.sparkline.options(this, userOptions);
- var render = function() {
- var values, width, height;
- if (uservalues==='html' || uservalues===undefined) {
- var vals = this.getAttribute(options.get('tagValuesAttribute'));
- if (vals===undefined || vals===null) {
- vals = $(this).html();
- }
- values = vals.replace(/(^\s*<!--)|(-->\s*$)|\s+/g, '').split(',');
- } else {
- values = uservalues;
- }
-
- width = options.get('width')=='auto' ? values.length*options.get('defaultPixelsPerValue') : options.get('width');
- if (options.get('height') == 'auto') {
- if (!options.get('composite') || !this.VCanvas) {
- // must be a better way to get the line height
- var tmp = document.createElement('span');
- tmp.innerHTML = 'a';
- $(this).html(tmp);
- height = $(tmp).innerHeight();
- $(tmp).remove();
- }
- } else {
- height = options.get('height');
- }
-
- $.fn.sparkline[options.get('type')].call(this, values, options, width, height);
- };
- // jQuery 1.3.0 completely changed the meaning of :hidden :-/
- if (($(this).html() && $(this).is(':hidden')) || ($.fn.jquery < "1.3.0" && $(this).parents().is(':hidden')) || !$(this).parents('body').length) {
- pending.push([this, render]);
- } else {
- render.call(this);
- }
- });
- };
-
- $.fn.sparkline.defaults = defaults;
-
-
- $.sparkline_display_visible = function() {
- for (var i=pending.length-1; i>=0; i--) {
- var el = pending[i][0];
- if ($(el).is(':visible') && !$(el).parents().is(':hidden')) {
- pending[i][1].call(el);
- pending.splice(i, 1);
- }
- }
- };
-
-
- /**
- * User option handler
- */
- var UNSET_OPTION = {};
- var normalizeValue = function(val) {
- switch(val) {
- case 'undefined':
- val = undefined;
- break;
- case 'null':
- val = null;
- break;
- case 'true':
- val = true;
- break;
- case 'false':
- val = false;
- break;
- default:
- var nf = parseFloat(val);
- if (val == nf) {
- val = nf;
- }
- }
- return val;
- };
- $.fn.sparkline.options = function(tag, userOptions) {
- var extendedOptions;
- this.userOptions = userOptions = userOptions || {};
- this.tag = tag;
- this.tagValCache = {};
- var defaults = $.fn.sparkline.defaults;
- var base = defaults.common;
- this.tagOptionsPrefix = userOptions.enableTagOptions && (userOptions.tagOptionsPrefix || base.tagOptionsPrefix);
-
- var tagOptionType = this.getTagSetting('type');
- if (tagOptionType === UNSET_OPTION) {
- extendedOptions = defaults[userOptions.type || base.type];
- } else {
- extendedOptions = defaults[tagOptionType];
- }
- this.mergedOptions = $.extend({}, base, extendedOptions, userOptions);
- };
-
-
- $.fn.sparkline.options.prototype.getTagSetting = function(key) {
- var val, i, prefix = this.tagOptionsPrefix;
- if (prefix === false || prefix === undefined) {
- return UNSET_OPTION;
- }
- if (this.tagValCache.hasOwnProperty(key)) {
- val = this.tagValCache.key;
- } else {
- val = this.tag.getAttribute(prefix + key);
- if (val === undefined || val === null) {
- val = UNSET_OPTION;
- } else if (val.substr(0, 1) == '[') {
- val = val.substr(1, val.length-2).split(',');
- for(i=val.length; i--;) {
- val[i] = normalizeValue(val[i].replace(/(^\s*)|(\s*$)/g, ''));
- }
- } else if (val.substr(0, 1) == '{') {
- var pairs= val.substr(1, val.length-2).split(',');
- val = {};
- for(i=pairs.length; i--;) {
- var keyval = pairs[i].split(':', 2);
- val[keyval[0].replace(/(^\s*)|(\s*$)/g, '')] = normalizeValue(keyval[1].replace(/(^\s*)|(\s*$)/g, ''));
- }
- } else {
- val = normalizeValue(val);
- }
- this.tagValCache.key = val;
- }
- return val;
- };
-
- $.fn.sparkline.options.prototype.get = function(key) {
- var tagOption = this.getTagSetting(key);
- if (tagOption !== UNSET_OPTION) {
- return tagOption;
- }
- return this.mergedOptions[key];
- };
-
-
- /**
- * Line charts
- */
- $.fn.sparkline.line = function(values, options, width, height) {
- var xvalues = [], yvalues = [], yminmax = [];
- for (var i=0; i<values.length; i++) {
- var val = values[i];
- var isstr = typeof(values[i])=='string';
- var isarray = typeof(values[i])=='object' && values[i] instanceof Array;
- var sp = isstr && values[i].split(':');
- if (isstr && sp.length == 2) { // x:y
- xvalues.push(Number(sp[0]));
- yvalues.push(Number(sp[1]));
- yminmax.push(Number(sp[1]));
- } else if (isarray) {
- xvalues.push(val[0]);
- yvalues.push(val[1]);
- yminmax.push(val[1]);
- } else {
- xvalues.push(i);
- if (values[i]===null || values[i]=='null') {
- yvalues.push(null);
- } else {
- yvalues.push(Number(val));
- yminmax.push(Number(val));
- }
- }
- }
- if (options.get('xvalues')) {
- xvalues = options.get('xvalues');
- }
-
- var maxy = Math.max.apply(Math, yminmax);
- var maxyval = maxy;
- var miny = Math.min.apply(Math, yminmax);
- var minyval = miny;
-
- var maxx = Math.max.apply(Math, xvalues);
- var minx = Math.min.apply(Math, xvalues);
-
- var normalRangeMin = options.get('normalRangeMin');
- var normalRangeMax = options.get('normalRangeMax');
-
- if (normalRangeMin!==undefined) {
- if (normalRangeMin<miny) {
- miny = normalRangeMin;
- }
- if (normalRangeMax>maxy) {
- maxy = normalRangeMax;
- }
- }
- if (options.get('chartRangeMin')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMin')<miny)) {
- miny = options.get('chartRangeMin');
- }
- if (options.get('chartRangeMax')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMax')>maxy)) {
- maxy = options.get('chartRangeMax');
- }
- if (options.get('chartRangeMinX')!==undefined && (options.get('chartRangeClipX') || options.get('chartRangeMinX')<minx)) {
- minx = options.get('chartRangeMinX');
- }
- if (options.get('chartRangeMaxX')!==undefined && (options.get('chartRangeClipX') || options.get('chartRangeMaxX')>maxx)) {
- maxx = options.get('chartRangeMaxX');
- }
- var rangex = maxx-minx === 0 ? 1 : maxx-minx;
- var rangey = maxy-miny === 0 ? 1 : maxy-miny;
- var vl = yvalues.length-1;
-
- if (vl<1) {
- this.innerHTML = '';
- return;
- }
-
- var target = $(this).simpledraw(width, height, options.get('composite'));
- if (target) {
- var canvas_width = target.pixel_width;
- var canvas_height = target.pixel_height;
- var canvas_top = 0;
- var canvas_left = 0;
-
- var spotRadius = options.get('spotRadius');
- if (spotRadius && (canvas_width < (spotRadius*4) || canvas_height < (spotRadius*4))) {
- spotRadius = 0;
- }
- if (spotRadius) {
- // adjust the canvas size as required so that spots will fit
- if (options.get('minSpotColor') || (options.get('spotColor') && yvalues[vl]==miny)) {
- canvas_height -= Math.ceil(spotRadius);
- }
- if (options.get('maxSpotColor') || (options.get('spotColor') && yvalues[vl]==maxy)) {
- canvas_height -= Math.ceil(spotRadius);
- canvas_top += Math.ceil(spotRadius);
- }
- if (options.get('minSpotColor') || options.get('maxSpotColor') && (yvalues[0]==miny || yvalues[0]==maxy)) {
- canvas_left += Math.ceil(spotRadius);
- canvas_width -= Math.ceil(spotRadius);
- }
- if (options.get('spotColor') || (options.get('minSpotColor') || options.get('maxSpotColor') && (yvalues[vl]==miny||yvalues[vl]==maxy))) {
- canvas_width -= Math.ceil(spotRadius);
- }
- }
-
-
- canvas_height--;
-
- var drawNormalRange = function() {
- if (normalRangeMin!==undefined) {
- var ytop = canvas_top+Math.round(canvas_height-(canvas_height*((normalRangeMax-miny)/rangey)));
- var height = Math.round((canvas_height*(normalRangeMax-normalRangeMin))/rangey);
- target.drawRect(canvas_left, ytop, canvas_width, height, undefined, options.get('normalRangeColor'));
- }
- };
-
- if (!options.get('drawNormalOnTop')) {
- drawNormalRange();
- }
-
- var path = [];
- var paths = [path];
- var x, y, vlen=yvalues.length;
- for(i=0; i<vlen; i++) {
- x=xvalues[i];
- y=yvalues[i];
- if (y===null) {
- if (i) {
- if (yvalues[i-1]!==null) {
- path = [];
- paths.push(path);
- }
- }
- } else {
- if (y < miny) {
- y=miny;
- }
- if (y > maxy) {
- y=maxy;
- }
- if (!path.length) {
- // previous value was null
- path.push([canvas_left+Math.round((x-minx)*(canvas_width/rangex)), canvas_top+canvas_height]);
- }
- path.push([canvas_left+Math.round((x-minx)*(canvas_width/rangex)), canvas_top+Math.round(canvas_height-(canvas_height*((y-miny)/rangey)))]);
- }
- }
- var lineshapes = [];
- var fillshapes = [];
- var plen=paths.length;
- for(i=0; i<plen; i++) {
- path = paths[i];
- if (!path.length) {
- continue; // last value was null
- }
- if (options.get('fillColor')) {
- path.push([path[path.length-1][0], canvas_top+canvas_height-1]);
- fillshapes.push(path.slice(0));
- path.pop();
- }
- // if there's only a single point in this path, then we want to display it as a vertical line
- // which means we keep path[0] as is
- if (path.length>2) {
- // else we want the first value
- path[0] = [ path[0][0], path[1][1] ];
- }
- lineshapes.push(path);
- }
-
- // draw the fill first, then optionally the normal range, then the line on top of that
- plen = fillshapes.length;
- for(i=0; i<plen; i++) {
- target.drawShape(fillshapes[i], undefined, options.get('fillColor'));
- }
-
- if (options.get('drawNormalOnTop')) {
- drawNormalRange();
- }
-
- plen = lineshapes.length;
- for(i=0; i<plen; i++) {
- target.drawShape(lineshapes[i], options.get('lineColor'), undefined, options.get('lineWidth'));
- }
-
- if (spotRadius && options.get('spotColor')) {
- target.drawCircle(canvas_left+Math.round(xvalues[xvalues.length-1]*(canvas_width/rangex)), canvas_top+Math.round(canvas_height-(canvas_height*((yvalues[vl]-miny)/rangey))), spotRadius, undefined, options.get('spotColor'));
- }
- if (maxy!=minyval) {
- if (spotRadius && options.get('minSpotColor')) {
- x = xvalues[$.inArray(minyval, yvalues)];
- target.drawCircle(canvas_left+Math.round((x-minx)*(canvas_width/rangex)), canvas_top+Math.round(canvas_height-(canvas_height*((minyval-miny)/rangey))), spotRadius, undefined, options.get('minSpotColor'));
- }
- if (spotRadius && options.get('maxSpotColor')) {
- x = xvalues[$.inArray(maxyval, yvalues)];
- target.drawCircle(canvas_left+Math.round((x-minx)*(canvas_width/rangex)), canvas_top+Math.round(canvas_height-(canvas_height*((maxyval-miny)/rangey))), spotRadius, undefined, options.get('maxSpotColor'));
- }
- }
-
- } else {
- // Remove the tag contents if sparklines aren't supported
- this.innerHTML = '';
- }
- };
-
-
- /**
- * Bar charts
- */
- $.fn.sparkline.bar = function(values, options, width, height) {
- width = (values.length * options.get('barWidth')) + ((values.length-1) * options.get('barSpacing'));
- var num_values = [];
- for(var i=0, vlen=values.length; i<vlen; i++) {
- if (values[i]=='null' || values[i]===null) {
- values[i] = null;
- } else {
- values[i] = Number(values[i]);
- num_values.push(Number(values[i]));
- }
- }
- var max = Math.max.apply(Math, num_values),
- min = Math.min.apply(Math, num_values);
- if (options.get('chartRangeMin')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMin')<min)) {
- min = options.get('chartRangeMin');
- }
- if (options.get('chartRangeMax')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMax')>max)) {
- max = options.get('chartRangeMax');
- }
- var zeroAxis = options.get('zeroAxis');
- if (zeroAxis === undefined) {
- zeroAxis = min<0;
- }
- var range = max-min === 0 ? 1 : max-min;
-
- var colorMapByIndex, colorMapByValue;
- if ($.isArray(options.get('colorMap'))) {
- colorMapByIndex = options.get('colorMap');
- colorMapByValue = null;
- } else {
- colorMapByIndex = null;
- colorMapByValue = options.get('colorMap');
- }
-
- var target = $(this).simpledraw(width, height, options.get('composite'));
- if (target) {
- var color,
- canvas_height = target.pixel_height,
- yzero = min<0 && zeroAxis ? canvas_height-Math.round(canvas_height * (Math.abs(min)/range))-1 : canvas_height-1;
-
- for(i=values.length; i--;) {
- var x = i*(options.get('barWidth')+options.get('barSpacing')),
- y,
- val = values[i];
- if (val===null) {
- if (options.get('nullColor')) {
- color = options.get('nullColor');
- val = (zeroAxis && min<0) ? 0 : min;
- height = 1;
- y = (zeroAxis && min<0) ? yzero : canvas_height - height;
- } else {
- continue;
- }
- } else {
- if (val < min) {
- val=min;
- }
- if (val > max) {
- val=max;
- }
- color = (val < 0) ? options.get('negBarColor') : options.get('barColor');
- if (zeroAxis && min<0) {
- height = Math.round(canvas_height*((Math.abs(val)/range)))+1;
- y = (val < 0) ? yzero : yzero-height;
- } else {
- height = Math.round(canvas_height*((val-min)/range))+1;
- y = canvas_height-height;
- }
- if (val===0 && options.get('zeroColor')!==undefined) {
- color = options.get('zeroColor');
- }
- if (colorMapByValue && colorMapByValue[val]) {
- color = colorMapByValue[val];
- } else if (colorMapByIndex && colorMapByIndex.length>i) {
- color = colorMapByIndex[i];
- }
- if (color===null) {
- continue;
- }
- }
- target.drawRect(x, y, options.get('barWidth')-1, height-1, color, color);
- }
- } else {
- // Remove the tag contents if sparklines aren't supported
- this.innerHTML = '';
- }
- };
-
-
- /**
- * Tristate charts
- */
- $.fn.sparkline.tristate = function(values, options, width, height) {
- values = $.map(values, Number);
- width = (values.length * options.get('barWidth')) + ((values.length-1) * options.get('barSpacing'));
-
- var colorMapByIndex, colorMapByValue;
- if ($.isArray(options.get('colorMap'))) {
- colorMapByIndex = options.get('colorMap');
- colorMapByValue = null;
- } else {
- colorMapByIndex = null;
- colorMapByValue = options.get('colorMap');
- }
-
- var target = $(this).simpledraw(width, height, options.get('composite'));
- if (target) {
- var canvas_height = target.pixel_height,
- half_height = Math.round(canvas_height/2);
-
- for(var i=values.length; i--;) {
- var x = i*(options.get('barWidth')+options.get('barSpacing')),
- y, color;
- if (values[i] < 0) {
- y = half_height;
- height = half_height-1;
- color = options.get('negBarColor');
- } else if (values[i] > 0) {
- y = 0;
- height = half_height-1;
- color = options.get('posBarColor');
- } else {
- y = half_height-1;
- height = 2;
- color = options.get('zeroBarColor');
- }
- if (colorMapByValue && colorMapByValue[values[i]]) {
- color = colorMapByValue[values[i]];
- } else if (colorMapByIndex && colorMapByIndex.length>i) {
- color = colorMapByIndex[i];
- }
- if (color===null) {
- continue;
- }
- target.drawRect(x, y, options.get('barWidth')-1, height-1, color, color);
- }
- } else {
- // Remove the tag contents if sparklines aren't supported
- this.innerHTML = '';
- }
- };
-
-
- /**
- * Discrete charts
- */
- $.fn.sparkline.discrete = function(values, options, width, height) {
- values = $.map(values, Number);
- width = options.get('width')=='auto' ? values.length*2 : width;
- var interval = Math.floor(width / values.length);
-
- var target = $(this).simpledraw(width, height, options.get('composite'));
- if (target) {
- var canvas_height = target.pixel_height,
- line_height = options.get('lineHeight') == 'auto' ? Math.round(canvas_height * 0.3) : options.get('lineHeight'),
- pheight = canvas_height - line_height,
- min = Math.min.apply(Math, values),
- max = Math.max.apply(Math, values);
- if (options.get('chartRangeMin')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMin')<min)) {
- min = options.get('chartRangeMin');
- }
- if (options.get('chartRangeMax')!==undefined && (options.get('chartRangeClip') || options.get('chartRangeMax')>max)) {
- max = options.get('chartRangeMax');
- }
- var range = max-min;
-
- for(var i=values.length; i--;) {
- var val = values[i];
- if (val < min) {
- val=min;
- }
- if (val > max) {
- val=max;
- }
- var x = (i*interval),
- ytop = Math.round(pheight-pheight*((val-min)/range));
- target.drawLine(x, ytop, x, ytop+line_height, (options.get('thresholdColor') && val < options.get('thresholdValue')) ? options.get('thresholdColor') : options.get('lineColor'));
- }
- } else {
- // Remove the tag contents if sparklines aren't supported
- this.innerHTML = '';
- }
-
- };
-
-
- /**
- * Bullet charts
- */
- $.fn.sparkline.bullet = function(values, options, width, height) {
- values = $.map(values, Number);
- // target, performance, range1, range2, range3
-
- width = options.get('width')=='auto' ? '4.0em' : width;
-
- var target = $(this).simpledraw(width, height, options.get('composite'));
- if (target && values.length>1) {
- var canvas_width = target.pixel_width-Math.ceil(options.get('targetWidth')/2),
- canvas_height = target.pixel_height,
- min = Math.min.apply(Math, values),
- max = Math.max.apply(Math, values);
-
- if (options.get('base') === undefined) {
- min = min < 0 ? min : 0;
- } else {
- min = options.get('base');
- }
- var range = max-min;
-
- // draw range values
- for(var i=2, vlen=values.length; i<vlen; i++) {
- var rangeval = values[i],
- rangewidth = Math.round(canvas_width*((rangeval-min)/range));
- target.drawRect(0, 0, rangewidth-1, canvas_height-1, options.get('rangeColors')[i-2], options.get('rangeColors')[i-2]);
- }
-
- // draw the performance bar
- var perfval = values[1],
- perfwidth = Math.round(canvas_width*((perfval-min)/range));
- target.drawRect(0, Math.round(canvas_height*0.3), perfwidth-1, Math.round(canvas_height*0.4)-1, options.get('performanceColor'), options.get('performanceColor'));
-
- // draw the target line
- var targetval = values[0],
- x = Math.round(canvas_width*((targetval-min)/range)-(options.get('targetWidth')/2)),
- targettop = Math.round(canvas_height*0.10),
- targetheight = canvas_height-(targettop*2);
- target.drawRect(x, targettop, options.get('targetWidth')-1, targetheight-1, options.get('targetColor'), options.get('targetColor'));
- } else {
- // Remove the tag contents if sparklines aren't supported
- this.innerHTML = '';
- }
- };
-
-
- /**
- * Pie charts
- */
- $.fn.sparkline.pie = function(values, options, width, height) {
- values = $.map(values, Number);
- width = options.get('width')=='auto' ? height : width;
-
- var target = $(this).simpledraw(width, height, options.get('composite'));
- if (target && values.length>1) {
- var canvas_width = target.pixel_width,
- canvas_height = target.pixel_height,
- radius = Math.floor(Math.min(canvas_width, canvas_height)/2),
- total = 0,
- next = 0,
- circle = 2*Math.PI;
-
- for(var i=values.length; i--;) {
- total += values[i];
- }
-
- if (options.get('offset')) {
- next += (2*Math.PI)*(options.get('offset')/360);
- }
- var vlen = values.length;
- for(i=0; i<vlen; i++) {
- var start = next;
- var end = next;
- if (total > 0) { // avoid divide by zero
- end = next + (circle*(values[i]/total));
- }
- target.drawPieSlice(radius, radius, radius, start, end, undefined, options.get('sliceColors')[i % options.get('sliceColors').length]);
- next = end;
- }
- }
- };
-
-
- /**
- * Box plots
- */
- var quartile = function(values, q) {
- if (q==2) {
- var vl2 = Math.floor(values.length/2);
- return values.length % 2 ? values[vl2] : (values[vl2]+values[vl2+1])/2;
- } else {
- var vl4 = Math.floor(values.length/4);
- return values.length % 2 ? (values[vl4*q]+values[vl4*q+1])/2 : values[vl4*q];
- }
- };
-
- $.fn.sparkline.box = function(values, options, width, height) {
- values = $.map(values, Number);
- width = options.get('width')=='auto' ? '4.0em' : width;
-
- var minvalue = options.get('chartRangeMin')===undefined ? Math.min.apply(Math, values) : options.get('chartRangeMin'),
- maxvalue = options.get('chartRangeMax')===undefined ? Math.max.apply(Math, values) : options.get('chartRangeMax'),
- target = $(this).simpledraw(width, height, options.get('composite')),
- vlen = values.length,
- lwhisker, loutlier, q1, q2, q3, rwhisker, routlier;
-
- if (target && values.length>1) {
- var canvas_width = target.pixel_width,
- canvas_height = target.pixel_height;
- if (options.get('raw')) {
- if (options.get('showOutliers') && values.length>5) {
- loutlier=values[0]; lwhisker=values[1]; q1=values[2]; q2=values[3]; q3=values[4]; rwhisker=values[5]; routlier=values[6];
- } else {
- lwhisker=values[0]; q1=values[1]; q2=values[2]; q3=values[3]; rwhisker=values[4];
- }
- } else {
- values.sort(function(a, b) { return a-b; });
- q1 = quartile(values, 1);
- q2 = quartile(values, 2);
- q3 = quartile(values, 3);
- var iqr = q3-q1;
- if (options.get('showOutliers')) {
- lwhisker=undefined; rwhisker=undefined;
- for(var i=0; i<vlen; i++) {
- if (lwhisker===undefined && values[i] > q1-(iqr*options.get('outlierIQR'))) {
- lwhisker = values[i];
- }
- if (values[i] < q3+(iqr*options.get('outlierIQR'))) {
- rwhisker = values[i];
- }
- }
- loutlier = values[0];
- routlier = values[vlen-1];
- } else {
- lwhisker = values[0];
- rwhisker = values[vlen-1];
- }
- }
-
- var unitsize = canvas_width / (maxvalue-minvalue+1),
- canvas_left = 0;
- if (options.get('showOutliers')) {
- canvas_left = Math.ceil(options.get('spotRadius'));
- canvas_width -= 2*Math.ceil(options.get('spotRadius'));
- unitsize = canvas_width / (maxvalue-minvalue+1);
- if (loutlier < lwhisker) {
- target.drawCircle((loutlier-minvalue)*unitsize+canvas_left, canvas_height/2, options.get('spotRadius'), options.get('outlierLineColor'), options.get('outlierFillColor'));
- }
- if (routlier > rwhisker) {
- target.drawCircle((routlier-minvalue)*unitsize+canvas_left, canvas_height/2, options.get('spotRadius'), options.get('outlierLineColor'), options.get('outlierFillColor'));
- }
- }
-
- // box
- target.drawRect(
- Math.round((q1-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height*0.1),
- Math.round((q3-q1)*unitsize),
- Math.round(canvas_height*0.8),
- options.get('boxLineColor'),
- options.get('boxFillColor'));
- // left whisker
- target.drawLine(
- Math.round((lwhisker-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height/2),
- Math.round((q1-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height/2),
- options.get('lineColor'));
- target.drawLine(
- Math.round((lwhisker-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height/4),
- Math.round((lwhisker-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height-canvas_height/4),
- options.get('whiskerColor'));
- // right whisker
- target.drawLine(Math.round((rwhisker-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height/2),
- Math.round((q3-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height/2),
- options.get('lineColor'));
- target.drawLine(
- Math.round((rwhisker-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height/4),
- Math.round((rwhisker-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height-canvas_height/4),
- options.get('whiskerColor'));
- // median line
- target.drawLine(
- Math.round((q2-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height*0.1),
- Math.round((q2-minvalue)*unitsize+canvas_left),
- Math.round(canvas_height*0.9),
- options.get('medianColor'));
- if (options.get('target')) {
- var size = Math.ceil(options.get('spotRadius'));
- target.drawLine(
- Math.round((options.get('target')-minvalue)*unitsize+canvas_left),
- Math.round((canvas_height/2)-size),
- Math.round((options.get('target')-minvalue)*unitsize+canvas_left),
- Math.round((canvas_height/2)+size),
- options.get('targetColor'));
- target.drawLine(
- Math.round((options.get('target')-minvalue)*unitsize+canvas_left-size),
- Math.round(canvas_height/2),
- Math.round((options.get('target')-minvalue)*unitsize+canvas_left+size),
- Math.round(canvas_height/2),
- options.get('targetColor'));
- }
- } else {
- // Remove the tag contents if sparklines aren't supported
- this.innerHTML = '';
- }
- };
-
-
- // Setup a very simple "virtual canvas" to make drawing the few shapes we need easier
- // This is accessible as $(foo).simpledraw()
-
- if ($.browser.msie && !document.namespaces.v) {
- document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', '#default#VML');
- }
-
- if ($.browser.hasCanvas === undefined) {
- var t = document.createElement('canvas');
- $.browser.hasCanvas = t.getContext!==undefined;
- }
-
- VCanvas_base = function(width, height, target) {
- };
-
- VCanvas_base.prototype = {
- init : function(width, height, target) {
- this.width = width;
- this.height = height;
- this.target = target;
- if (target[0]) {
- target=target[0];
- }
- target.VCanvas = this;
- },
-
- drawShape : function(path, lineColor, fillColor, lineWidth) {
- alert('drawShape not implemented');
- },
-
- drawLine : function(x1, y1, x2, y2, lineColor, lineWidth) {
- return this.drawShape([ [x1,y1], [x2,y2] ], lineColor, lineWidth);
- },
-
- drawCircle : function(x, y, radius, lineColor, fillColor) {
- alert('drawCircle not implemented');
- },
-
- drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor) {
- alert('drawPieSlice not implemented');
- },
-
- drawRect : function(x, y, width, height, lineColor, fillColor) {
- alert('drawRect not implemented');
- },
-
- getElement : function() {
- return this.canvas;
- },
-
- _insert : function(el, target) {
- $(target).html(el);
- }
- };
-
- VCanvas_canvas = function(width, height, target) {
- return this.init(width, height, target);
- };
-
- VCanvas_canvas.prototype = $.extend(new VCanvas_base(), {
- _super : VCanvas_base.prototype,
-
- init : function(width, height, target) {
- this._super.init(width, height, target);
- this.canvas = document.createElement('canvas');
- if (target[0]) {
- target=target[0];
- }
- target.VCanvas = this;
- $(this.canvas).css({ display:'inline-block', width:width, height:height, verticalAlign:'top' });
- this._insert(this.canvas, target);
- this.pixel_height = $(this.canvas).height();
- this.pixel_width = $(this.canvas).width();
- this.canvas.width = this.pixel_width;
- this.canvas.height = this.pixel_height;
- $(this.canvas).css({width: this.pixel_width, height: this.pixel_height});
- },
-
- _getContext : function(lineColor, fillColor, lineWidth) {
- var context = this.canvas.getContext('2d');
- if (lineColor !== undefined) {
- context.strokeStyle = lineColor;
- }
- context.lineWidth = lineWidth===undefined ? 1 : lineWidth;
- if (fillColor !== undefined) {
- context.fillStyle = fillColor;
- }
- return context;
- },
-
- drawShape : function(path, lineColor, fillColor, lineWidth) {
- var context = this._getContext(lineColor, fillColor, lineWidth);
- context.beginPath();
- context.moveTo(path[0][0]+0.5, path[0][1]+0.5);
- for(var i=1, plen=path.length; i<plen; i++) {
- context.lineTo(path[i][0]+0.5, path[i][1]+0.5); // the 0.5 offset gives us crisp pixel-width lines
- }
- if (lineColor !== undefined) {
- context.stroke();
- }
- if (fillColor !== undefined) {
- context.fill();
- }
- },
-
- drawCircle : function(x, y, radius, lineColor, fillColor) {
- var context = this._getContext(lineColor, fillColor);
- context.beginPath();
- context.arc(x, y, radius, 0, 2*Math.PI, false);
- if (lineColor !== undefined) {
- context.stroke();
- }
- if (fillColor !== undefined) {
- context.fill();
- }
- },
-
- drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor) {
- var context = this._getContext(lineColor, fillColor);
- context.beginPath();
- context.moveTo(x, y);
- context.arc(x, y, radius, startAngle, endAngle, false);
- context.lineTo(x, y);
- context.closePath();
- if (lineColor !== undefined) {
- context.stroke();
- }
- if (fillColor) {
- context.fill();
- }
- },
-
- drawRect : function(x, y, width, height, lineColor, fillColor) {
- return this.drawShape([ [x,y], [x+width, y], [x+width, y+height], [x, y+height], [x, y] ], lineColor, fillColor);
- }
-
- });
-
- VCanvas_vml = function(width, height, target) {
- return this.init(width, height, target);
- };
-
- VCanvas_vml.prototype = $.extend(new VCanvas_base(), {
- _super : VCanvas_base.prototype,
-
- init : function(width, height, target) {
- this._super.init(width, height, target);
- if (target[0]) {
- target=target[0];
- }
- target.VCanvas = this;
- this.canvas = document.createElement('span');
- $(this.canvas).css({ display:'inline-block', position: 'relative', overflow:'hidden', width:width, height:height, margin:'0px', padding:'0px', verticalAlign: 'top'});
- this._insert(this.canvas, target);
- this.pixel_height = $(this.canvas).height();
- this.pixel_width = $(this.canvas).width();
- this.canvas.width = this.pixel_width;
- this.canvas.height = this.pixel_height;
- var groupel = '<v:group coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'"' +
- ' style="position:absolute;top:0;left:0;width:'+this.pixel_width+'px;height='+this.pixel_height+'px;"></v:group>';
- this.canvas.insertAdjacentHTML('beforeEnd', groupel);
- this.group = $(this.canvas).children()[0];
- },
-
- drawShape : function(path, lineColor, fillColor, lineWidth) {
- var vpath = [];
- for(var i=0, plen=path.length; i<plen; i++) {
- vpath[i] = ''+(path[i][0])+','+(path[i][1]);
- }
- var initial = vpath.splice(0,1);
- lineWidth = lineWidth === undefined ? 1 : lineWidth;
- var stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="'+lineWidth+'" strokeColor="'+lineColor+'" ';
- var fill = fillColor === undefined ? ' filled="false"' : ' fillColor="'+fillColor+'" filled="true" ';
- var closed = vpath[0] == vpath[vpath.length-1] ? 'x ' : '';
- var vel = '<v:shape coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'" ' +
- stroke +
- fill +
- ' style="position:absolute;left:0px;top:0px;height:'+this.pixel_height+'px;width:'+this.pixel_width+'px;padding:0px;margin:0px;" ' +
- ' path="m '+initial+' l '+vpath.join(', ')+' '+closed+'e">' +
- ' </v:shape>';
- this.group.insertAdjacentHTML('beforeEnd', vel);
- },
-
- drawCircle : function(x, y, radius, lineColor, fillColor) {
- x -= radius+1;
- y -= radius+1;
- var stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="1" strokeColor="'+lineColor+'" ';
- var fill = fillColor === undefined ? ' filled="false"' : ' fillColor="'+fillColor+'" filled="true" ';
- var vel = '<v:oval ' +
- stroke +
- fill +
- ' style="position:absolute;top:'+y+'px; left:'+x+'px; width:'+(radius*2)+'px; height:'+(radius*2)+'px"></v:oval>';
- this.group.insertAdjacentHTML('beforeEnd', vel);
-
- },
-
- drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor) {
- if (startAngle == endAngle) {
- return; // VML seems to have problem when start angle equals end angle.
- }
- if ((endAngle - startAngle) == (2*Math.PI)) {
- startAngle = 0.0; // VML seems to have a problem when drawing a full circle that doesn't start 0
- endAngle = (2*Math.PI);
- }
-
- var startx = x + Math.round(Math.cos(startAngle) * radius);
- var starty = y + Math.round(Math.sin(startAngle) * radius);
- var endx = x + Math.round(Math.cos(endAngle) * radius);
- var endy = y + Math.round(Math.sin(endAngle) * radius);
-
- // Prevent very small slices from being mistaken as a whole pie
- if (startx==endx && starty==endy && (endAngle-startAngle) < Math.PI) {
- return;
- }
-
- var vpath = [ x-radius, y-radius, x+radius, y+radius, startx, starty, endx, endy ];
- var stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="1" strokeColor="'+lineColor+'" ';
- var fill = fillColor === undefined ? ' filled="false"' : ' fillColor="'+fillColor+'" filled="true" ';
- var vel = '<v:shape coordorigin="0 0" coordsize="'+this.pixel_width+' '+this.pixel_height+'" ' +
- stroke +
- fill +
- ' style="position:absolute;left:0px;top:0px;height:'+this.pixel_height+'px;width:'+this.pixel_width+'px;padding:0px;margin:0px;" ' +
- ' path="m '+x+','+y+' wa '+vpath.join(', ')+' x e">' +
- ' </v:shape>';
- this.group.insertAdjacentHTML('beforeEnd', vel);
- },
-
- drawRect : function(x, y, width, height, lineColor, fillColor) {
- return this.drawShape( [ [x, y], [x, y+height], [x+width, y+height], [x+width, y], [x, y] ], lineColor, fillColor);
- }
- });
-
-})(jQuery);
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-2.0.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-2.0.min.js
new file mode 100644
index 0000000..ea174b6
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/jquery.sparkline-2.0.min.js
@@ -0,0 +1,5 @@
+/* jquery.sparkline 2.0 - http://omnipotent.net/jquery.sparkline/
+** Licensed under the New BSD License - see above site for details */
+
+(function(a){"use strict";var b={},c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I=0;c=function(){return{common:{type:"line",lineColor:"#00f",fillColor:"#cdf",defaultPixelsPerValue:3,width:"auto",height:"auto",composite:!1,tagValuesAttribute:"values",tagOptionsPrefix:"spark",enableTagOptions:!1,enableHighlight:!0,highlightLighten:1.4,tooltipSkipNull:!0,tooltipPrefix:"",tooltipSuffix:"",disableHiddenCheck:!1,numberFormatter:!1,numberDigitGroupCount:3,numberDigitGroupSep:",",numberDecimalMark:".",disableTooltips:!1,disableInteraction:!1},line:{spotColor:"#f80",highlightSpotColor:"#5f5",highlightLineColor:"#f22",spotRadius:1.5,minSpotColor:"#f80",maxSpotColor:"#f80",lineWidth:1,normalRangeMin:undefined,normalRangeMax:undefined,normalRangeColor:"#ccc",drawNormalOnTop:!1,chartRangeMin:undefined,chartRangeMax:undefined,chartRangeMinX:undefined,chartRangeMaxX:undefined,tooltipFormat:new e('<span style="color: {{color}}">●</span> {{prefix}}{{y}}{{suffix}}')},
bar:{barColor:"#3366cc",negBarColor:"#f44",stackedBarColor:["#3366cc","#dc3912","#ff9900","#109618","#66aa00","#dd4477","#0099c6","#990099"],zeroColor:undefined,nullColor:undefined,zeroAxis:!0,barWidth:4,barSpacing:1,chartRangeMax:undefined,chartRangeMin:undefined,chartRangeClip:!1,colorMap:undefined,tooltipFormat:new e('<span style="color: {{color}}">●</span> {{prefix}}{{value}}{{suffix}}')},tristate:{barWidth:4,barSpacing:1,posBarColor:"#6f6",negBarColor:"#f44",zeroBarColor:"#999",colorMap:{},tooltipFormat:new e('<span style="color: {{color}}">●</span> {{value:map}}'),tooltipValueLookups:{map:{"-1":"Loss",0:"Draw",1:"Win"}}},discrete:{lineHeight:"auto",thresholdColor:undefined,thresholdValue:0,chartRangeMax:undefined,chartRangeMin:undefined,chartRangeClip:!1,tooltipFormat:new e("{{prefix}}{{value}}{{suffix}}")},bullet:{targetColor:"#f33",targetWidth:3,performanceColor:"#33f",rangeColors:["#d3dafe","#a8b6ff","#7f94ff"],base:undefined,tooltipFormat:new e("{{field
key:fields}} - {{value}}"),tooltipValueLookups:{fields:{r:"Range",p:"Performance",t:"Target"}}},pie:{offset:0,sliceColors:["#3366cc","#dc3912","#ff9900","#109618","#66aa00","#dd4477","#0099c6","#990099"],borderWidth:0,borderColor:"#000",tooltipFormat:new e('<span style="color: {{color}}">●</span> {{value}} ({{percent.1}}%)')},box:{raw:!1,boxLineColor:"#000",boxFillColor:"#cdf",whiskerColor:"#000",outlierLineColor:"#333",outlierFillColor:"#fff",medianColor:"#f00",showOutliers:!0,outlierIQR:1.5,spotRadius:1.5,target:undefined,targetColor:"#4a2",chartRangeMax:undefined,chartRangeMin:undefined,tooltipFormat:new e("{{field:fields}}: {{value}}"),tooltipFormatFieldlistKey:"field",tooltipValueLookups:{fields:{lq:"Lower Quartile",med:"Median",uq:"Upper Quartile",lo:"Left Outlier",ro:"Right Outlier",lw:"Left Whisker",rw:"Right Whisker"}}}}},B='.jqstooltip { position: absolute;left: 0px;top: 0px;visibility: hidden;background: rgb(0, 0, 0) transparent;background-color: rgba(0,0,0,
0.6);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";color: white;font: 10px arial, san serif;text-align: left;white-space: nowrap;padding: 5px;border: 1px solid white;}.jqsfield { color: white;font: 10px arial, san serif;text-align: left;}',C=function(){n(B)},a(C),d=function(){var b,c;return b=function(){this.init.apply(this,arguments)},arguments.length>1?(arguments[0]?(b.prototype=a.extend(new arguments[0],arguments[arguments.length-1]),b._super=arguments[0].prototype):b.prototype=arguments[arguments.length-1],arguments.length>2&&(c=Array.prototype.slice.call(arguments,1,-1),c.unshift(b.prototype),a.extend.apply(a,c))):b.prototype=arguments[0],b.prototype.cls=b,b},a.SPFormatClass=e=d({fre:/\{\{([\w.]+?)(:(.+?))?\}\}/g,precre:/(\w+)\.(\d+)/,init:function(a,b){this.format=a,this.fclass=b},render:function(a,b,c){var d=this,
e=a,f,g,h,i,j;return this.format.replace(this.fre,function(){var a;return g=arguments[1],h=arguments[3],f=d.precre.exec(g),f?(j=f[2],g=f[1]):j=!1,i=e[g],i===undefined?"":h&&b&&b[h]?(a=b[h],a.get?b[h].get(i)||i:b[h][i]||i):(k(i)&&(c.get("numberFormatter")?i=c.get("numberFormatter")(i):i=p(i,j,c.get("numberDigitGroupCount"),c.get("numberDigitGroupSep"),c.get("numberDecimalMark"))),i)})}}),a.spformat=function(a,b){return new e(a,b)},f=function(a,b,c){return a<b?b:a>c?c:a},g=function(a,b){var c;return b===2?(c=Math.floor(a.length/2),a.length%2?a[c]:(a[c]+a[c+1])/2):(c=Math.floor(a.length/4),a.length%2?(a[c*b]+a[c*b+1])/2:a[c*b])},h=function(a){var b;switch(a){case"undefined":a=undefined;break;case"null":a=null;break;case"true":a=!0;break;case"false":a=!1;break;default:b=parseFloat(a),a==b&&(a=b)}return a},i=function(a){var b,c=[];for(b=a.length;b--;)c[b]=h(a[b]);return c},j=function(a,b){var c,d,e=[];for(c=0,d=a.length;c<d;c++)a[c]!==b&&e.push(a[c]);return e},k=function(a){retur
n!isNaN(parseFloat(a))&&isFinite(a)},p=function(b,c,d,e,f){var g,h;b=(c===!1?parseFloat(b).toString():b.toFixed(c)).split(""),g=(g=a.inArray(".",b))<0?b.length:g,g<b.length&&(b[g]=f);for(h=g-d;h>0;h-=d)b.splice(h,0,e);return b.join("")},l=function(a,b,c){var d;for(d=b.length;d--;)if(b[d]!==a||!c&&a===null)return!1;return!0},m=function(a){var b=0,c;for(c=a.length;c--;)b+=typeof a[c]=="number"?a[c]:0;return b},o=function(b){return a.isArray(b)?b:[b]},n=function(a){var b;document.createStyleSheet?document.createStyleSheet().cssText=a:(b=document.createElement("style"),b.type="text/css",document.getElementsByTagName("head")[0].appendChild(b),b[typeof document.body.style.WebkitAppearance=="string"?"innerText":"innerHTML"]=a)},a.fn.simpledraw=function(b,c,d,e){var f,g;if(d&&(f=this.data("_jqs_vcanvas")))return f;b===undefined&&(b=a(this).innerWidth()),c===undefined&&(c=a(this).innerHeight());if(a.browser.hasCanvas)f=new F(b,c,this,e);else{if(!a.browser.msie)return!1;f=new G(b,c,th
is)}return g=a(this).data("_jqs_mhandler"),g&&g.registerCanvas(f),f},a.fn.cleardraw=function(){var a=this.data("_jqs_vcanvas");a&&a.reset()},a.RangeMapClass=q=d({init:function(a){var b,c,d=[];for(b in a)a.hasOwnProperty(b)&&typeof b=="string"&&b.indexOf(":")>-1&&(c=b.split(":"),c[0]=c[0].length===0?-Infinity:parseFloat(c[0]),c[1]=c[1].length===0?Infinity:parseFloat(c[1]),c[2]=a[b],d.push(c));this.map=a,this.rangelist=d||!1},get:function(a){var b=this.rangelist,c,d,e;if((e=this.map[a])!==undefined)return e;if(b)for(c=b.length;c--;){d=b[c];if(d[0]<=a&&d[1]>=a)return d[2]}return undefined}}),a.range_map=function(a){return new q(a)},r=d({init:function(b,c){var d=a(b);this.$el=d,this.options=c,this.currentPageX=0,this.currentPageY=0,this.el=b,this.splist=[],this.tooltip=null,this.over=!1,this.displayTooltips=!c.get("disableTooltips"),this.highlightEnabled=!c.get("disableHighlight")},registerSparkline:function(a){this.splist.push(a),this.over&&this.updateDisplay()},registerCanvas:
function(b){var c=a(b.canvas);this.canvas=b,this.$canvas=c,c.mouseenter(a.proxy(this.mouseenter,this)),c.mouseleave(a.proxy(this.mouseleave,this)),c.click(a.proxy(this.mouseclick,this))},reset:function(a){this.splist=[],this.tooltip&&a&&(this.tooltip.remove(),this.tooltip=undefined)},mouseclick:function(b){var c=a.Event("sparklineClick");c.originalEvent=b,c.sparklines=this.splist,this.$el.trigger(c)},mouseenter:function(b){a(document.body).unbind("mousemove.jqs"),a(document.body).bind("mousemove.jqs",a.proxy(this.mousemove,this)),this.over=!0,this.currentPageX=b.pageX,this.currentPageY=b.pageY,this.currentEl=b.target,!this.tooltip&&this.displayTooltips&&(this.tooltip=new s(this.options),this.tooltip.updatePosition(b.pageX,b.pageY)),this.updateDisplay()},mouseleave:function(){a(document.body).unbind("mousemove.jqs");var b=this.splist,c=b.length,d=!1,e,f;this.over=!1,this.currentEl=null,this.tooltip&&(this.tooltip.remove(),this.tooltip=null);for(f=0;f<c;f++)e=b[f],e.clearRegio
nHighlight()&&(d=!0);d&&this.canvas.render()},mousemove:function(a){this.currentPageX=a.pageX,this.currentPageY=a.pageY,this.currentEl=a.target,this.tooltip&&this.tooltip.updatePosition(a.pageX,a.pageY),this.updateDisplay()},updateDisplay:function(){var b=this.splist,c=b.length,d=!1,e=this.$canvas.offset(),f=this.currentPageX-e.left,g=this.currentPageY-e.top,h,i,j,k,l;if(!this.over)return;for(j=0;j<c;j++)i=b[j],k=i.setRegionHighlight(this.currentEl,f,g),k&&(d=!0);if(d){l=a.Event("sparklineRegionChange"),l.sparklines=this.splist,this.$el.trigger(l);if(this.tooltip){h="";for(j=0;j<c;j++)i=b[j],h+=i.getCurrentRegionTooltip();this.tooltip.setContent(h)}this.disableHighlight||this.canvas.render()}k===null&&this.mouseleave()}}),s=d({sizeStyle:"position: static !important;display: block !important;visibility: hidden !important;float: left !important;",init:function(b){var c=b.get("tooltipClassname","jqstooltip"),d=this.sizeStyle,e;this.container=b.get("tooltipContainer")||document.
body,this.tooltipOffsetX=b.get("tooltipOffsetX",10),this.tooltipOffsetY=b.get("tooltipOffsetY",12),a("#jqssizetip").remove(),a("#jqstooltip").remove(),this.sizetip=a("<div/>",{id:"jqssizetip",style:d,"class":c}),this.tooltip=a("<div/>",{id:"jqstooltip","class":c}).appendTo(this.container),e=this.tooltip.offset(),this.offsetLeft=e.left,this.offsetTop=e.top,this.hidden=!0,a(window).unbind("resize.jqs scroll.jqs"),a(window).bind("resize.jqs scroll.jqs",a.proxy(this.updateWindowDims,this)),this.updateWindowDims()},updateWindowDims:function(){this.scrollTop=a(window).scrollTop(),this.scrollLeft=a(window).scrollLeft(),this.scrollRight=this.scrollLeft+a(window).width(),this.updatePosition()},getSize:function(a){this.sizetip.html(a).appendTo(this.container),this.width=this.sizetip.width()+1,this.height=this.sizetip.height(),this.sizetip.remove()},setContent:function(a){if(!a){this.tooltip.css("visibility","hidden"),this.hidden=!0;return}this.getSize(a),this.tooltip.html(a).css({widt
h:this.width,height:this.height,visibility:"visible"}),this.hidden&&(this.hidden=!1,this.updatePosition())},updatePosition:function(a,b){if(a===undefined){if(this.mousex===undefined)return;a=this.mousex-this.offsetLeft,b=this.mousey-this.offsetTop}else this.mousex=a-=this.offsetLeft,this.mousey=b-=this.offsetTop;if(!this.height||!this.width||this.hidden)return;b-=this.height+this.tooltipOffsetY,a+=this.tooltipOffsetX,b<this.scrollTop&&(b=this.scrollTop),a<this.scrollLeft?a=this.scrollLeft:a+this.width>this.scrollRight&&(a=this.scrollRight-this.width),this.tooltip.css({left:a,top:b})},remove:function(){this.tooltip.remove(),this.sizetip.remove(),this.sizetip=this.tooltip=undefined,a(window).unbind("resize.jqs scroll.jqs")}}),H=[],a.fn.sparkline=function(b,c){return this.each(function(){var d=new a.fn.sparkline.options(this,c),e=a(this),f,g;f=function(){var c,f,g,h,i,j,k;if(b==="html"||b===undefined){k=this.getAttribute(d.get("tagValuesAttribute"));if(k===undefined||k===null)k
=e.html();c=k.replace(/(^\s*<!--)|(-->\s*$)|\s+/g,"").split(",")}else c=b;f=d.get("width")==="auto"?c.length*d.get("defaultPixelsPerValue"):d.get("width");if(d.get("height")==="auto"){if(!d.get("composite")||!a.data(this,"_jqs_vcanvas"))h=document.createElement("span"),h.innerHTML="a",e.html(h),g=a(h).innerHeight()||a(h).height(),a(h).remove(),h=null}else g=d.get("height");d.get("disableInteraction")?i=!1:(i=a.data(this,"_jqs_mhandler"),i?d.get("composite")||i.reset():(i=new r(this,d),a.data(this,"_jqs_mhandler",i)));if(d.get("composite")&&!a.data(this,"_jqs_vcanvas")){a.data(this,"_jqs_errnotify")||(alert("Attempted to attach a composite sparkline to an element with no existing sparkline"),a.data(this,"_jqs_errnotify",!0));return}j=new(a.fn.sparkline[d.get("type")])(this,c,d,f,g),j.render(),i&&i.registerSparkline(j)};if(a(this).html()&&!d.get("disableHiddenCheck")&&a(this).is(":hidden")||a.fn.jquery<"1.3.0"&&a(this).parents().is(":hidden")||!a(this).parents("body").length){
if(!d.get("composite")&&a.data(this,"_jqs_pending"))for(g=H.length;g;g--)H[g-1][0]==this&&H.splice(g-1,1);H.push([this,f]),a.data(this,"_jqs_pending",!0)}else f.call(this)})},a.fn.sparkline.defaults=c(),a.sparkline_display_visible=function(){var b,c,d,e=[];for(c=0,d=H.length;c<d;c++)b=H[c][0],a(b).is(":visible")&&!a(b).parents().is(":hidden")?(H[c][1].call(b),a.data(H[c][0],"_jqs_pending",!1),e.push(c)):!a(b).closest("html").length&&!a.data(b,"_jqs_pending")&&(a.data(H[c][0],"_jqs_pending",!1),e.push(c));for(c=e.length;c;c--)H.splice(e[c-1],1)},a.fn.sparkline.options=d({init:function(c,d){var e,f,g,h;this.userOptions=d=d||{},this.tag=c,this.tagValCache={},f=a.fn.sparkline.defaults,g=f.common,this.tagOptionsPrefix=d.enableTagOptions&&(d.tagOptionsPrefix||g.tagOptionsPrefix),h=this.getTagSetting("type"),h===b?e=f[d.type||g.type]:e=f[h],this.mergedOptions=a.extend({},g,e,d)},getTagSetting:function(a){var c=this.tagOptionsPrefix,d,e,f,g;if(c===!1||c===undefined)return b;if(this.
tagValCache.hasOwnProperty(a))d=this.tagValCache.key;else{d=this.tag.getAttribute(c+a);if(d===undefined||d===null)d=b;else if(d.substr(0,1)==="["){d=d.substr(1,d.length-2).split(",");for(e=d.length;e--;)d[e]=h(d[e].replace(/(^\s*)|(\s*$)/g,""))}else if(d.substr(0,1)==="{"){f=d.substr(1,d.length-2).split(","),d={};for(e=f.length;e--;)g=f[e].split(":",2),d[g[0].replace(/(^\s*)|(\s*$)/g,"")]=h(g[1].replace(/(^\s*)|(\s*$)/g,""))}else d=h(d);this.tagValCache.key=d}return d},get:function(a,c){var d=this.getTagSetting(a),e;return d!==b?d:(e=this.mergedOptions[a])===undefined?c:e}}),a.fn.sparkline._base=d({disabled:!1,init:function(b,c,d,e,f){this.el=b,this.$el=a(b),this.values=c,this.options=d,this.width=e,this.height=f,this.currentRegion=undefined},initTarget:function(){var a=!this.options.get("disableInteraction");(this.target=this.$el.simpledraw(this.width,this.height,this.options.get("composite"),a))?(this.canvasWidth=this.target.pixelWidth,this.canvasHeight=this.target.pixelHe
ight):this.disabled=!0},render:function(){return this.disabled?(this.el.innerHTML="",!1):!0},getRegion:function(a,b){},setRegionHighlight:function(a,b,c){var d=this.currentRegion,e=!this.options.get("disableHighlight"),f;return b>this.canvasWidth||c>this.canvasHeight||b<0||c<0?null:(f=this.getRegion(a,b,c),d!==f?(d!==undefined&&e&&this.removeHighlight(),this.currentRegion=f,f!==undefined&&e&&this.renderHighlight(),!0):!1)},clearRegionHighlight:function(){return this.currentRegion!==undefined?(this.removeHighlight(),this.currentRegion=undefined,!0):!1},renderHighlight:function(){this.changeHighlight(!0)},removeHighlight:function(){this.changeHighlight(!1)},changeHighlight:function(a){},getCurrentRegionTooltip:function(){var b=this.options,c="",d=[],f,g,h,i,j,k,l,m,n,o,p,q,r,s;if(this.currentRegion===undefined)return"";f=this.getCurrentRegionFields(),p=b.get("tooltipFormatter");if(p)return p(this,b,f);b.get("tooltipChartTitle")&&(c+='<div class="jqs jqstitle">'+b.get("tooltipC
hartTitle")+"</div>\n"),g=this.options.get("tooltipFormat");if(!g)return"";a.isArray(g)||(g=[g]),a.isArray(f)||(f=[f]),l=this.options.get("tooltipFormatFieldlist"),m=this.options.get("tooltipFormatFieldlistKey");if(l&&m){n=[];for(k=f.length;k--;)o=f[k][m],(s=a.inArray(o,l))!=-1&&(n[s]=f[k]);f=n}h=g.length,r=f.length;for(k=0;k<h;k++){q=g[k],typeof q=="string"&&(q=new e(q)),i=q.fclass||"jqsfield";for(s=0;s<r;s++)if(!f[s].isNull||!b.get("tooltipSkipNull"))a.extend(f[s],{prefix:b.get("tooltipPrefix"),suffix:b.get("tooltipSuffix")}),j=q.render(f[s],b.get("tooltipValueLookups"),b),d.push('<div class="'+i+'">'+j+"</div>")}return d.length?c+d.join("\n"):""},getCurrentRegionFields:function(){},calcHighlightColor:function(a,b){var c=b.get("highlightColor"),d=b.get("highlightLighten"),e,g,h,i;if(c)return c;if(d){e=/^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(a)||/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(a);if(e){h=[],g=a.length===4?16:1;for(i=0;i<3;i++)h[i]=f(Math.round(parseInt(
e[i+1],16)*g*d),0,255);return"rgb("+h.join(",")+")"}}return a}}),t={changeHighlight:function(b){var c=this.currentRegion,d=this.target,e=this.regionShapes[c],f;e&&(f=this.renderRegion(c,b),a.isArray(f)||a.isArray(e)?(d.replaceWithShapes(e,f),this.regionShapes[c]=a.map(f,function(a){return a.id})):(d.replaceWithShape(e,f),this.regionShapes[c]=f.id))},render:function(){var b=this.values,c=this.target,d=this.regionShapes,e,f,g,h;if(!this.cls._super.render.call(this))return;for(g=b.length;g--;){e=this.renderRegion(g);if(e)if(a.isArray(e)){f=[];for(h=e.length;h--;)e[h].append(),f.push(e[h].id);d[g]=f}else e.append(),d[g]=e.id;else d[g]=null}c.render()}},a.fn.sparkline.line=u=d(a.fn.sparkline._base,{type:"line",init:function(a,b,c,d,e){u._super.init.call(this,a,b,c,d,e),this.vertices=[],this.regionMap=[],this.xvalues=[],this.yvalues=[],this.yminmax=[],this.hightlightSpotId=null,this.lastShapeId=null,this.initTarget()},getRegion:function(a,b,c){var d,e=this.regionMap;for(d=e.length
;d--;)if(e[d]!==null&&b>=e[d][0]&&b<=e[d][1])return e[d][2];return undefined},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.yvalues[a]===null,x:this.xvalues[a],y:this.yvalues[a],color:this.options.get("lineColor"),fillColor:this.options.get("fillColor"),offset:a}},renderHighlight:function(){var a=this.currentRegion,b=this.target,c=this.vertices[a],d=this.options,e=d.get("spotRadius"),f=d.get("highlightSpotColor"),g=d.get("highlightLineColor"),h,i;if(!c)return;e&&f&&(h=b.drawCircle(c[0],c[1],e,undefined,f),this.highlightSpotId=h.id,b.insertAfterShape(this.lastShapeId,h)),g&&(i=b.drawLine(c[0],this.canvasTop,c[0],this.canvasTop+this.canvasHeight,g),this.highlightLineId=i.id,b.insertAfterShape(this.lastShapeId,i))},removeHighlight:function(){var a=this.target;this.highlightSpotId&&(a.removeShapeId(this.highlightSpotId),this.highlightSpotId=null),this.highlightLineId&&(a.removeShapeId(this.highlightLineId),this.highlightLineId=null)},scanValues:fu
nction(){var a=this.values,b=a.length,c=this.xvalues,d=this.yvalues,e=this.yminmax,f,g,h,i,j;for(f=0;f<b;f++)g=a[f],h=typeof a[f]=="string",i=typeof a[f]=="object"&&a[f]instanceof Array,j=h&&a[f].split(":"),h&&j.length===2?(c.push(Number(j[0])),d.push(Number(j[1])),e.push(Number(j[1]))):i?(c.push(g[0]),d.push(g[1]),e.push(g[1])):(c.push(f),a[f]===null||a[f]==="null"?d.push(null):(d.push(Number(g)),e.push(Number(g))));this.options.get("xvalues")&&(c=this.options.get("xvalues")),this.maxy=this.maxyorg=Math.max.apply(Math,e),this.miny=this.minyorg=Math.min.apply(Math,e),this.maxx=Math.max.apply(Math,c),this.minx=Math.min.apply(Math,c),this.xvalues=c,this.yvalues=d,this.yminmax=e},processRangeOptions:function(){var a=this.options,b=a.get("normalRangeMin"),c=a.get("normalRangeMax");b!==undefined&&(b<this.miny&&(this.miny=b),c>this.maxy&&(this.maxy=c)),a.get("chartRangeMin")!==undefined&&(a.get("chartRangeClip")||a.get("chartRangeMin")<this.miny)&&(this.miny=a.get("chartRangeMin")
),a.get("chartRangeMax")!==undefined&&(a.get("chartRangeClip")||a.get("chartRangeMax")>this.maxy)&&(this.maxy=a.get("chartRangeMax")),a.get("chartRangeMinX")!==undefined&&(a.get("chartRangeClipX")||a.get("chartRangeMinX")<this.minx)&&(this.minx=a.get("chartRangeMinX")),a.get("chartRangeMaxX")!==undefined&&(a.get("chartRangeClipX")||a.get("chartRangeMaxX")>this.maxx)&&(this.maxx=a.get("chartRangeMaxX"))},drawNormalRange:function(a,b,c,d,e){var f=this.options.get("normalRangeMin"),g=this.options.get("normalRangeMax"),h=b+Math.round(c-c*((g-this.miny)/e)),i=Math.round(c*(g-f)/e);this.target.drawRect(a,h,d,i,undefined,this.options.get("normalRangeColor")).append()},render:function(){var b=this.options,c=this.target,d=this.canvasWidth,e=this.canvasHeight,f=this.vertices,g=b.get("spotRadius"),h=this.regionMap,i,j,k,l,m,n,o,p,r,s,t,v,w,x,y,z,A,B,C,D,E,F,G,H;if(!u._super.render.call(this))return;this.scanValues(),this.processRangeOptions(),F=this.xvalues,G=this.yvalues;if(!this.ymin
max.length||this.yvalues.length<2)return;l=m=0,i=this.maxx-this.minx===0?1:this.maxx-this.minx,j=this.maxy-this.miny===0?1:this.maxy-this.miny,k=this.yvalues.length-1,g&&(d<g*4||e<g*4)&&(g=0);if(g){if(b.get("minSpotColor")||b.get("spotColor")&&G[k]===this.miny)e-=Math.ceil(g);if(b.get("maxSpotColor")||b.get("spotColor")&&G[k]===this.maxy)e-=Math.ceil(g),l+=Math.ceil(g);(b.get("minSpotColor")||b.get("maxSpotColor"))&&(G[0]===this.miny||G[0]===this.maxy)&&(m+=Math.ceil(g),d-=Math.ceil(g));if(b.get("spotColor")||b.get("minSpotColor")||b.get("maxSpotColor")&&(G[k]===this.miny||G[k]===this.maxy))d-=Math.ceil(g)}e--,b.get("normalRangeMin")&&!b.get("drawNormalOnTop")&&this.drawNormalRange(m,l,e,d,j),o=[],p=[o],x=y=null,z=G.length;for(H=0;H<z;H++)r=F[H],t=F[H+1],s=G[H],v=m+Math.round((r-this.minx)*(d/i)),w=H<z-1?m+Math.round((t-this.minx)*(d/i)):d,y=v+(w-v)/2,h[H]=[x||0,y,H],x=y,s===null?H&&G[H-1]!==null&&(o=[],p.push(o),f.push(null)):(s<this.miny&&(s=this.miny),s>this.maxy&&(s=this
.maxy),o.length||o.push([v,l+e]),n=[v,l+Math.round(e-e*((s-this.miny)/j))],o.push(n),f.push(n));A=[],B=[],C=p.length;for(H=0;H<C;H++)o=p[H],o.length&&(b.get("fillColor")&&(o.push([o[o.length-1][0],l+e]),B.push(o.slice(0)),o.pop()),o.length>2&&(o[0]=[o[0][0],o[1][1]]),A.push(o));C=B.length;for(H=0;H<C;H++)c.drawShape(B[H],b.get("fillColor"),b.get("fillColor")).append();b.get("normalRangeMin")&&b.get("drawNormalOnTop")&&this.drawNormalRange(m,l,e,d,j),C=A.length;for(H=0;H<C;H++)c.drawShape(A[H],b.get("lineColor"),undefined,b.get("lineWidth")).append();if(g&&b.get("valueSpots")){D=b.get("valueSpots"),D.get===undefined&&(D=new q(D));for(H=0;H<z;H++)E=D.get(G[H]),E&&c.drawCircle(m+Math.round((F[H]-this.minx)*(d/i)),l+Math.round(e-e*((G[H]-this.miny)/j)),g,undefined,E).append()}g&&b.get("spotColor")&&c.drawCircle(m+Math.round((F[F.length-1]-this.minx)*(d/i)),l+Math.round(e-e*((G[k]-this.miny)/j)),g,undefined,b.get("spotColor")).append(),this.maxy!==this.minyorg&&(g&&b.get("minSpot
Color")&&(r=F[a.inArray(this.minyorg,G)],c.drawCircle(m+Math.round((r-this.minx)*(d/i)),l+Math.round(e-e*((this.minyorg-this.miny)/j)),g,undefined,b.get("minSpotColor")).append()),g&&b.get("maxSpotColor")&&(r=F[a.inArray(this.maxyorg,G)],c.drawCircle(m+Math.round((r-this.minx)*(d/i)),l+Math.round(e-e*((this.maxyorg-this.miny)/j)),g,undefined,b.get("maxSpotColor")).append())),this.lastShapeId=c.getLastShapeId(),this.canvasTop=l,c.render()}}),a.fn.sparkline.bar=v=d(a.fn.sparkline._base,t,{type:"bar",init:function(b,c,d,e,g){var k=parseInt(d.get("barWidth"),10),l=parseInt(d.get("barSpacing"),10),m=d.get("chartRangeMin"),n=d.get("chartRangeMax"),o=d.get("chartRangeClip"),p=Infinity,r=-Infinity,s,t,u,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P;v._super.init.call(this,b,c,d,e,g);for(y=0,z=c.length;y<z;y++){M=c[y],s=typeof M=="string"&&M.indexOf(":")>-1;if(s||a.isArray(M))H=!0,s&&(M=c[y]=i(M.split(":"))),M=j(M,null),t=Math.min.apply(Math,M),u=Math.max.apply(Math,M),t<p&&(p=t),u>r&&(r=u
)}this.stacked=H,this.regionShapes={},this.barWidth=k,this.barSpacing=l,this.totalBarWidth=k+l,this.width=e=c.length*k+(c.length-1)*l,this.initTarget(),o&&(F=m===undefined?-Infinity:m,G=n===undefined?Infinity:n),x=[],w=H?[]:x;var Q=[],R=[];for(y=0,z=c.length;y<z;y++)if(H){I=c[y],c[y]=L=[],Q[y]=0,w[y]=R[y]=0;for(J=0,K=I.length;J<K;J++)M=L[J]=o?f(I[J],F,G):I[J],M!==null&&(M>0&&(Q[y]+=M),p<0&&r>0?M<0?R[y]+=Math.abs(M):w[y]+=M:w[y]+=Math.abs(M-(M<0?r:p)),x.push(M))}else M=o?f(c[y],F,G):c[y],M=c[y]=h(M),M!==null&&x.push(M);this.max=E=Math.max.apply(Math,x),this.min=D=Math.min.apply(Math,x),this.stackMax=r=H?Math.max.apply(Math,Q):E,this.stackMin=p=H?Math.min.apply(Math,x):D,d.get("chartRangeMin")!==undefined&&(d.get("chartRangeClip")||d.get("chartRangeMin")<D)&&(D=d.get("chartRangeMin")),d.get("chartRangeMax")!==undefined&&(d.get("chartRangeClip")||d.get("chartRangeMax")>E)&&(E=d.get("chartRangeMax")),this.zeroAxis=B=d.get("zeroAxis",!0),D<=0&&E>=0&&B?C=0:B==0?C=D:D>0?C=D:C=E,thi
s.xaxisOffset=C,A=H?Math.max.apply(Math,w)+Math.max.apply(Math,R):E-D,this.canvasHeightEf=B&&D<0?this.canvasHeight-2:this.canvasHeight-1,D<C?(O=H&&E>=0?r:E,N=(O-C)/A*this.canvasHeight,N!==Math.ceil(N)&&(this.canvasHeightEf-=2,N=Math.ceil(N))):N=this.canvasHeight,this.yoffset=N,a.isArray(d.get("colorMap"))?(this.colorMapByIndex=d.get("colorMap"),this.colorMapByValue=null):(this.colorMapByIndex=null,this.colorMapByValue=d.get("colorMap"),this.colorMapByValue&&this.colorMapByValue.get===undefined&&(this.colorMapByValue=new q(this.colorMapByValue))),this.range=A},getRegion:function(a,b,c){var d=Math.floor(b/this.totalBarWidth);return d<0||d>=this.values.length?undefined:d},getCurrentRegionFields:function(){var a=this.currentRegion,b=o(this.values[a]),c=[],d,e;for(e=b.length;e--;)d=b[e],c.push({isNull:d===null,value:d,color:this.calcColor(e,d,a),offset:a});return c},calcColor:function(b,c,d){var e=this.colorMapByIndex,f=this.colorMapByValue,g=this.options,h,i;return this.stacked?
h=g.get("stackedBarColor"):h=c<0?g.get("negBarColor"):g.get("barColor"),c===0&&g.get("zeroColor")!==undefined&&(h=g.get("zeroColor")),f&&(i=f.get(c))?h=i:e&&e.length>d&&(h=e[d]),a.isArray(h)?h[b%h.length]:h},renderRegion:function(b,c){var d=this.values[b],e=this.options,f=this.xaxisOffset,g=[],h=this.range,i=this.stacked,j=this.target,k=b*this.totalBarWidth,m=this.canvasHeightEf,n=this.yoffset,o,p,q,r,s,t,u,v,w,x;d=a.isArray(d)?d:[d],u=d.length,v=d[0],r=l(null,d),x=l(f,d,!0);if(r)return e.get("nullColor")?(q=c?e.get("nullColor"):this.calcHighlightColor(e.get("nullColor"),e),o=n>0?n-1:n,j.drawRect(k,o,this.barWidth-1,0,q,q)):undefined;s=n;for(t=0;t<u;t++){v=d[t];if(i&&v===f){if(!x||w)continue;w=!0}h>0?p=Math.floor(m*(Math.abs(v-f)/h))+1:p=1,v<f||v===f&&n===0?(o=s,s+=p):(o=n-p,n-=p),q=this.calcColor(t,v,b),c&&(q=this.calcHighlightColor(q,e)),g.push(j.drawRect(k,o,this.barWidth-1,p-1,q,q))}return g.length===1?g[0]:g}}),a.fn.sparkline.tristate=w=d(a.fn.sparkline._base,t,{type:"t
ristate",init:function(b,c,d,e,f){var g=parseInt(d.get("barWidth"),10),h=parseInt(d.get("barSpacing"),10);w._super.init.call(this,b,c,d,e,f),this.regionShapes={},this.barWidth=g,this.barSpacing=h,this.totalBarWidth=g+h,this.values=a.map(c,Number),this.width=e=c.length*g+(c.length-1)*h,a.isArray(d.get("colorMap"))?(this.colorMapByIndex=d.get("colorMap"),this.colorMapByValue=null):(this.colorMapByIndex=null,this.colorMapByValue=d.get("colorMap"),this.colorMapByValue&&this.colorMapByValue.get===undefined&&(this.colorMapByValue=new q(this.colorMapByValue))),this.initTarget()},getRegion:function(a,b,c){return Math.floor(b/this.totalBarWidth)},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===undefined,value:this.values[a],color:this.calcColor(this.values[a],a),offset:a}},calcColor:function(a,b){var c=this.values,d=this.options,e=this.colorMapByIndex,f=this.colorMapByValue,g,h;return f&&(h=f.get(a))?g=h:e&&e.length>b?g=e[b]:c[b]<0?g=d.get("n
egBarColor"):c[b]>0?g=d.get("posBarColor"):g=d.get("zeroBarColor"),g},renderRegion:function(a,b){var c=this.values,d=this.options,e=this.target,f,g,h,i,j,k;f=e.pixelHeight,h=Math.round(f/2),i=a*this.totalBarWidth,c[a]<0?(j=h,g=h-1):c[a]>0?(j=0,g=h-1):(j=h-1,g=2),k=this.calcColor(c[a],a);if(k===null)return;return b&&(k=this.calcHighlightColor(k,d)),e.drawRect(i,j,this.barWidth-1,g-1,k,k)}}),a.fn.sparkline.discrete=x=d(a.fn.sparkline._base,t,{type:"discrete",init:function(b,c,d,e,f){x._super.init.call(this,b,c,d,e,f),this.regionShapes={},this.values=c=a.map(c,Number),this.min=Math.min.apply(Math,c),this.max=Math.max.apply(Math,c),this.range=this.max-this.min,this.width=e=d.get("width")==="auto"?c.length*2:this.width,this.interval=Math.floor(e/c.length),this.itemWidth=e/c.length,d.get("chartRangeMin")!==undefined&&(d.get("chartRangeClip")||d.get("chartRangeMin")<this.min)&&(this.min=d.get("chartRangeMin")),d.get("chartRangeMax")!==undefined&&(d.get("chartRangeClip")||d.get("cha
rtRangeMax")>this.max)&&(this.max=d.get("chartRangeMax")),this.initTarget(),this.target&&(this.lineHeight=d.get("lineHeight")==="auto"?Math.round(this.canvasHeight*.3):d.get("lineHeight"))},getRegion:function(a,b,c){return Math.floor(b/this.itemWidth)},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===undefined,value:this.values[a],offset:a}},renderRegion:function(a,b){var c=this.values,d=this.options,e=this.min,g=this.max,h=this.range,i=this.interval,j=this.target,k=this.canvasHeight,l=this.lineHeight,m=k-l,n,o,p,q;return o=f(c[a],e,g),q=a*i,n=Math.round(m-m*((o-e)/h)),p=d.get("thresholdColor")&&o<d.get("thresholdValue")?d.get("thresholdColor"):d.get("lineColor"),b&&(p=this.calcHighlightColor(p,d)),j.drawLine(q,n,q,n+l,p)}}),a.fn.sparkline.bullet=y=d(a.fn.sparkline._base,{type:"bullet",init:function(b,c,d,e,f){var g,h;y._super.init.call(this,b,c,d,e,f),c=a.map(c,Number),g=Math.min.apply(Math,c),h=Math.max.apply(Math,c),d.get("base")==
=undefined?g=g<0?g:0:g=d.get("base"),this.min=g,this.max=h,this.range=h-g,this.shapes={},this.valueShapes={},this.regiondata={},this.width=e=d.get("width")==="auto"?"4.0em":e,this.target=this.$el.simpledraw(e,f,d.get("composite")),c.length||(this.disabled=!0),this.initTarget()},getRegion:function(a,b,c){var d=this.target.getShapeAt(a,b,c);return d!==undefined&&this.shapes[d]!==undefined?this.shapes[d]:undefined},getCurrentRegionFields:function(){var a=this.currentRegion;return{fieldkey:a.substr(0,1),value:this.values[a.substr(1)],region:a}},changeHighlight:function(a){var b=this.currentRegion,c=this.valueShapes[b],d;delete this.shapes[c];switch(b.substr(0,1)){case"r":d=this.renderRange(b.substr(1),a);break;case"p":d=this.renderPerformance(a);break;case"t":d=this.renderTarget(a)}this.valueShapes[b]=d.id,this.shapes[d.id]=b,this.target.replaceWithShape(c,d)},renderRange:function(a,b){var c=this.values[a],d=Math.round(this.canvasWidth*((c-this.min)/this.range)),e=this.options.g
et("rangeColors")[a-2];return b&&(e=this.calcHighlightColor(e,this.options)),this.target.drawRect(0,0,d-1,this.canvasHeight-1,e,e)},renderPerformance:function(a){var b=this.values[1],c=Math.round(this.canvasWidth*((b-this.min)/this.range)),d=this.options.get("performanceColor");return a&&(d=this.calcHighlightColor(d,this.options)),this.target.drawRect(0,Math.round(this.canvasHeight*.3),c-1,Math.round(this.canvasHeight*.4)-1,d,d)},renderTarget:function(a){var b=this.values[0],c=Math.round(this.canvasWidth*((b-this.min)/this.range)-this.options.get("targetWidth")/2),d=Math.round(this.canvasHeight*.1),e=this.canvasHeight-d*2,f=this.options.get("targetColor");return a&&(f=this.calcHighlightColor(f,this.options)),this.target.drawRect(c,d,this.options.get("targetWidth")-1,e-1,f,f)},render:function(){var a=this.values.length,b=this.target,c,d;if(!y._super.render.call(this))return;for(c=2;c<a;c++)d=this.renderRange(c).append(),this.shapes[d.id]="r"+c,this.valueShapes["r"+c]=d.id;d=t
his.renderPerformance().append(),this.shapes[d.id]="p1",this.valueShapes.p1=d.id,d=this.renderTarget().append(),this.shapes[d.id]="t0",this.valueShapes.t0=d.id,b.render()}}),a.fn.sparkline.pie=z=d(a.fn.sparkline._base,{type:"pie",init:function(b,c,d,e,f){var g=0,h;z._super.init.call(this,b,c,d,e,f),this.shapes={},this.valueShapes={},this.values=c=a.map(c,Number),d.get("width")==="auto"&&(this.width=this.height);if(c.length>0)for(h=c.length;h--;)g+=c[h];this.total=g,this.initTarget(),this.radius=Math.floor(Math.min(this.canvasWidth,this.canvasHeight)/2)},getRegion:function(a,b,c){var d=this.target.getShapeAt(a,b,c);return d!==undefined&&this.shapes[d]!==undefined?this.shapes[d]:undefined},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===undefined,value:this.values[a],percent:this.values[a]/this.total*100,color:this.options.get("sliceColors")[a%this.options.get("sliceColors").length],offset:a}},changeHighlight:function(a){var b=this.cur
rentRegion,c=this.renderSlice(b,a),d=this.valueShapes[b];delete this.shapes[d],this.target.replaceWithShape(d,c),this.valueShapes[b]=c.id,this.shapes[c.id]=b},renderSlice:function(a,b){var c=this.target,d=this.options,e=this.radius,f=d.get("borderWidth"),g=d.get("offset"),h=2*Math.PI,i=this.values,j=this.total,k=g?2*Math.PI*(g/360):0,l,m,n,o,p;o=i.length;for(n=0;n<o;n++){l=k,m=k,j>0&&(m=k+h*(i[n]/j));if(a===n)return p=d.get("sliceColors")[n%d.get("sliceColors").length],b&&(p=this.calcHighlightColor(p,d)),c.drawPieSlice(e,e,e-f,l,m,undefined,p);k=m}},render:function(){var a=this.target,b=this.values,c=this.options,d=this.radius,e=c.get("borderWidth"),f,g;if(!z._super.render.call(this))return;e&&a.drawCircle(d,d,Math.floor(d-e/2),c.get("borderColor"),undefined,e).append();for(g=b.length;g--;)f=this.renderSlice(g).append(),this.valueShapes[g]=f.id,this.shapes[f.id]=g;a.render()}}),a.fn.sparkline.box=A=d(a.fn.sparkline._base,{type:"box",init:function(b,c,d,e,f){A._super.init.cal
l(this,b,c,d,e,f),this.values=a.map(c,Number),this.width=d.get("width")==="auto"?"4.0em":e,this.initTarget(),this.values.length||(this
+.disabled=1)},getRegion:function(){return 1},getCurrentRegionFields:function(){var a=[{field:"lq",value:this.quartiles[0]},{field:"med",value:this.quartiles[1]},{field:"uq",value:this.quartiles[2]},{field:"lo",value:this.loutlier},{field:"ro",value:this.routlier}];return this.lwhisker!==undefined&&a.push({field:"lw",value:this.lwhisker}),this.rwhisker!==undefined&&a.push({field:"rw",value:this.rwhisker}),a},render:function(){var a=this.target,b=this.values,c=b.length,d=this.options,e=this.canvasWidth,f=this.canvasHeight,h=d.get("chartRangeMin")===undefined?Math.min.apply(Math,b):d.get("chartRangeMin"),i=d.get("chartRangeMax")===undefined?Math.max.apply(Math,b):d.get("chartRangeMax"),j=0,k,l,m,n,o,p,q,r,s,t,u;if(!A._super.render.call(this))return;if(d.get("raw"))d.get("showOutliers")&&b.length>5?(l=b[0],k=b[1],n=b[2],o=b[3],p=b[4],q=b[5],r=b[6]):(k=b[0],n=b[1],o=b[2],p=b[3],q=b[4]);else{b.sort(function(a,b){return a-b}),n=g(b,1),o=g(b,2),p=g(b,3),m=p-n;if(d.get("showOutliers"
)){k=q=undefined;for(s=0;s<c;s++)k===undefined&&b[s]>n-m*d.get("outlierIQR")&&(k=b[s]),b[s]<p+m*d.get("outlierIQR")&&(q=b[s]);l=b[0],r=b[c-1]}else k=b[0],q=b[c-1]}this.quartiles=[n,o,p],this.lwhisker=k,this.rwhisker=q,this.loutlier=l,this.routlier=r,u=e/(i-h+1),d.get("showOutliers")&&(j=Math.ceil(d.get("spotRadius")),e-=2*Math.ceil(d.get("spotRadius")),u=e/(i-h+1),l<k&&a.drawCircle((l-h)*u+j,f/2,d.get("spotRadius"),d.get("outlierLineColor"),d.get("outlierFillColor")).append(),r>q&&a.drawCircle((r-h)*u+j,f/2,d.get("spotRadius"),d.get("outlierLineColor"),d.get("outlierFillColor")).append()),a.drawRect(Math.round((n-h)*u+j),Math.round(f*.1),Math.round((p-n)*u),Math.round(f*.8),d.get("boxLineColor"),d.get("boxFillColor")).append(),a.drawLine(Math.round((k-h)*u+j),Math.round(f/2),Math.round((n-h)*u+j),Math.round(f/2),d.get("lineColor")).append(),a.drawLine(Math.round((k-h)*u+j),Math.round(f/4),Math.round((k-h)*u+j),Math.round(f-f/4),d.get("whiskerColor")).append(),a.drawLine(Math
.round((q-h)*u+j),Math.round(f/2),Math.round((p-h)*u+j),Math.round(f/2),d.get("lineColor")).append(),a.drawLine(Math.round((q-h)*u+j),Math.round(f/4),Math.round((q-h)*u+j),Math.round(f-f/4),d.get("whiskerColor")).append(),a.drawLine(Math.round((o-h)*u+j),Math.round(f*.1),Math.round((o-h)*u+j),Math.round(f*.9),d.get("medianColor")).append(),d.get("target")&&(t=Math.ceil(d.get("spotRadius")),a.drawLine(Math.round((d.get("target")-h)*u+j),Math.round(f/2-t),Math.round((d.get("target")-h)*u+j),Math.round(f/2+t),d.get("targetColor")).append(),a.drawLine(Math.round((d.get("target")-h)*u+j-t),Math.round(f/2),Math.round((d.get("target")-h)*u+j+t),Math.round(f/2),d.get("targetColor")).append()),a.render()}}),a.browser.msie&&!document.namespaces.v&&document.namespaces.add("v","urn:schemas-microsoft-com:vml","#default#VML"),a.browser.hasCanvas===undefined&&(a.browser.hasCanvas=document.createElement("canvas").getContext!==undefined),D=d({init:function(a,b,c,d){this.target=a,this.id=b,th
is.type=c,this.args=d},append:function(){return this.target.appendShape(this),this}}),E=d({_pxregex:/(\d+)(px)?\s*$/i,init:function(b,c,d){if(!b)return;this.width=b,this.height=c,this.target=d,this.lastShapeId=null,d[0]&&(d=d[0]),a.data(d,"_jqs_vcanvas",this)},drawLine:function(a,b,c,d,e,f){return this.drawShape([[a,b],[c,d]],e,f)},drawShape:function(a,b,c,d){return this._genShape("Shape",[a,b,c,d])},drawCircle:function(a,b,c,d,e,f){return this._genShape("Circle",[a,b,c,d,e,f])},drawPieSlice:function(a,b,c,d,e,f,g){return this._genShape("PieSlice",[a,b,c,d,e,f,g])},drawRect:function(a,b,c,d,e,f){return this._genShape("Rect",[a,b,c,d,e,f])},getElement:function(){return this.canvas},getLastShapeId:function(){return this.lastShapeId},reset:function(){alert("reset not implemented")},_insert:function(b,c){a(c).html(b)},_calculatePixelDims:function(b,c,d){var e;e=this._pxregex.exec(c),e?this.pixelHeight=e[1]:this.pixelHeight=a(d).height(),e=this._pxregex.exec(b),e?this.pixelWidth=
e[1]:this.pixelWidth=a(d).width()},_genShape:function(a,b){var c=I++;return b.unshift(c),new D(this,c,a,b)},appendShape:function(a){alert("appendShape not implemented")},replaceWithShape:function(a,b){alert("replaceWithShape not implemented")},insertAfterShape:function(a,b){alert("insertAfterShape not implemented")},removeShapeId:function(a){alert("removeShapeId not implemented")},getShapeAt:function(a,b,c){alert("getShapeAt not implemented")},render:function(){alert("render not implemented")}}),F=d(E,{init:function(b,c,d,e){F._super.init.call(this,b,c,d),this.canvas=document.createElement("canvas"),d[0]&&(d=d[0]),a.data(d,"_jqs_vcanvas",this),a(this.canvas).css({display:"inline-block",width:b,height:c,verticalAlign:"top"}),this._insert(this.canvas,d),this._calculatePixelDims(b,c,this.canvas),this.canvas.width=this.pixelWidth,this.canvas.height=this.pixelHeight,this.interact=e,this.shapes={},this.shapeseq=[],this.currentTargetShapeId=undefined,a(this.canvas).css({width:this.
pixelWidth,height:this.pixelHeight})},_getContext:function(a,b,c){var d=this.canvas.getContext("2d");return a!==undefined&&(d.strokeStyle=a),d.lineWidth=c===undefined?1:c,b!==undefined&&(d.fillStyle=b),d},reset:function(){var a=this._getContext();a.clearRect(0,0,this.pixelWidth,this.pixelHeight),this.shapes={},this.shapeseq=[],this.currentTargetShapeId=undefined},_drawShape:function(a,b,c,d,e){var f=this._getContext(c,d,e),g,h;f.beginPath(),f.moveTo(b[0][0]+.5,b[0][1]+.5);for(g=1,h=b.length;g<h;g++)f.lineTo(b[g][0]+.5,b[g][1]+.5);c!==undefined&&f.stroke(),d!==undefined&&f.fill(),this.targetX!==undefined&&this.targetY!==undefined&&f.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a)},_drawCircle:function(a,b,c,d,e,f,g){var h=this._getContext(e,f,g);h.beginPath(),h.arc(b,c,d,0,2*Math.PI,!1),this.targetX!==undefined&&this.targetY!==undefined&&h.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a),e!==undefined&&h.stroke(),f!==undefined&&h
.fill()},_drawPieSlice:function(a,b,c,d,e,f,g,h){var i=this._getContext(g,h);i.beginPath(),i.moveTo(b,c),i.arc(b,c,d,e,f,!1),i.lineTo(b,c),i.closePath(),g!==undefined&&i.stroke(),h&&i.fill(),this.targetX!==undefined&&this.targetY!==undefined&&i.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a)},_drawRect:function(a,b,c,d,e,f,g){return this._drawShape(a,[[b,c],[b+d,c],[b+d,c+e],[b,c+e],[b,c]],f,g)},appendShape:function(a){return this.shapes[a.id]=a,this.shapeseq.push(a.id),this.lastShapeId=a.id,a.id},replaceWithShape:function(a,b){var c=this.shapeseq,d;this.shapes[b.id]=b;for(d=c.length;d--;)c[d]==a&&(c[d]=b.id);delete this.shapes[a]},replaceWithShapes:function(a,b){var c=this.shapeseq,d={},e,f,g;for(f=a.length;f--;)d[a[f]]=!0;for(f=c.length;f--;)e=c[f],d[e]&&(c.splice(f,1),delete this.shapes[e],g=f);for(f=b.length;f--;)c.splice(g,0,b[f].id),this.shapes[b[f].id]=b[f]},insertAfterShape:function(a,b){var c=this.shapeseq,d;for(d=c.length;d--;)if(c[d]===a){c
.splice(d+1,0,b.id),this.shapes[b.id]=b;return}},removeShapeId:function(a){var b=this.shapeseq,c;for(c=b.length;c--;)if(b[c]===a){b.splice(c,1);break}delete this.shapes[a]},getShapeAt:function(a,b,c){return this.targetX=b,this.targetY=c,this.render(),this.currentTargetShapeId},render:function(){var a=this.shapeseq,b=this.shapes,c=a.length,d=this._getContext(),e,f,g;d.clearRect(0,0,this.pixelWidth,this.pixelHeight);for(g=0;g<c;g++)e=a[g],f=b[e],this["_draw"+f.type].apply(this,f.args);this.interact||(this.shapes={},this.shapeseq=[])}}),G=d(E,{init:function(b,c,d){var e;G._super.init.call(this,b,c,d),d[0]&&(d=d[0]),a.data(d,"_jqs_vcanvas",this),this.canvas=document.createElement("span"),a(this.canvas).css({display:"inline-block",position:"relative",overflow:"hidden",width:b,height:c,margin:"0px",padding:"0px",verticalAlign:"top"}),this._insert(this.canvas,d),this._calculatePixelDims(b,c,this.canvas),this.canvas.width=this.pixelWidth,this.canvas.height=this.pixelHeight,e='<v:gro
up coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'"'+' style="position:absolute;top:0;left:0;width:'+this.pixelWidth+"px;height="+this.pixelHeight+'px;"></v:group>',this.canvas.insertAdjacentHTML("beforeEnd",e),this.group=a(this.canvas).children()[0],this.rendered=!1,this.prerender=""},_drawShape:function(a,b,c,d,e){var f=[],g,h,i,j,k,l,m;for(m=0,l=b.length;m<l;m++)f[m]=""+b[m][0]+","+b[m][1];return g=f.splice(0,1),e=e===undefined?1:e,h=c===undefined?' stroked="false" ':' strokeWeight="'+e+'px" strokeColor="'+c+'" ',i=d===undefined?' filled="false"':' fillColor="'+d+'" filled="true" ',j=f[0]===f[f.length-1]?"x ":"",k='<v:shape coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'" '+' id="jqsshape'+a+'" '+h+i+' style="position:absolute;left:0px;top:0px;height:'+this.pixelHeight+"px;width:"+this.pixelWidth+'px;padding:0px;margin:0px;" '+' path="m '+g+" l "+f.join(", ")+" "+j+'e">'+" </v:shape>",k},_drawCircle:function(a,b,c,d,e,f,g){var h
,i,j;return b-=d,c-=d,h=e===undefined?' stroked="false" ':' strokeWeight="'+g+'px" strokeColor="'+e+'" ',i=f===undefined?' filled="false"':' fillColor="'+f+'" filled="true" ',j='<v:oval id="jqsshape'+a+'" '+h+i+' style="position:absolute;top:'+c+"px; left:"+b+"px; width:"+d*2+"px; height:"+d*2+'px"></v:oval>',j},_drawPieSlice:function(a,b,c,d,e,f,g,h){var i,j,k,l,m,n,o,p;if(e===f)return;f-e===2*Math.PI&&(e=0,f=2*Math.PI),j=b+Math.round(Math.cos(e)*d),k=c+Math.round(Math.sin(e)*d),l=b+Math.round(Math.cos(f)*d),m=c+Math.round(Math.sin(f)*d);if(j===l&&k===m&&f-e<Math.PI)return;return i=[b-d,c-d,b+d,c+d,j,k,l,m],n=g===undefined?' stroked="false" ':' strokeWeight="1px" strokeColor="'+g+'" ',o=h===undefined?' filled="false"':' fillColor="'+h+'" filled="true" ',p='<v:shape coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'" '+' id="jqsshape'+a+'" '+n+o+' style="position:absolute;left:0px;top:0px;height:'+this.pixelHeight+"px;width:"+this.pixelWidth+'px;padding:0
px;margin:0px;" '+' path="m '+b+","+c+" wa "+i.join(", ")+' x e">'+" </v:shape>",p},_drawRect:function(a,b,c,d,e,f,g){return this._drawShape(a,[[b,c],[b,c+e],[b+d,c+e],[b+d,c],[b,c]],f,g)},reset:function(){this.group.innerHTML=""},appendShape:function(a){var b=this["_draw"+a.type].apply(this,a.args);return this.rendered?this.group.insertAdjacentHTML("beforeEnd",b):this.prerender+=b,this.lastShapeId=a.id,a.id},replaceWithShape:function(b,c){var d=a("#jqsshape"+b),e=this["_draw"+c.type].apply(this,c.args);d[0].outerHTML=e},replaceWithShapes:function(b,c){var d=a("#jqsshape"+b[0]),e="",f=c.length,g;for(g=0;g<f;g++)e+=this["_draw"+c[g].type].apply(this,c[g].args);d[0].outerHTML=e;for(g=1;g<b.length;g++)a("#jqsshape"+b[g]).remove()},insertAfterShape:function(b,c){var d=a("#jqsshape"+b),e=this["_draw"+c.type].apply(this,c.args);d[0].insertAdjacentHTML("afterEnd",e)},removeShapeId:function(b){var c=a("#jqsshape"+b);this.group.removeChild(c[0])},getShapeAt:function(a,b,c){var d=a.id
.substr(8);return d},render:function(){this.rendered||(this.group.innerHTML=this.prerender,this.rendered=!0)}})})(jQuery);
\ No newline at end of file
commit 12250e1e39fa3e4b48ca42c17eb561eff3d4d4bd
Author: John Sanda <jsanda(a)redhat.com>
Date: Wed Aug 15 13:24:37 2012 -0400
[BZ 802796] Provide more details for time outs
This commit add more details to the timeout help message.
CreateResourceRunner has also been updated so that it sets the status of
the respone to TIMED_OUT. Previously timed out deployments were getting
flagged as just a FAILURE. The error message in the response now also
contains additional details indicating that the deployment might still
succeed and that the user may want to run a discovery scan to see if it
did.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java
index 7a01b88..b3c65bd 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/CreateResourceRunner.java
@@ -22,22 +22,22 @@
*/
package org.rhq.core.pc.inventory;
- import org.rhq.core.clientapi.agent.inventory.CreateResourceResponse;
- import org.rhq.core.clientapi.server.discovery.InventoryReport;
- import org.rhq.core.clientapi.server.inventory.ResourceFactoryServerService;
- import org.rhq.core.domain.configuration.Configuration;
- import org.rhq.core.domain.resource.CreateResourceStatus;
- import org.rhq.core.domain.resource.Resource;
- import org.rhq.core.pc.PluginContainer;
- import org.rhq.core.pluginapi.inventory.CreateChildResourceFacet;
- import org.rhq.core.pluginapi.inventory.CreateResourceReport;
- import org.rhq.core.util.exception.ThrowableUtil;
-
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
-
import java.util.concurrent.Callable;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.clientapi.agent.inventory.CreateResourceResponse;
+import org.rhq.core.clientapi.server.discovery.InventoryReport;
+import org.rhq.core.clientapi.server.inventory.ResourceFactoryServerService;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.resource.CreateResourceStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.pc.PluginContainer;
+import org.rhq.core.pluginapi.inventory.CreateChildResourceFacet;
+import org.rhq.core.pluginapi.inventory.CreateResourceReport;
+import org.rhq.core.util.exception.ThrowableUtil;
+
/**
* Runnable implementation to process Resource create requests.
*
@@ -159,9 +159,15 @@ public class CreateResourceRunner implements Callable, Runnable {
// If we still don't have an error message, populate it from the exception
errorMessage = (errorMessage != null) ? (errorMessage + " - Cause: " + messages) : messages;
}
+ } catch(TimeoutException e) {
+ status = CreateResourceStatus.TIMED_OUT;
+ errorMessage = "The time out has been exceeded; however, the deployment may have been successful. You " +
+ "may want to run a discovery scan to see if the deployment did complete successfully. Also consider " +
+ "using a higher time out value for future deployments.\n\nRoot Cause:\n";
+ errorMessage += ThrowableUtil.getStackAsString(e);
} catch (Throwable t) {
- errorMessage = ThrowableUtil.getStackAsString(t);
status = CreateResourceStatus.FAILURE;
+ errorMessage = ThrowableUtil.getStackAsString(t);
}
// Send results back to the server
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index f9b75f3..cfa1f6d 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -2035,8 +2035,8 @@ widget_resourceFactoryWizard_infoStepName = Resource Information
widget_resourceFactoryWizard_infoStep_loadFail = Failed to get available Architectures
widget_resourceFactoryWizard_namePrompt = New Resource Name
widget_resourceFactoryWizard_templatePrompt = Connection Settings Template
-widget_resourceFactoryWizard_timeoutFailure = Timed out. Note that it is possible that the deployment may still succeed.
-widget_resourceFactoryWizard_timeoutHelp = A timeout duration. If specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. Useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure.
+widget_resourceFactoryWizard_timeoutFailure = Timed out
+widget_resourceFactoryWizard_timeoutHelp = A timeout duration that if specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. A higher value may be useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure. Note that if there is a timeout failure, it is still possible that the resource deployment succeeded. In the event of a timeout you may want to execute a discovery scan before attempting to redeploy the resource.
widget_resourceFactoryWizard_uploadFailure = Failed to upload file
widget_resourceFactoryWizard_uploadFileStepName = Upload Resource Content File
widget_resourceFactoryWizard_uploadInProgress = The upload is in progress... This can take several minutes to complete for large distribution files.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index 11c4488..5be0d57 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -2052,8 +2052,8 @@ widget_resourceFactoryWizard_infoStepName = Informace o zdroji
widget_resourceFactoryWizard_infoStep_loadFail = Nepodařilo se získat dostupné architektury
widget_resourceFactoryWizard_namePrompt = Nové jméno zdroje
widget_resourceFactoryWizard_templatePrompt = Šablona pro nastavení připojení
-##widget_resourceFactoryWizard_timeoutFailure = Timed out. Note that it is possible that the deployment may still succeed.
-##widget_resourceFactoryWizard_timeoutHelp = A timeout duration. If specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. Useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure.
+##widget_resourceFactoryWizard_timeoutFailure = Timed out
+##widget_resourceFactoryWizard_timeoutHelp = A timeout duration that if specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. A higher value may be useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure. Note that if there is a timeout failure, it is still possible that the resource deployment succeeded. In the event of a timeout you may want to execute a discovery scan before attempting to redeploy the resource.
widget_resourceFactoryWizard_uploadFailure = Nepodařilo se nahrát soubor
widget_resourceFactoryWizard_uploadFileStepName = Nahrát obsah souboru zdroje
widget_resourceFactoryWizard_uploadInProgress = Upload právě probíhá... Může to trvat několik minut.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 71d8367..d39f16a 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -1815,9 +1815,9 @@ widget_resourceFactoryWizard_infoStepName = Information über die Ressource
widget_resourceFactoryWizard_infoStep_loadFail = Konnte die verfügbaren Architekturen nicht ermitteln
widget_resourceFactoryWizard_namePrompt = Name der neuen Ressource
widget_resourceFactoryWizard_templatePrompt = Vorlage für die Verbindungseinstellungen
-##widget_resourceFactoryWizard_timeoutHelp = A timeout duration. If specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. Useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure.
+##widget_resourceFactoryWizard_timeoutHelp = A timeout duration that if specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. A higher value may be useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure. Note that if there is a timeout failure, it is still possible that the resource deployment succeeded. In the event of a timeout you may want to execute a discovery scan before attempting to redeploy the resource.
widget_resourceFactoryWizard_uploadFailure = Konnte die Datei nicht hochladen
-###widget_resourceFactoryWizard_timeoutFailure = Timed out. Note that it is possible that the deployment may still succeed.
+###widget_resourceFactoryWizard_timeoutFailure = Timed out
##widget_resourceFactoryWizard_uploadFileStepName = Upload Resource Content File
##widget_resourceFactoryWizard_uploadInProgress = The upload is in progress... This can take several minutes to complete for large distribution files.
widget_resourceFactoryWizard_versionPrompt = Paketversion
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index 33e39c8..6c2044a 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -2022,8 +2022,8 @@ widget_resourceFactoryWizard_infoStepName = リソース情報
widget_resourceFactoryWizard_infoStep_loadFail = アーキテクチャーを利用可能にするのに失敗しました
widget_resourceFactoryWizard_namePrompt = 新規リソース名
widget_resourceFactoryWizard_templatePrompt = コネクション設定テンプレート
-###widget_resourceFactoryWizard_timeoutFailure = Timed out. Note that it is possible that the deployment may still succeed.
-##widget_resourceFactoryWizard_timeoutHelp = A timeout duration. If specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. Useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure.
+###widget_resourceFactoryWizard_timeoutFailure = Timed out
+##widget_resourceFactoryWizard_timeoutHelp = A timeout duration that if specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. A higher value may be useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure. Note that if there is a timeout failure, it is still possible that the resource deployment succeeded. In the event of a timeout you may want to execute a discovery scan before attempting to redeploy the resource.
widget_resourceFactoryWizard_uploadFailure = ファイルアップロードの失敗
widget_resourceFactoryWizard_uploadFileStepName = リソースコンテントファイルのアップロード
widget_resourceFactoryWizard_uploadInProgress = アップロードは処理中です... 大きなファイルを配布するには数分かかることもあります。
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 2c1af7e..9f00c55 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -2137,8 +2137,8 @@ widget_resourceFactoryWizard_infoStepName = Informa\u00E7\u00E3o do Recurso
widget_resourceFactoryWizard_infoStep_loadFail = Falha ao recuperar Arquiteturas dispon\u00EDveis.
widget_resourceFactoryWizard_namePrompt = Novo Nome do Recurso
widget_resourceFactoryWizard_templatePrompt = Modelo de Propriedades para Conex\u00E3o
-##widget_resourceFactoryWizard_timeoutFailure = Timed out. Note that it is possible that the deployment may still succeed.
-##widget_resourceFactoryWizard_timeoutHelp = A timeout duration. If specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. Useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure.
+##widget_resourceFactoryWizard_timeoutFailure = Timed out
+##widget_resourceFactoryWizard_timeoutHelp = A timeout duration that if specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. A higher value may be useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure. Note that if there is a timeout failure, it is still possible that the resource deployment succeeded. In the event of a timeout you may want to execute a discovery scan before attempting to redeploy the resource.
widget_resourceFactoryWizard_uploadFailure = Falha ao realizar o upload do arquivo
widget_resourceFactoryWizard_uploadFileStepName = Upload do Arquivo do Recurso
widget_resourceFactoryWizard_uploadInProgress = Upload em andamento... Esse processo pode demorar alguns minutos para ser finalizado em caso de arquivos muito grandes.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 29a3fa6..25671e1 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -2014,8 +2014,8 @@
#widget_resourceFactoryWizard_infoStep_loadFail = Failed to get available Architectures
#widget_resourceFactoryWizard_namePrompt = New Resource Name
#widget_resourceFactoryWizard_templatePrompt = Connection Settings Template
-#widget_resourceFactoryWizard_timeoutHelp = A timeout duration. If specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. Useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure.
-#widget_resourceFactoryWizard_timeoutFailure = Timed out. Note that it is possible that the deployment may still succeed.
+#widget_resourceFactoryWizard_timeoutHelp = A timeout duration that if specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. A higher value may be useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure. Note that if there is a timeout failure, it is still possible that the resource deployment succeeded. In the event of a timeout you may want to execute a discovery scan before attempting to redeploy the resource.
+#widget_resourceFactoryWizard_timeoutFailure = Timed out
#widget_resourceFactoryWizard_uploadFailure = Failed to upload file
#widget_resourceFactoryWizard_uploadFileStepName = Upload Resource Content File
#widget_resourceFactoryWizard_uploadInProgress = The upload is in progress... This can take several minutes to complete for large distribution files.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index cd7f97f..827e01b 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -2020,8 +2020,8 @@ widget_resourceFactoryWizard_infoStepName = \u8d44\u6e90\u6d88\u606f
widget_resourceFactoryWizard_infoStep_loadFail = \u65e0\u6cd5\u53d6\u5f97\u67b6\u6784
widget_resourceFactoryWizard_namePrompt = \u65b0\u8d44\u6e90\u540d
widget_resourceFactoryWizard_templatePrompt = \u8fde\u63a5\u8bbe\u7f6e\u6a21\u677f
-#widget_resourceFactoryWizard_timeoutHelp = A timeout duration. If specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. Useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure.
-#widget_resourceFactoryWizard_timeoutFailure = Timed out. Note that it is possible that the deployment may still succeed.
+#widget_resourceFactoryWizard_timeoutHelp = A timeout duration that if specified will override the default timeout for child resource creation (on the {0} Agent). The default timeout is set to 60 seconds. A higher value may be useful for particularly long create actions, like deployment of a large application. Usually used if a previous attempt suffered a timeout failure. Note that if there is a timeout failure, it is still possible that the resource deployment succeeded. In the event of a timeout you may want to execute a discovery scan before attempting to redeploy the resource.
+#widget_resourceFactoryWizard_timeoutFailure = Timed out
widget_resourceFactoryWizard_uploadFailure = \u4e0a\u4f20\u6587\u4ef6\u5931\u8d25
widget_resourceFactoryWizard_uploadFileStepName = \u4e0a\u4f20\u8d44\u6e90Content\u6587\u4ef6
widget_resourceFactoryWizard_uploadInProgress = \u6b63\u5728\u4e0a\u4f20\u4e2d... \u5927\u7684\u53d1\u5e03\u6587\u4ef6\u9700\u8981\u6d88\u8017\u6570\u5206\u949f\u5b8c\u6210.
commit 7b82e90aa77706ec33c5195e02da0f374e410c86
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Wed Aug 15 12:07:13 2012 -0400
Upate this dev plugin to also allow for a delay when reporting metrics. This
allows the plugin to be used for "slow" collection reporting when
simulating an overloaded agent or misbehaving plugin.
For example, to see debug logging in the agent when metric collection is
falling behind try:
1) Update pattern2 collection interval to 40s so that the two pattern metrics
are not collected at the same time, thus creating more load.
2) Set the new "delay" plugin config prop to 25. So, each collection will
take 25s, and quickly the agent will fall behind.
diff --git a/modules/plugins/pattern-generator/src/main/java/org/rhq/plugins/pattern/PatternComponent.java b/modules/plugins/pattern-generator/src/main/java/org/rhq/plugins/pattern/PatternComponent.java
index 5c8d631..18c6036 100644
--- a/modules/plugins/pattern-generator/src/main/java/org/rhq/plugins/pattern/PatternComponent.java
+++ b/modules/plugins/pattern-generator/src/main/java/org/rhq/plugins/pattern/PatternComponent.java
@@ -1,4 +1,3 @@
-
package org.rhq.plugins.pattern;
import java.util.Set;
@@ -30,6 +29,8 @@ public class PatternComponent implements ResourceComponent, MeasurementFacet {
int[] wanted = new int[2];
+ long delay = 0L; // in seconds
+
/**
* Return availability of this resource
* @see org.rhq.core.pluginapi.inventory.ResourceComponent#getAvailability()
@@ -38,7 +39,6 @@ public class PatternComponent implements ResourceComponent, MeasurementFacet {
return AvailabilityType.UP;
}
-
/**
* Start the resource connection
* @see org.rhq.core.pluginapi.inventory.ResourceComponent#start(org.rhq.core.pluginapi.inventory.ResourceContext)
@@ -46,19 +46,23 @@ public class PatternComponent implements ResourceComponent, MeasurementFacet {
public void start(ResourceContext context) throws InvalidPluginConfigurationException {
Configuration conf = context.getPluginConfiguration();
- String tmp = conf.getSimpleValue("ones","1");
+ String tmp = conf.getSimpleValue("ones", "1");
int wantedOnes = Integer.parseInt(tmp);
- if (wantedOnes<1)
+ if (wantedOnes < 1)
throw new InvalidPluginConfigurationException("Ones must be > 0");
- tmp = conf.getSimpleValue("zeros","1");
+ tmp = conf.getSimpleValue("zeros", "1");
int wantedZeros = Integer.parseInt(tmp);
- if (wantedZeros<1)
+ if (wantedZeros < 1)
throw new InvalidPluginConfigurationException("Zeros must be > 0");
wanted[0] = wantedZeros;
wanted[1] = wantedOnes;
- }
+ tmp = conf.getSimpleValue("delay", "0");
+ delay = Long.parseLong(tmp);
+ if (delay < 0L)
+ delay = 0L;
+ }
/**
* Tear down the resource connection
@@ -68,19 +72,22 @@ public class PatternComponent implements ResourceComponent, MeasurementFacet {
// Nothing to do.
}
-
/**
* Gather "measurement" data - actually a series of 1s and 0s starting with 0.
* @see org.rhq.core.pluginapi.measurement.MeasurementFacet#getValues(org.rhq.core.domain.measurement.MeasurementReport, java.util.Set)
*/
- public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> requests) throws Exception {
+ public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> requests) throws Exception {
+
+ if (delay > 0L) {
+ Thread.sleep(delay * 1000L);
+ }
- boolean flipMetrics = false;
- boolean flipTraits = false;
- for (MeasurementScheduleRequest request : requests) {
- String metricName = request.getName();
+ boolean flipMetrics = false;
+ boolean flipTraits = false;
+ for (MeasurementScheduleRequest request : requests) {
+ String metricName = request.getName();
- if (metricName.startsWith("pattern")) {
+ if (metricName.startsWith("pattern")) {
double value;
if (metricName.equals("pattern1")) {
@@ -98,15 +105,15 @@ public class PatternComponent implements ResourceComponent, MeasurementFacet {
double value;
if (metricName.equals("text1")) {
- value = numberForTrait;
- flipTraits = true;
+ value = numberForTrait;
+ flipTraits = true;
} else {
- // text2
- value = 1 - numberForTrait;
+ // text2
+ value = 1 - numberForTrait;
}
String traitValue = (value == 0) ? "red" : "green";
- MeasurementDataTrait datum = new MeasurementDataTrait(request,traitValue);
+ MeasurementDataTrait datum = new MeasurementDataTrait(request, traitValue);
report.addData(datum);
}
}
diff --git a/modules/plugins/pattern-generator/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/pattern-generator/src/main/resources/META-INF/rhq-plugin.xml
index 70a8a59..e45ba0f 100644
--- a/modules/plugins/pattern-generator/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/pattern-generator/src/main/resources/META-INF/rhq-plugin.xml
@@ -16,6 +16,7 @@
<plugin-configuration>
<c:simple-property name="zeros" description="Number of zeros in a row" type="integer" default="1"/>
<c:simple-property name="ones" description="Number of ones in a row" type="integer" default="2"/>
+ <c:simple-property name="delay" description="Number of seconds to delay each metric collection (to test slow reporting)" type="integer" default="0"/>
</plugin-configuration>
<metric property="pattern1" displayName="Pattern 1 Metric" defaultInterval="30000" displayType="summary" defaultOn="true"/>
commit c9eb53bb8dab7393d9b5383fbe5bab99088487ed
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue Aug 14 17:13:42 2012 -0400
[Bug 846353 - ORA-02049 during upgrade from JON-3.1.0.GA to JON-3.1.1.ER1 with Oracle]
After a lot of investigation it seems that the problem occurs occasionally
when we remove obsolete properties from resource configuration. It does
not happen every time, on fact it's fairly rare, although for the same DB,
and the same plugin update, it is repeatable. This makes it seem like the
locking issue is due mainly to unpredictable locking at the db level, and
likely the fact that we occasionally hit a page lock due to some other
prior update to the config table. Since the config table stores so many
different types of data it's not obvious how we would identify the conflict.
The approach taken was to try and reduce possible conflict by increasing the
granularity of metadata update transactions. Prior to this change we used a
single encompassing transaction for a plugin update, that means all types
were updated under one umbrella transaction. Not one transaction, because
we already use nested transactions in several places, but using one umbrella
transaction increases the chance of that transaction holding a lock that
could affect a nested transaction.
We still maintain the umbrella transaction but this commit breaks it up
such that a nested transaction is used for the update of each resource
type in the plugin.
That means each type update will not hold any locks when it has completed.
This change seems to be working as the AS7 plugin now updates successfully.
Additionally:
- added some more INFO level logging to give some basic progress during a
plugin update.
- added some more debug logging as well
- removed a bunch of unnecessary em.flush calls
- used the return value of some em.merge calls to ensure using the up to
date entity.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java
index dcc1a0b..b343f79 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java
@@ -73,24 +73,27 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
for (PropertyDefinition newProperty : newPropertyDefinitions) {
PropertyDefinition existingProp = existingDefinition.get(newProperty.getName());
if (existingProp != null) {
+ log.debug("Updating nonGrouped property [" + existingProp + "]");
+
updatePropertyDefinition(existingProp, newProperty);
updateReport.addUpdatedPropertyDefinition(newProperty);
} else {
+ log.debug("Adding nonGrouped property [" + newProperty + "]");
+
existingDefinition.put(newProperty);
updateReport.addNewPropertyDefinition(newProperty);
}
}
- // delete outdated properties
- removeNoLongerUsedProperties(newDefinition, existingDefinition, existingPropertyDefinitions);
+ existingDefinition = removeNoLongerUsedProperties(newDefinition, existingDefinition,
+ existingPropertyDefinitions);
+
} else {
// TODO what if existingDefinitions is null?
// we probably don't run in here, as the initial persisting is done
// somewhere else.
}
- // entityManager.flush();
-
/*
* Now update / delete contained groups We need to be careful here, as groups are present in PropertyDefinition
* as "backlink" from PropertyDefinition to group
@@ -108,6 +111,8 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
// first look for contained stuff
for (PropertyDefinition def : groupedDefinitions) {
+ log.debug("Removing property [" + def + "] from group [" + group + "]");
+
existingPropertyDefinitions.remove(def);
existingDefinition.getPropertyDefinitions().remove(def.getName());
def.setPropertyGroupDefinition(null);
@@ -115,41 +120,44 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
}
// then remove the definition itself
+ log.debug("Removing group [" + group + "]");
+
existingGroups.remove(group);
entityManager.remove(group);
}
- // entityManager.flush();
-
// update existing groups that stay
for (PropertyGroupDefinition group : toUpdate) {
String groupName = group.getName();
- // System.out.println("Group to update: " + groupName + ", id=" + group.getId());
List<PropertyDefinition> newGroupedDefinitions = newDefinition.getPropertiesInGroup(groupName);
for (PropertyDefinition nDef : newGroupedDefinitions) {
PropertyDefinition existingProperty = existingDefinition.getPropertyDefinitions().get(nDef.getName());
if (existingProperty != null) {
+ log.debug("Updating property [" + nDef + "] in group [" + group + "]");
+
updatePropertyDefinition(existingProperty, nDef);
updateReport.addUpdatedPropertyDefinition(nDef);
+
} else {
+ log.debug("Adding property [" + nDef + "] to group [" + group + "]");
+
existingDefinition.put(nDef);
updateReport.addNewPropertyDefinition(nDef);
}
}
// delete outdated properties of this group
- removeNoLongerUsedProperties(newDefinition, existingDefinition,
+ existingDefinition = removeNoLongerUsedProperties(newDefinition, existingDefinition,
existingDefinition.getPropertiesInGroup(groupName));
}
- // entityManager.flush();
-
// persist new groups
for (PropertyGroupDefinition group : toPersist) {
- /*
- * First persist a new group definition and then link the properties to it
- */
+
+ // First persist a new group definition and then link the properties to it
+ log.debug("Persisting new group [" + group + "]");
+
entityManager.persist(group);
existingGroups.add(group); // iterating over this does not update the underlying crap
@@ -185,17 +193,22 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
}
for (String name : toRemove) {
+ log.debug("Removing template [" + name + "]");
+
ConfigurationTemplate template = existingTemplates.remove(name);
entityManager.remove(template);
}
for (String name : templatesToUpdate) {
+ log.debug("Updating template [" + name + "]");
+
updateTemplate(existingDefinition.getTemplate(name), newTemplates.get(name));
}
for (String name : newTemplates.keySet()) {
// add completely new templates
if (!existingTemplates.containsKey(name)) {
+ log.debug("Adding template [" + name + "]");
ConfigurationTemplate newTemplate = newTemplates.get(name);
@@ -279,8 +292,9 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
* @param existingConfigDef existing persisted configuration
* @param existingProperties list of existing properties to inspect for potential removal
*/
- private void removeNoLongerUsedProperties(ConfigurationDefinition newConfigDef,
+ private ConfigurationDefinition removeNoLongerUsedProperties(ConfigurationDefinition newConfigDef,
ConfigurationDefinition existingConfigDef, List<PropertyDefinition> existingProperties) {
+
List<PropertyDefinition> propDefsToDelete = new ArrayList<PropertyDefinition>();
for (PropertyDefinition existingPropDef : existingProperties) {
PropertyDefinition newPropDef = newConfigDef.get(existingPropDef.getName());
@@ -296,8 +310,10 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
existingConfigDef.getPropertyDefinitions().remove(propDef.getName());
existingProperties.remove(propDef); // does not operate on original list!!
}
- entityManager.merge(existingConfigDef);
+ existingConfigDef = entityManager.merge(existingConfigDef);
}
+
+ return existingConfigDef;
}
/**
@@ -360,7 +376,7 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
}
}
- entityManager.merge(existingProperty);
+ existingProperty = entityManager.merge(existingProperty);
} else { // different type
@@ -412,7 +428,7 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa
}
}
}
- entityManager.merge(existingPDS);
+ existingPDS = entityManager.merge(existingPDS);
// handle <constraint> [0..*]
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
index 032deb3..2c8a925 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
@@ -153,7 +153,7 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
Set<ResourceType> legitimateChildren = new HashSet<ResourceType>();
for (ResourceType resourceType : nonRunsInsideResourceTypes) {
long startTime = System.currentTimeMillis();
- updateType(resourceType);
+ resourceType = resourceMetadataManager.updateType(resourceType);
long endTime = System.currentTimeMillis();
log.debug("Updated resource type [" + toConciseString(resourceType) + "] in " + (endTime - startTime)
+ " ms");
@@ -181,7 +181,7 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
resourceMetadataManager.getPluginTypes(subject, pluginName, legitTypes, obsoleteTypes, metadataCache);
if (!obsoleteTypes.isEmpty()) {
- log.debug("Removing " + obsoleteTypes.size() + " obsolete types: " + obsoleteTypes + "...");
+ log.info("Removing " + obsoleteTypes.size() + " obsolete types: " + obsoleteTypes + "...");
removeResourceTypes(subject, obsoleteTypes, new HashSet<ResourceType>(obsoleteTypes));
}
@@ -361,21 +361,19 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
}
}
- private void updateType(ResourceType resourceType) {
- entityManager.flush();
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public ResourceType updateType(ResourceType resourceType) {
// see if there is already an existing type that we need to update
- if (log.isDebugEnabled()) {
- log.debug("Updating resource type [" + resourceType.getName() + "] from plugin ["
- + resourceType.getPlugin() + "]...");
- }
+ log.info("Updating resource type [" + toConciseString(resourceType) + "]...");
ResourceType existingType;
try {
existingType = resourceTypeManager.getResourceTypeByNameAndPlugin(resourceType.getName(),
resourceType.getPlugin());
+
} catch (NonUniqueResultException nure) {
- log.debug("Found more than one existing ResourceType for " + resourceType);
+ log.info("Found more than one existing ResourceType for " + resourceType);
// TODO: Delete the redundant ResourceTypes to get the DB into a valid state.
throw new IllegalStateException(nure);
}
@@ -390,6 +388,8 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
} else {
mergeExistingType(resourceType, existingType);
}
+
+ return resourceType;
}
private void mergeExistingType(ResourceType resourceType, ResourceType existingType) {
@@ -427,7 +427,7 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
// Update the type itself
if (resourceType.getCategory() != existingType.getCategory()) {
log.info("Changing category of Resource type [" + resourceType + "] from " + existingType.getCategory()
- + " to " + resourceType.getCategory() + "...");
+ + " to " + resourceType.getCategory() + "...");
existingType.setCategory(resourceType.getCategory());
}
@@ -447,7 +447,7 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
// above already took care of any modifications to the ResourceSubCategories themselves).
} else if (newSubCat == null) {
if (oldSubCat != null) {
- log.debug("Metadata update: Subcategory of ResourceType [" + resourceType.getName() + "] changed from "
+ log.info("Metadata update: Subcategory of ResourceType [" + resourceType.getName() + "] changed from "
+ oldSubCat + " to " + newSubCat);
existingType.setSubCategory(null);
}
@@ -459,13 +459,12 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
throw new IllegalStateException("Resource type [" + resourceType.getName() + "] in plugin ["
+ resourceType.getPlugin() + "] has a subcategory (" + newSubCat.getName()
+ ") which was not defined as a child subcategory of one of its ancestor resource types.");
- log.debug("Metadata update: Subcategory of ResourceType [" + resourceType.getName() + "] changed from "
+ log.info("Metadata update: Subcategory of ResourceType [" + resourceType.getName() + "] changed from "
+ oldSubCat + " to " + existingSubCat);
existingType.setSubCategory(existingSubCat);
}
existingType = entityManager.merge(existingType);
- entityManager.flush();
}
@Override
@@ -600,7 +599,6 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
MeasurementMetadataManagerBean.getMetricDefinitions(resourceType);
entityManager.persist(resourceType);
- entityManager.flush();
}
private void linkSubCategoryToParents(ResourceType resourceType) {
@@ -665,8 +663,6 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
obsoleteParentType.removeChildResourceType(existingType);
moveResourcesToNewParent(existingType, obsoleteParentType, newParentTypes);
}
-
- entityManager.flush();
}
private static String toConciseString(ResourceType type) {
@@ -711,7 +707,7 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
// children are not handled in this method, update their ancestry now.
resourceManager.updateAncestry(subjectManager.getOverlord(), resource.getId());
} else {
- log.debug("We were unable to move " + resource + " from invalid parent " + resource.getParentResource()
+ log.info("We were unable to move " + resource + " from invalid parent " + resource.getParentResource()
+ " to a new valid parent with one of the following types: " + newParentTypes);
}
}
@@ -842,7 +838,7 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
// simply use the ones from the new type
if ((existingSubCat.getChildSubCategories() == null) || existingSubCat.getChildSubCategories().isEmpty()) {
for (ResourceSubCategory newChildSubCategory : newSubCategory.getChildSubCategories()) {
- log.debug("Metadata update: Adding new child SubCategory [" + newChildSubCategory.getName()
+ log.info("Metadata update: Adding new child SubCategory [" + newChildSubCategory.getName()
+ "] to SubCategory [" + existingSubCat.getName() + "]...");
existingSubCat.addChildSubCategory(newChildSubCategory);
entityManager.persist(newChildSubCategory);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerLocal.java
index ae96d22..b40bf7a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerLocal.java
@@ -46,6 +46,9 @@ public interface ResourceMetadataManagerLocal {
void updateTypes(Set<ResourceType> resourceTypes) throws Exception;
+ /** Exists only to for transactional boundary reasons. Not for general consumption. */
+ ResourceType updateType(ResourceType resourceType) throws Exception;
+
/** TODO: do we want to create a driftMetadataManager SLSB and put this in there */
void updateDriftMetadata(ResourceType existingType, ResourceType resourceType);
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java
index 20f3b9e..4714f57 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java
@@ -176,6 +176,8 @@ public class UpdateConfigurationSubsystemTest extends UpdatePluginMetadataTestBa
}
}
+ // 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
commit b86e772ba8569cc2084fac6e1b2a96f7422cc0e8
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Aug 14 15:40:56 2012 -0400
BZ 848030 - jmxName can be null, so act accordingly. Also put the jmxName into the connection properties of the created resource.
diff --git a/modules/plugins/jboss-cache-v3/src/main/java/org/rhq/plugins/jbosscache3/JBossCacheDetailDiscoveryComponent.java b/modules/plugins/jboss-cache-v3/src/main/java/org/rhq/plugins/jbosscache3/JBossCacheDetailDiscoveryComponent.java
index 5d522de..5d907da 100644
--- a/modules/plugins/jboss-cache-v3/src/main/java/org/rhq/plugins/jbosscache3/JBossCacheDetailDiscoveryComponent.java
+++ b/modules/plugins/jboss-cache-v3/src/main/java/org/rhq/plugins/jbosscache3/JBossCacheDetailDiscoveryComponent.java
@@ -40,9 +40,9 @@ import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
import org.rhq.plugins.jbossas5.ProfileServiceComponent;
/**
- *
+ *
* @author Filip Drabek
- *
+ *
*/
public class JBossCacheDetailDiscoveryComponent implements
ResourceDiscoveryComponent<ProfileServiceComponent<?>> {
@@ -80,7 +80,7 @@ public class JBossCacheDetailDiscoveryComponent implements
String jmxName = defaultConfig.getSimple(CACHE_JMX_NAME).getStringValue();
- beanName += (jmxName.equals("") ? "" : "," + jmxName);
+ beanName += ((jmxName==null || jmxName.equals("")) ? "" : "," + jmxName);
// This is a singleton ResourceType, so we are only looking for a single MBean.
EmsBean emsBean = connection.getBean(beanName);
@@ -94,6 +94,8 @@ public class JBossCacheDetailDiscoveryComponent implements
conf.put(new PropertySimple(
JBossCacheDetailComponent.CACHE_DETAIL_BEAN_NAME,
beanName));
+ conf.put(new PropertySimple(CACHE_JMX_NAME, jmxName));
+
resources.add(new DiscoveredResourceDetails(resourceType,
beanName, resourceType.getName(), "", "JBoss Cache",
conf, null));
diff --git a/modules/plugins/jboss-cache-v3/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-cache-v3/src/main/resources/META-INF/rhq-plugin.xml
index cba79cf..2572f54 100644
--- a/modules/plugins/jboss-cache-v3/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-cache-v3/src/main/resources/META-INF/rhq-plugin.xml
@@ -31,7 +31,7 @@
singleton="true">
<plugin-configuration>
- <c:simple-property name="jmx-resource" default=""/>
+ <c:simple-property name="jmx-resource" default="" required="false"/>
</plugin-configuration>
<operation name="destroy" displayName="Destroy this cache."/>
commit 9e5352d85ca3b4ee98d52771930b61e72f73f579
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 14 14:35:51 2012 -0500
[BZ 833187] A few more updates to :nullable list parsing and saving code. The original fix did not include the loading of such properties.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationLoadDelegate.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationLoadDelegate.java
index 0a49bd1..2fdff39 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationLoadDelegate.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationLoadDelegate.java
@@ -257,7 +257,8 @@ public class ConfigurationLoadDelegate implements ConfigurationFacet {
}
}
- if (propertyName.endsWith(":expr") || propertyName.endsWith(":collapsed")) {
+ if (propertyName.endsWith(":expr") || propertyName.endsWith(":collapsed")
+ || propertyName.endsWith(":nullable")) {
String realName = propertyName.substring(0, propertyName.indexOf(":"));
valueObject = results.get(realName);
} else {
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
index 86ba37a..8286f17 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
@@ -569,7 +569,7 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
}
}
- propertyName = stripNumberIdentifier(property.getName());
+ propertyName = stripNumberIdentifier(propertyName);
return new SimpleEntry<String, List<Object>>(propertyName, values);
}
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 08c12ba..a1eb285 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
@@ -3734,7 +3734,7 @@
<c:simple-property name="persist-delivery-count-before-delivery" required="false" type="boolean" readOnly="true" defaultValue="false" description="Whether the delivery count is persisted before delivery. False means that this only happens after a message has been cancelled. The default value is false."/>
<c:simple-property name="persist-id-cache" required="false" type="boolean" readOnly="true" defaultValue="true" description="Whether IDs are persisted to the journal. The default value is true."/>
<c:simple-property name="persistence-enabled" required="false" type="boolean" readOnly="true" defaultValue="true" description="Whether the server will use the file based journal for persistence. The default value is true."/>
- <c:list-property name="remoting-interceptors:nullable" required="false" readOnly="true" description="The list of interceptor classes used by this server." >
+ <c:list-property name="remoting-interceptors:nullable" required="false" readOnly="true" displayName="Remoting Interceptors" description="The list of interceptor classes used by this server." >
<c:simple-property name="remoting-interceptors" readOnly="true"/>
</c:list-property>
<c:simple-property name="run-sync-speed-test" required="false" type="boolean" readOnly="true" defaultValue="false" description="Whether on startup to perform a diagnostic test on how fast your disk can sync. Useful when determining performance issues. The default value is false."/>
@@ -4700,7 +4700,7 @@
<c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="true" defaultValue="-1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of -1 signifies an unlimited number of attempts. The default value is -1."/>
<c:simple-property name="retry-interval" required="false" type="long" readOnly="true" defaultValue="500" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 500."/>
<c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="true" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
- <c:list-property name="static-connectors:nullable" required="false" readOnly="true" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if 'discovery-group-name' is defined." >
+ <c:list-property name="static-connectors:nullable" required="false" readOnly="true" displayName="Static Connectors" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if 'discovery-group-name' is defined." >
<c:simple-property name="static-connectors" readOnly="true"/>
</c:list-property>
<c:simple-property name="use-duplicate-detection" required="false" type="boolean" readOnly="true" defaultValue="true" description="Whether the bridge will automatically insert a duplicate id property into each message that it forwards. The default value is true."/>
@@ -4823,7 +4823,7 @@
<c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="true" defaultValue="-1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of -1 signifies an unlimited number of attempts. The default value is -1."/>
<c:simple-property name="retry-interval" required="false" type="long" readOnly="true" defaultValue="2000" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 2000."/>
<c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="true" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
- <c:list-property name="static-connectors:nullable" required="false" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if 'discovery-group-name' is defined." >
+ <c:list-property name="static-connectors:nullable" required="false" displayName="Static Connectors" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if 'discovery-group-name' is defined." >
<c:simple-property name="static-connectors" />
</c:list-property>
<c:simple-property name="transformer-class-name" required="false" type="string" readOnly="true" description="The name of a user-defined class which implements the org.hornetq.core.server.cluster.Transformer interface."/>
@@ -6373,7 +6373,7 @@
<c:simple-property name="persist-delivery-count-before-delivery" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether the delivery count is persisted before delivery. False means that this only happens after a message has been cancelled. The default value is false."/>
<c:simple-property name="persist-id-cache" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether IDs are persisted to the journal. The default value is true."/>
<c:simple-property name="persistence-enabled" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the server will use the file based journal for persistence. The default value is true."/>
- <c:list-property name="remoting-interceptors:nullable" required="false" description="The list of interceptor classes used by this server." >
+ <c:list-property name="remoting-interceptors:nullable" required="false" displayName="Remoting Interceptors" description="The list of interceptor classes used by this server." >
<c:simple-property name="remoting-interceptors" />
</c:list-property>
<c:simple-property name="run-sync-speed-test" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether on startup to perform a diagnostic test on how fast your disk can sync. Useful when determining performance issues. The default value is false."/>
@@ -6829,7 +6829,7 @@
<c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="false" defaultValue="-1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of -1 signifies an unlimited number of attempts. The default value is -1."/>
<c:simple-property name="retry-interval" required="false" type="long" readOnly="false" defaultValue="500" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 500."/>
<c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
- <c:list-property name="static-connectors:nullable" required="false" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if 'discovery-group-name' is defined." >
+ <c:list-property name="static-connectors:nullable" required="false" displayName="Static Connectors" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if 'discovery-group-name' is defined." >
<c:simple-property name="static-connectors" />
</c:list-property>
<c:simple-property name="use-duplicate-detection" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the bridge will automatically insert a duplicate id property into each message that it forwards. The default value is true."/>
@@ -6918,7 +6918,7 @@
<c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="false" defaultValue="-1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of -1 signifies an unlimited number of attempts. The default value is -1."/>
<c:simple-property name="retry-interval" required="false" type="long" readOnly="false" defaultValue="2000" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 2000."/>
<c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
- <c:list-property name="static-connectors:nullable" required="false" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if 'discovery-group-name' is defined." >
+ <c:list-property name="static-connectors:nullable" required="false" displayName="Static Connectors" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if 'discovery-group-name' is defined." >
<c:simple-property name="static-connectors" />
</c:list-property>
<c:simple-property name="transformer-class-name" required="false" type="string" readOnly="false" description="The name of a user-defined class which implements the org.hornetq.core.server.cluster.Transformer interface."/>
@@ -9342,7 +9342,7 @@
<c:simple-property name="persist-delivery-count-before-delivery" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether the delivery count is persisted before delivery. False means that this only happens after a message has been cancelled. The default value is false."/>
<c:simple-property name="persist-id-cache" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether IDs are persisted to the journal. The default value is true."/>
<c:simple-property name="persistence-enabled" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the server will use the file based journal for persistence. The default value is true."/>
- <c:list-property name="remoting-interceptors:nullable" required="false" description="The list of interceptor classes used by this server.">
+ <c:list-property name="remoting-interceptors:nullable" required="false" displayName="Remoting Interceptors" description="The list of interceptor classes used by this server.">
<c:simple-property name="remoting-interceptors"/>
</c:list-property>
<c:simple-property name="run-sync-speed-test" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether on startup to perform a diagnostic test on how fast your disk can sync. Useful when determining performance issues. The default value is false."/>
@@ -11936,7 +11936,7 @@
<c:simple-property name="persist-delivery-count-before-delivery" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether the delivery count is persisted before delivery. False means that this only happens after a message has been cancelled. The default value is false."/>
<c:simple-property name="persist-id-cache" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether IDs are persisted to the journal. The default value is true."/>
<c:simple-property name="persistence-enabled" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the server will use the file based journal for persistence. The default value is true."/>
- <c:list-property name="remoting-interceptors:nullable" required="false" description="The list of interceptor classes used by this server.">
+ <c:list-property name="remoting-interceptors:nullable" required="false" displayName="Remoting Interceptors" description="The list of interceptor classes used by this server.">
<c:simple-property name="remoting-interceptors"/>
</c:list-property>
<c:simple-property name="run-sync-speed-test" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether on startup to perform a diagnostic test on how fast your disk can sync. Useful when determining performance issues. The default value is false."/>
@@ -12903,7 +12903,7 @@
<c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="false" defaultValue="-1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of -1 signifies an unlimited number of attempts. The default value is -1."/>
<c:simple-property name="retry-interval" required="false" type="long" readOnly="false" defaultValue="500" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 500."/>
<c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
- <c:list-property name="static-connectors:nullable" required="false" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if 'discovery-group-name' is defined.">
+ <c:list-property name="static-connectors:nullable" required="false" displayName="Static Connectors" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if 'discovery-group-name' is defined.">
<c:simple-property name="static-connectors"/>
</c:list-property>
<c:simple-property name="use-duplicate-detection" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the bridge will automatically insert a duplicate id property into each message that it forwards. The default value is true."/>
@@ -13026,7 +13026,7 @@
<c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="false" defaultValue="-1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of -1 signifies an unlimited number of attempts. The default value is -1."/>
<c:simple-property name="retry-interval" required="false" type="long" readOnly="false" defaultValue="2000" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 2000."/>
<c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
- <c:list-property name="static-connectors:nullable" required="false" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if 'discovery-group-name' is defined.">
+ <c:list-property name="static-connectors:nullable" required="false" displayName="Static Connectors" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if 'discovery-group-name' is defined.">
<c:simple-property name="static-connectors"/>
</c:list-property>
<c:simple-property name="transformer-class-name" required="false" type="string" readOnly="false" description="The name of a user-defined class which implements the org.hornetq.core.server.cluster.Transformer interface."/>
commit 15248b7c3099a46a3c41ccf487f391861d03a9bd
Author: John Sanda <jsanda(a)redhat.com>
Date: Tue Aug 14 15:13:24 2012 -0400
[BZ 846715] Taking groovy server plugin out of build
Until we find a new home for the groovy-script-server plugin, I am
taking it out of the build to get past errors when building with Java 7.
diff --git a/modules/enterprise/server/plugins/pom.xml b/modules/enterprise/server/plugins/pom.xml
index 4e4a30e..11f3b5c 100644
--- a/modules/enterprise/server/plugins/pom.xml
+++ b/modules/enterprise/server/plugins/pom.xml
@@ -78,7 +78,6 @@
<module>filetemplate-bundle</module>
<module>ant-bundle</module>
<module>validate-all-serverplugins</module>
- <module>groovy-script</module>
<module>packagetype-cli</module>
</modules>
commit 19cfeb90dcbf853a5aacf76656b4218af16d642f
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Aug 14 15:51:48 2012 +0200
[BZ 848066] - The group resource configuration page shows the config editor again
Also made the layout consistent with the single resource config page by
moving the button bar to the bottom of the page.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
index f6d6657..c5467b8 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
@@ -111,9 +111,8 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
save();
}
});
+ this.saveButton.disable();
buttonbar.addMember(saveButton);
- // The button bar will remain hidden until the configuration has been successfully loaded.
- buttonbar.setVisible(false);
return buttonbar;
}
@@ -125,7 +124,7 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
}
this.refreshing = true;
- this.saveButton.disable();
+
if (editor != null) {
editor.destroy();
removeMember(editor);
@@ -146,6 +145,7 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
this.editor.addPropertyValueChangeListener(this);
this.editor.setReadOnly(!this.resourcePermission.isConfigureWrite());
addMember(this.editor);
+ addMember(createButtonBar());
this.refreshing = false; // when we get here, we know we are done the refresh
}
}
@@ -197,7 +197,6 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
"The server did not return the configuration for one or more member resources.");
}
memberConfigurations.add(memberConfiguration);
- addMember(createButtonBar());
}
initEditor();
}
commit bbdcaee2ca23717a53277fe0bb479f761f46025e
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Aug 14 13:38:06 2012 +0200
[BZ 847804] - make sure to fetch the latest known resource config through
the proxy factory.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
index 10ee612..0199c77 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
@@ -491,10 +491,13 @@ public class ResourceClientProxy {
public Configuration getResourceConfiguration() {
if (!LazyLoadScenario.isShouldLoad())
return null;
-
- return remoteClient.getProxy(ConfigurationManagerRemote.class).getResourceConfiguration(
- remoteClient.getSubject(),
- resourceClientProxy.resourceId);
+
+ //make sure to fetch the latest known resource config. This ensures that
+ //the server goes out to the agent if there is no known config yet and thus
+ //giving the scripting user an always up-to-date info.
+ ResourceConfigurationUpdate update = remoteClient.getProxy(ConfigurationManagerRemote.class).getLatestResourceConfigurationUpdate(
+ remoteClient.getSubject(), resourceClientProxy.resourceId);
+ return update == null ? null : update.getConfiguration();
}
public ConfigurationDefinition getResourceConfigurationDefinition() {
commit 06a05b1371c11563b639d4faf74f27254668cd21
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon Aug 13 18:20:12 2012 -0500
[BZ 829329] Enable the discovery of server-group deployments after a domain deployment is sent to server groups.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
index ff55c8d..27b1133 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
@@ -552,6 +552,13 @@ public abstract class BaseServerComponent<T extends ResourceComponent<?>> extend
return result;
}
+ /**
+ * Requests a deferred child resource discovery for sub-resources of this server.
+ */
+ public void requestDeferredChildResourcesDiscovery() {
+ this.context.getInventoryContext().requestDeferredChildResourcesDiscovery();
+ }
+
@Override
public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> requests) throws Exception {
Set<MeasurementScheduleRequest> skmRequests = new HashSet<MeasurementScheduleRequest>(requests.size());
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DomainDeploymentComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DomainDeploymentComponent.java
index 6192c18..54cffbf 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DomainDeploymentComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/DomainDeploymentComponent.java
@@ -77,6 +77,14 @@ public class DomainDeploymentComponent extends DeploymentComponent implements Op
Result res = getASConnection().execute(operation, 120); // wait up to 2 minutes
if (res.isSuccess()) {
operationResult.setSimpleResult("Successfully deployed to server groups " + serverGroups);
+
+ //request the server to discover child resources to allow the discovery of the deployments
+ //on server groups immediately
+ if (this.context.getParentResourceComponent().getClass().isInstance(HostControllerComponent.class)) {
+ HostControllerComponent<?> hostController = (HostControllerComponent<?>) this.context
+ .getParentResourceComponent();
+ hostController.requestDeferredChildResourcesDiscovery();
+ }
} else {
operationResult.setErrorMessage("Deployment to server groups failed: " + res.getFailureDescription());
}
commit 1084a72ad31e8d78529ce8313e9e83c12b264ec7
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon Aug 13 16:36:03 2012 -0500
[BZ 839643] Removed the property from the profile subsystem definition until the AS7 issue is resolved. The property is not important for profiles since the value is read-only and used only by the managed server. The value can still be read from the managed server itself.
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 d27d432..08c12ba 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
@@ -6471,7 +6471,6 @@
<c:simple-property name="failover-on-server-shutdown" required="false" type="boolean" readOnly="false" description="True to fail over on server shutdown."/>
<c:simple-property name="group-id" required="false" type="string" readOnly="false" description="The group id."/>
<c:simple-property name="ha" required="true" type="boolean" readOnly="false" defaultValue="false" description="Whether the connection factory supports High Availability. The default value is false."/>
- <c:simple-property name="initial-message-packet-size" required="true" type="integer" readOnly="true" description="The initial size of messages created through this factory."/>
<c:simple-property name="max-retry-interval" required="false" type="long" readOnly="false" defaultValue="2000" description="The max retry interval. The default value is 2000."/>
<c:simple-property name="min-large-message-size" required="false" type="integer" readOnly="false" defaultValue="102400" description="The min large message size. The default value is 102400."/>
<c:simple-property name="pre-acknowledge" required="false" type="boolean" readOnly="false" defaultValue="false" description="True to pre-acknowledge. The default value is false."/>
commit 83c2b30289f9b11b2d0e25d02f51b1475ccd9aea
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Aug 13 16:34:19 2012 -0400
BZ 846385 - Make sure to use the JDG types only when he product found is JDG and the other way around.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SubsystemDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SubsystemDiscovery.java
index deec7a3..18eb274 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SubsystemDiscovery.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/SubsystemDiscovery.java
@@ -85,8 +85,9 @@ public class SubsystemDiscovery implements ResourceDiscoveryComponent<BaseCompon
lookForChildren = true;
}
- if (isIspnForJDG(context, confPath)) {
- log.debug("We have JDG as child, ignoring the {JBossAS7}Infinispan type");
+ // check if the parent is a JDG server. In this case ignore the as7 version
+ // of the type and vice versa
+ if (shouldSkipEntryWrtIspn(context, confPath)) {
return details;
}
@@ -190,40 +191,48 @@ public class SubsystemDiscovery implements ResourceDiscoveryComponent<BaseCompon
return details;
}
- private boolean isIspnForJDG(ResourceDiscoveryContext<BaseComponent<?>> context, String confPath) {
-
- // Check if this is ISPN
+ /**
+ * The as7 plugin and the JDG plugin both have a subsystem=infinispan. We need to decide
+ * which one to 'activate' depending on the type, plugin and the detected parent.
+ * Rules are:<ul>
+ * <li>If the parent is a host controller or such, there is no jdg available</li>
+ * <li>If parent is eap/as7, use the type from the as7 plugin</li>
+ * <li>If parent is a jdg server, use the type from the jdg plugin.</li>
+ * </ul>
+ *
+ *
+ * @param context The parent's resource component
+ * @param confPath The subsystem that got fed into discovery. Directly return is not subsystem=infinispan
+ * @return True if this subsystem should be skipped.
+ */
+ private boolean shouldSkipEntryWrtIspn(ResourceDiscoveryContext<BaseComponent<?>> context,
+ String confPath) {
+
+ String jdgPluginType = "JDG";
+
+ // If this is not subsystem=infinispan, we should not skip it at all
if (!"subsystem=infinispan".equals(confPath))
return false;
ResourceType ourType = context.getResourceType();
- if (ourType.getPlugin().equals("JDG"))
- return false;
+ boolean ourPluginTypeIsJdg = ourType.getPlugin().equals(jdgPluginType);
- if (!ourType.getName().equals("Infinispan"))
- return false;
+ String productType = context.getParentResourceComponent().pluginConfiguration.getSimpleValue("productType","AS7");
+ boolean isJdgProduct = jdgPluginType.equals(productType);
- // So we are {JBossAS7}Infinispan
- Set<ResourceType> parentTypes = ourType.getParentResourceTypes();
- ResourceType parent = null;
- for (ResourceType type : parentTypes) {
- if (type.getName().equals("JBossAS7 Standalone Server") && type.getPlugin().equals("JBossAS7")) {
- parent = type;
- break;
- }
- }
- if (parent==null)
+ if (ourPluginTypeIsJdg && isJdgProduct) {
+ if (log.isDebugEnabled())
+ log.debug("Ours is JDG and product is JDG");
return false;
+ }
- // So we are as7/eap and need to check now if we have a JDG plugin's ISPN resource as child
- boolean found = false;
- for (ResourceType type: parent.getChildResourceTypes()) {
- if (type.getPlugin().equals("JDG") && type.getName().equals("Infinispan")) {
- found = true;
- }
+ if (!ourPluginTypeIsJdg && !isJdgProduct) {
+ if (log.isDebugEnabled())
+ log.debug("Ours is not JDG (" + ourType.toString() + ") and product is not JDG (" + productType + ")");
+ return false;
}
- return found;
+ return true;
}
}
commit 1b2ba60b043c4c9e8feff247dcb0b53f342b9371
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon Aug 13 15:07:10 2012 -0500
[BZ 847674] Prevent exceptions from bubbling up because that is an indication the server is still down after the restart. Consider a thrown exception just a failed attempt to connect to the server, equivalent to success == false response for the test operation.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
index 9bc01f2..ff55c8d 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
@@ -406,12 +406,19 @@ public abstract class BaseServerComponent<T extends ResourceComponent<?>> extend
int count = 0;
while (!up) {
Operation op = new ReadAttribute(new Address(), "release-version");
- Result res = getASConnection().execute(op);
- if (res.isSuccess()) { // If op succeeds, server is not down
- up = true;
- } else if (count > 20) {
- break;
+ try{
+ Result res = getASConnection().execute(op);
+ if (res.isSuccess()) { // If op succeeds, server is not down
+ up = true;
+ } else if (count > 20) {
+ break;
+ }
+ } catch (Exception e) {
+ //do absolutely nothing
+ //if an exception is thrown that means the server is still down, so consider this
+ //a single failed attempt, equivalent to res.isSuccess == false
}
+
if (!up) {
try {
Thread.sleep(1000); // Wait 1s
commit 35d9093ac3c6118d1fc9ad5a8eef3a6bce6fe398
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Aug 13 14:18:10 2012 -0400
- Fix issues with Filtering UNCOMMITTED resources in a few NamedQueries.
- Remove unnecessary decl of ResourceGroupManager in test class, use the base class var.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/Availability.java b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/Availability.java
index 6158a74..d8a1083 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/Availability.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/Availability.java
@@ -104,7 +104,8 @@ import org.rhq.core.domain.resource.Resource;
+ " WHERE av.resource.id IN ( SELECT ires.id " //
+ " FROM ResourceGroup rg " //
+ " JOIN rg.implicitResources ires " //
- + " WHERE rg.id = :groupId AND ires.inventoryStatus = 'COMMITTED' ) " //
+ + " WHERE rg.id = :groupId ) " //
+ + " AND av.resource.inventoryStatus = 'COMMITTED' " //
+ " AND ((av.startTime <= :start AND (av.endTime >= :start OR av.endTime IS NULL) ) " /* availability straddles :start */
+ " OR (av.startTime BETWEEN :start AND :end)) " /* interval straddles availability.startTime */
+ "ORDER BY av.startTime ASC"), //
@@ -113,6 +114,7 @@ import org.rhq.core.domain.resource.Resource;
+ " JOIN av.resource res JOIN res.parentResource parent JOIN res.resourceType type " //
+ " WHERE parent.id = :parentId " //
+ " AND type.id = :typeId " //
+ + " AND av.resource.inventoryStatus = 'COMMITTED' " //
+ " AND ((av.startTime <= :start AND (av.endTime >= :start OR av.endTime IS NULL)) " /* availability straddles :start */
+ " OR (av.startTime BETWEEN :start AND :end)) " /* interval straddles availability.startTime */
+ "ORDER BY av.startTime ASC"), //
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/ResourceGroup.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/ResourceGroup.java
index 7b30aaf..937a891 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/ResourceGroup.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/ResourceGroup.java
@@ -197,7 +197,8 @@ import org.rhq.core.domain.tagging.Tag;
+ " AND res.id NOT IN ( SELECT explicitRes.id " //
+ " FROM ResourceGroup rg " //
+ " JOIN rg.explicitResources explicitRes " //
- + " WHERE rg.id = :groupId AND explicitRes.inventoryStatus = 'COMMITTED') ") })
+ + " WHERE rg.id = :groupId ) " //
+ + " AND res.inventoryStatus = 'COMMITTED' ") })
@SequenceGenerator(name = "id", sequenceName = "RHQ_RESOURCE_GROUP_ID_SEQ")
@Table(name = "RHQ_RESOURCE_GROUP")
@XmlAccessorType(XmlAccessType.FIELD)
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/GroupWithUncommittedTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/GroupWithUncommittedTest.java
index 8ef992d..3c57e5c 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/GroupWithUncommittedTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/test/GroupWithUncommittedTest.java
@@ -24,7 +24,6 @@ import java.util.List;
import javax.persistence.Query;
import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.rhq.core.domain.authz.Permission;
@@ -39,7 +38,6 @@ 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.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.test.LargeGroupTestBase;
import org.rhq.enterprise.server.test.TestServerCommunicationsService;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -49,7 +47,6 @@ import org.rhq.enterprise.server.util.SessionTestHelper;
public class GroupWithUncommittedTest extends LargeGroupTestBase {
private static final boolean TESTS_ENABLED = true;
- private ResourceGroupManagerLocal rgMgr;
private LargeGroupEnvironment env;
private class GroupAvailCounts {
@@ -77,11 +74,6 @@ public class GroupWithUncommittedTest extends LargeGroupTestBase {
protected void setupMockAgentServices(TestServerCommunicationsService agentServiceContainer) {
}
- @BeforeMethod
- public void getManagers() {
- this.rgMgr = LookupUtil.getResourceGroupManager();
- }
-
/**
* Remove the group and all its members.
*/
@@ -104,7 +96,8 @@ public class GroupWithUncommittedTest extends LargeGroupTestBase {
SessionTestHelper.simulateLogin(env.normalSubject);
// these queries were tweeked to filter uncommitted - see BZ 820981
- PageList<ResourceGroupComposite> results = rgMgr.findResourceGroupComposites(env.normalSubject, null, null,
+ 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;
@@ -263,7 +256,7 @@ public class GroupWithUncommittedTest extends LargeGroupTestBase {
assert resConfigCount == gac.visibleTotal;
assert pluginConfigCount == gac.visibleTotal;
- int groupSize = rgMgr.getExplicitGroupMemberCount(env.compatibleGroup.getId());
+ int groupSize = resourceGroupManager.getExplicitGroupMemberCount(env.compatibleGroup.getId());
assert resConfigCount == groupSize;
assert pluginConfigCount == groupSize;
commit ef1a7865118a3a76f7ee0ea1e119ba03f28c34ca
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Fri Aug 10 15:31:52 2012 -0500
[BZ 828329] Adding inventory context to a resource context.
Squashed commit of the following:
commit 14b7dd184880140d74d4658ffa0e62a575f27c4f
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 7 16:03:33 2012 -0500
[BZ 828329] Minor documentation updates and rewording.
commit 7f5aa39c22688ee935b23d2dad767ff03c41dc96
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Aug 7 14:45:31 2012 -0500
[BZ 828329] Removed plugin container specific classes. The regular will just block until the discovery processes completes, no data is returned to caller.
commit 2b17808e9bff072776c7ecada992d33c34203155
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon Aug 6 21:07:00 2012 -0500
[BZ 828329] The inventory context has now a deferred and a blocking method for requesting discovery. Also included are various other updates based on community feedback.
commit 816622e43c88c3b2bf751c1e2d9682d64556fdbb
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon Aug 6 10:38:34 2012 -0500
[BZ 828329] Added the possibility to start discovery scans from a resource context. The code executes a deffered service scan for children of the resource managed by the resource context.
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/InventoryContext.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/InventoryContext.java
new file mode 100644
index 0000000..ec1fab4
--- /dev/null
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/InventoryContext.java
@@ -0,0 +1,65 @@
+/*
+ * 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.core.pluginapi.inventory;
+
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public interface InventoryContext {
+
+ /**
+ * This method requests a deferred service discovery process for children of the resource. It requests the discovery
+ * process and returns immediately without waiting for results. The discovery process imports into inventory all discovered
+ * resources, so no further action is required from the caller.
+ *
+ * This method should be used by resources following an action (outside of create/delete children) that results
+ * in having additional children discoverable. A good example is an operation execution that enables extra functionality
+ * on the managed resource which in turn translates into having additional children available for management.
+ *
+ * Note: All services are discovered by the regular discovery process that runs every 24 hours. This method allows
+ * a resource to request an immediate run of the discovery process for child resources, rather than wait for the scheduled
+ * service discovery.
+ */
+ public void requestDeferredChildResourcesDiscovery();
+
+
+ /**
+ * This method requests a service discovery process for children of the resource. It schedules the discovery
+ * process and blocks until the discovery finishes. The discovery process imports into inventory all discovered
+ * resources, so no further action is required from the caller.
+ *
+ * This method should be used by resources following an action (outside of create/delete children) that results
+ * in having additional children discoverable. A good example is an operation execution that enables extra functionality
+ * on the managed resource which in turn translates into having additional children available for management. This method blocks
+ * until the discovery processes finishes, this includes committing resources to inventory. For additional processing,
+ * the calling resource can then request the list of child resources (it will include newly discovered resources too).
+ *
+ * Note: All services are discovered by the regular discovery process that runs every 24 hours. This method allows
+ * a resource to request an immediate run of the discovery process for child resources, rather than wait for the scheduled
+ * service discovery.
+ *
+ * @return discovered child resources
+ */
+ public void requestChildResourcesDiscovery();
+
+}
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java
index 4b21719..76ccf39 100644
--- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java
@@ -83,6 +83,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
private final OperationContext operationContext;
private final ContentContext contentContext;
private final AvailabilityContext availabilityContext;
+ private final InventoryContext inventoryContext;
private final PluginContainerDeployment pluginContainerDeployment;
private final ResourceTypeProcesses trackedProcesses;
@@ -152,7 +153,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
public ResourceContext(Resource resource, T parentResourceComponent, ResourceContext<?> parentResourceContext,
ResourceDiscoveryComponent<T> resourceDiscoveryComponent, SystemInfo systemInfo, File temporaryDirectory,
File dataDirectory, String pluginContainerName, EventContext eventContext, OperationContext operationContext,
- ContentContext contentContext, AvailabilityContext availabilityContext,
+ ContentContext contentContext, AvailabilityContext availabilityContext, InventoryContext inventoryContext,
PluginContainerDeployment pluginContainerDeployment) {
this.resourceKey = resource.getResourceKey();
@@ -177,6 +178,7 @@ public class ResourceContext<T extends ResourceComponent<?>> {
this.operationContext = operationContext;
this.contentContext = contentContext;
this.availabilityContext = availabilityContext;
+ this.inventoryContext = inventoryContext;
String parentResourceUuid = "";
if (resource.getParentResource() != null) {
@@ -505,6 +507,16 @@ public class ResourceContext<T extends ResourceComponent<?>> {
}
/**
+ * Returns an {@link InventoryContext} that allows the plugin to access inventory related functionality provided by the
+ * plugin container.
+ *
+ * @return the inventory context
+ */
+ public InventoryContext getInventoryContext() {
+ return inventoryContext;
+ }
+
+ /**
* @deprecated Use {@link AvailabilityContext#createAvailabilityCollectorRunnable(AvailabilityFacet, long)}
*/
public AvailabilityCollectorRunnable createAvailabilityCollectorRunnable(AvailabilityFacet availChecker,
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java
index 3c5b6a2..471978c 100644
--- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java
@@ -23,13 +23,13 @@
package org.rhq.core.pluginapi.upgrade;
import java.io.File;
-import java.util.concurrent.Executor;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.pluginapi.availability.AvailabilityContext;
import org.rhq.core.pluginapi.content.ContentContext;
import org.rhq.core.pluginapi.event.EventContext;
+import org.rhq.core.pluginapi.inventory.InventoryContext;
import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
import org.rhq.core.pluginapi.inventory.ResourceContext;
@@ -60,11 +60,11 @@ public class ResourceUpgradeContext<T extends ResourceComponent<?>> extends Reso
T parentResourceComponent, ResourceDiscoveryComponent<T> resourceDiscoveryComponent, SystemInfo systemInfo,
File temporaryDirectory, File dataDirectory, String pluginContainerName, EventContext eventContext,
OperationContext operationContext, ContentContext contentContext, AvailabilityContext availabilityContext,
- PluginContainerDeployment pluginContainerDeployment) {
+ InventoryContext inventoryContext, PluginContainerDeployment pluginContainerDeployment) {
super(resource, parentResourceComponent, parentResourceContext, resourceDiscoveryComponent, systemInfo,
temporaryDirectory, dataDirectory, pluginContainerName, eventContext, operationContext, contentContext,
- availabilityContext, pluginContainerDeployment);
+ availabilityContext, inventoryContext, pluginContainerDeployment);
this.resourceConfiguration = resource.getResourceConfiguration();
this.name = resource.getName();
diff --git a/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java b/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java
index fe194c9..118d514 100644
--- a/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java
+++ b/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java
@@ -86,7 +86,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null,
- mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null);
+ mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -152,7 +152,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parent1ResourceContext, null,
- null, mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null);
+ null, mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -206,7 +206,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null,
- mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null);
+ mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -260,7 +260,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null,
- mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null);
+ mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -314,7 +314,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null,
- mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null);
+ mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getResourceDataDirectory();
@@ -377,7 +377,7 @@ public class ResourceContextTest {
//create object to test and inject required dependencies
ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parent1ResourceContext, null,
- null, mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null);
+ null, mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null, null);
//run code under test
File result = objectUnderTest.getFutureChildResourceDataDirectory(inputChildResourceKey);
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryContextImpl.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryContextImpl.java
new file mode 100644
index 0000000..460a827
--- /dev/null
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryContextImpl.java
@@ -0,0 +1,57 @@
+/*
+ * 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.core.pc.inventory;
+
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.pc.PluginContainer;
+import org.rhq.core.pluginapi.inventory.InventoryContext;
+
+/**
+ * @author Stefan Negrea
+ *
+ */
+public class InventoryContextImpl implements InventoryContext {
+
+ private final Resource resource;
+
+ /**
+ * @param resource resource
+ */
+ public InventoryContextImpl(Resource resource) {
+ this.resource = resource;
+ }
+
+ /* (non-Javadoc)
+ * @see org.rhq.core.pluginapi.inventory.InventoryContext#discoverChildResources()
+ */
+ @Override
+ public void requestDeferredChildResourcesDiscovery() {
+ PluginContainer.getInstance().getInventoryManager().executeServiceScanDeferred(resource);
+ }
+
+ /* (non-Javadoc)
+ * @see org.rhq.core.pluginapi.inventory.InventoryContext#requestChildResourcesDiscovery()
+ */
+ @Override
+ public void requestChildResourcesDiscovery() {
+ PluginContainer.getInstance().getInventoryManager().executeServiceScanImmediately(resource);
+ }
+}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
index 8cd3859..b3f7fa9 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
@@ -108,6 +108,7 @@ import org.rhq.core.pluginapi.event.EventContext;
import org.rhq.core.pluginapi.inventory.ClassLoaderFacet;
import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
+import org.rhq.core.pluginapi.inventory.InventoryContext;
import org.rhq.core.pluginapi.inventory.ManualAddFacet;
import org.rhq.core.pluginapi.inventory.ProcessScanResult;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
@@ -575,10 +576,29 @@ public class InventoryManager extends AgentService implements ContainerService,
}
}
+ @NotNull
+ public InventoryReport executeServiceScanImmediately(Resource resource) {
+ try {
+ RuntimeDiscoveryExecutor discoveryExecutor = new RuntimeDiscoveryExecutor(this, this.configuration,
+ resource);
+ return inventoryThreadPoolExecutor.submit((Callable<InventoryReport>) discoveryExecutor).get();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Service scan execution was interrupted", e);
+ } catch (ExecutionException e) {
+ // Should never happen, reports are always generated, even if they're just to report the error
+ throw new RuntimeException("Unexpected exception", e);
+ }
+ }
+
public void executeServiceScanDeferred() {
inventoryThreadPoolExecutor.submit((Callable<InventoryReport>) this.serviceScanExecutor);
}
+ public void executeServiceScanDeferred(Resource resource) {
+ RuntimeDiscoveryExecutor discoveryExecutor = new RuntimeDiscoveryExecutor(this, this.configuration, resource);
+ inventoryThreadPoolExecutor.submit((Callable<InventoryReport>) discoveryExecutor);
+ }
+
/** this will NOT send a availability report up to the server! */
public AvailabilityReport executeAvailabilityScanImmediately(boolean changedOnlyReport) {
return executeAvailabilityScanImmediately(changedOnlyReport, false);
@@ -1296,7 +1316,7 @@ public class InventoryManager extends AgentService implements ContainerService,
/**
* Get the parent resource's children, ensuring we use the resource container version of the resource, because
* the container's resource is guaranteed to be up to date.
- *
+ *
* @param parentResource
* @return the children. parentResouce children if there is no container. May be empty. Not null.
*/
@@ -1304,13 +1324,13 @@ public class InventoryManager extends AgentService implements ContainerService,
return getContainerChildren(parentResource, getResourceContainer(parentResource));
}
- /**
+ /**
* Get the parent resource's children, ensuring we use the resource container version of the resource, because
* the container's resource is guaranteed to be up to date.
- *
+ *
* @param parentResource
* @param parentContainer
- * @return the children, empty if parentContainer is null or there are no children. not null.
+ * @return the children, empty if parentContainer is null or there are no children. not null.
* @return the children, may be empty, not null.
*/
public Set<Resource> getContainerChildren(Resource parentResource, ResourceContainer container) {
@@ -1784,6 +1804,7 @@ public class InventoryManager extends AgentService implements ContainerService,
getOperationContext(resource), // for operation manager access
getContentContext(resource), // for content manager access
getAvailabilityContext(resource, this.availabilityCollectors), // for components that want to perform async avail checking
+ getInventoryContext(resource),
this.configuration.getPluginContainerDeployment()); // helps components make determinations of what to do
}
@@ -1803,6 +1824,7 @@ public class InventoryManager extends AgentService implements ContainerService,
getOperationContext(resource), // for operation manager access
getContentContext(resource), // for content manager access
getAvailabilityContext(resource, this.availabilityCollectors), // for components that want avail manager access
+ getInventoryContext(resource),
this.configuration.getPluginContainerDeployment()); // helps components make determinations of what to do
}
@@ -1853,7 +1875,7 @@ public class InventoryManager extends AgentService implements ContainerService,
return this.platform;
}
} else {
- // don't use container children here, the caller is providing the desired resources
+ // don't use container children here, the caller is providing the desired resources
for (Resource child : parent.getChildResources()) {
if (child != null && matches(resource, child)) {
return child;
@@ -2376,7 +2398,7 @@ public class InventoryManager extends AgentService implements ContainerService,
/**
* The resource upgrade should only occur during the {@link #initialize()} method and should be
* switched off at all other times.
- *
+ *
* @return true if resource upgrade is currently active, false otherwise
*/
public boolean isResourceUpgradeActive() {
@@ -2644,6 +2666,21 @@ public class InventoryManager extends AgentService implements ContainerService,
return availabilityContext;
}
+ /**
+ * Create inventory context for a resource.
+ *
+ * @param resource the resource
+ * @return the inventory context
+ */
+ private InventoryContext getInventoryContext(Resource resource) {
+ if (null == resource.getUuid() || resource.getUuid().isEmpty()) {
+ log.error("RESOURCE UUID IS NOT SET! Inventory features may not work!");
+ }
+
+ InventoryContext inventoryContext = new InventoryContextImpl(resource);
+ return inventoryContext;
+ }
+
private void updateResourceVersion(Resource resource, String version) {
String existingVersion = resource.getVersion();
boolean versionChanged = (existingVersion != null) ? !existingVersion.equals(version) : version != null;
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/bundle/BundleManagerTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/bundle/BundleManagerTest.java
index b6b39e0..4b37c89 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/bundle/BundleManagerTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/bundle/BundleManagerTest.java
@@ -478,7 +478,7 @@ public class BundleManagerTest {
@SuppressWarnings("unchecked")
private static class MockResourceContext extends ResourceContext {
public MockResourceContext(Resource resource) {
- super(resource, null, null, null, null, null, null, null, null, null, null, null, null);
+ super(resource, null, null, null, null, null, null, null, null, null, null, null, null, null);
}
}
}
\ No newline at end of file
diff --git a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
index 05ebc2f..daf5463 100644
--- a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
+++ b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
@@ -101,7 +101,8 @@ public class AntBundlePluginComponentTest {
resource.setUuid(UUID.randomUUID().toString());
@SuppressWarnings({ "rawtypes", "unchecked" })
ResourceContext<?> context = new ResourceContext(resource, null, null, null,
- SystemInfoFactory.createJavaSystemInfo(), tmpDir, null, "antBundleTestPC", null, null, null, null, null);
+ SystemInfoFactory.createJavaSystemInfo(), tmpDir, null, "antBundleTestPC", null, null, null, null, null,
+ null);
this.plugin.start(context);
}
diff --git a/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java b/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java
index b9622c6..050aa2e 100644
--- a/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java
+++ b/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java
@@ -52,6 +52,7 @@ import org.rhq.core.pc.availability.AvailabilityContextImpl;
import org.rhq.core.pc.content.ContentContextImpl;
import org.rhq.core.pc.event.EventContextImpl;
import org.rhq.core.pc.event.EventManager;
+import org.rhq.core.pc.inventory.InventoryContextImpl;
import org.rhq.core.pc.inventory.ResourceContainer;
import org.rhq.core.pc.operation.OperationContextImpl;
import org.rhq.core.pluginapi.availability.AvailabilityContext;
@@ -59,6 +60,7 @@ import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
import org.rhq.core.pluginapi.content.ContentContext;
import org.rhq.core.pluginapi.event.EventContext;
import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.InventoryContext;
import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
import org.rhq.core.pluginapi.inventory.ProcessScanResult;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
@@ -141,6 +143,7 @@ public abstract class ComponentTest {
private List<ProcessInfo> processInfo = Collections.emptyList();
private PluginDescriptor pluginDescriptor;
private AvailabilityContext availabilityContext;
+ private InventoryContext inventoryContext;
/**
@@ -277,11 +280,13 @@ public abstract class ComponentTest {
ResourceComponent component = (ResourceComponent) Class.forName(rclassname).newInstance();
availabilityContext = new AvailabilityContextImpl(cresource,availCollectorThreadPool);
+ inventoryContext = new InventoryContextImpl(cresource);
+
EventContext eventContext = new EventContextImpl(resource);
ResourceContext context = new ResourceContext(cresource, parentComponent,
null, rdc, systemInfo, temporaryDirectory, dataDirectory,
pluginContainerName, eventContext, operationContext, contentContext,
- availabilityContext, pluginContainerDeployment);
+ availabilityContext, inventoryContext, pluginContainerDeployment);
component.start(context);
components.put(component, cresource);
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
index 8b85deb..9bc01f2 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
@@ -540,6 +540,7 @@ public abstract class BaseServerComponent<T extends ResourceComponent<?>> extend
+ " server with key [" + context.getResourceKey() + "].");
context.getAvailabilityContext().requestAvailabilityCheck();
+ context.getInventoryContext().requestDeferredChildResourcesDiscovery();
return result;
}
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java
index 8ddb308..28a8688 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/nonpc/UploadAndDeployTest.java
@@ -345,7 +345,8 @@ public class UploadAndDeployTest extends AbstractIntegrationTest {
resource.setUuid(UUID.randomUUID().toString());
StandaloneASComponent parentComponent = new StandaloneASComponent();
parentComponent.setConnection(getASConnection());
- ResourceContext context = new ResourceContext(resource,parentComponent,null,null,null,null,null,null,null,null,null,null,null);
+ ResourceContext context = new ResourceContext(resource, parentComponent, null, null, null, null, null, null,
+ null, null, null, null, null, null);
bc.start(context);
String bytes_value = uploadToAs(TEST_WAR_PATH);
@@ -379,7 +380,8 @@ public class UploadAndDeployTest extends AbstractIntegrationTest {
resource.setUuid(UUID.randomUUID().toString());
StandaloneASComponent parentComponent = new StandaloneASComponent();
parentComponent.setConnection(getASConnection());
- ResourceContext context = new ResourceContext(resource,parentComponent,null,null,null,null,null,null,null,null,null,null,null);
+ ResourceContext context = new ResourceContext(resource, parentComponent, null, null, null, null, null, null,
+ null, null, null, null, null, null);
bc.start(context);
String bytes_value = uploadToAs(TEST_WAR_PATH);
diff --git a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
index 511d686..610cb61 100644
--- a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
+++ b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
@@ -71,6 +71,7 @@ import org.rhq.core.pc.availability.AvailabilityContextImpl;
import org.rhq.core.pc.content.ContentContextImpl;
import org.rhq.core.pc.event.EventContextImpl;
import org.rhq.core.pc.event.EventManager;
+import org.rhq.core.pc.inventory.InventoryContextImpl;
import org.rhq.core.pc.inventory.ResourceContainer;
import org.rhq.core.pc.operation.OperationContextImpl;
import org.rhq.core.pluginapi.availability.AvailabilityContext;
@@ -78,6 +79,7 @@ import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
import org.rhq.core.pluginapi.content.ContentContext;
import org.rhq.core.pluginapi.event.EventContext;
import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.InventoryContext;
import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
import org.rhq.core.pluginapi.inventory.ProcessScanResult;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
@@ -294,12 +296,13 @@ public abstract class ComponentTest {
ResourceComponent component = (ResourceComponent) Class.forName(rclassname).newInstance();
AvailabilityContext availContext = new AvailabilityContextImpl(cresource,availCollectorThreadPool);
+ InventoryContext inventoryContext = new InventoryContextImpl(cresource);
EventContext eventContext = new EventContextImpl(resource);
ResourceContext context = new ResourceContext(cresource, parentComponent,
null, rdc, systemInfo, temporaryDirectory, dataDirectory,
pluginContainerName, eventContext, operationContext, contentContext,
- availContext, pluginContainerDeployment);
+ availContext, inventoryContext,pluginContainerDeployment);
component.start(context);
components.put(component, cresource);
diff --git a/modules/plugins/oracle/src/test/java/org/rhq/plugins/oracle/ComponentTest.java b/modules/plugins/oracle/src/test/java/org/rhq/plugins/oracle/ComponentTest.java
index dfee1b6..569bd09 100644
--- a/modules/plugins/oracle/src/test/java/org/rhq/plugins/oracle/ComponentTest.java
+++ b/modules/plugins/oracle/src/test/java/org/rhq/plugins/oracle/ComponentTest.java
@@ -36,12 +36,14 @@ import org.rhq.core.pc.availability.AvailabilityContextImpl;
import org.rhq.core.pc.content.ContentContextImpl;
import org.rhq.core.pc.event.EventContextImpl;
import org.rhq.core.pc.event.EventManager;
+import org.rhq.core.pc.inventory.InventoryContextImpl;
import org.rhq.core.pc.operation.OperationContextImpl;
import org.rhq.core.pc.upgrade.plugins.multi.base.NothingDiscoveringDiscoveryComponent;
import org.rhq.core.pluginapi.availability.AvailabilityContext;
import org.rhq.core.pluginapi.content.ContentContext;
import org.rhq.core.pluginapi.event.EventContext;
import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.InventoryContext;
import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
import org.rhq.core.pluginapi.inventory.ResourceContext;
@@ -133,9 +135,11 @@ public abstract class ComponentTest {
ResourceDiscoveryComponent resourceDiscoveryComponent = new NothingDiscoveringDiscoveryComponent();
EventContext eventContext = new EventContextImpl(resource);
AvailabilityContext availContext = new AvailabilityContextImpl(resource, Executors.newCachedThreadPool());
+ InventoryContext inventoryContext = new InventoryContextImpl(resource);
ResourceContext context = new ResourceContext(resource, parentResourceComponent, parentResourceContext,
resourceDiscoveryComponent, systemInfo, temporaryDirectory, dataDirectory, pluginContainerName,
- eventContext, operationContext, contentContext, availContext, pluginContainerDeployment);
+ eventContext, operationContext, contentContext, availContext, inventoryContext,
+ pluginContainerDeployment);
component.start(context);
resourceDiscoveryContext = new ResourceDiscoveryContext(resourceType, parentResourceComponent, context,
@@ -169,9 +173,10 @@ public abstract class ComponentTest {
EventContext eventContext = new EventContextImpl(resource);
AvailabilityContext availContext = new AvailabilityContextImpl(resource, Executors.newCachedThreadPool());
+ InventoryContext inventoryContext = new InventoryContextImpl(resource);
ResourceContext context = new ResourceContext(resource, component, parentContext, resourceDiscoveryComponent,
systemInfo, temporaryDirectory, dataDirectory, pluginContainerName, eventContext, operationContext,
- contentContext, availContext, pluginContainerDeployment);
+ contentContext, availContext, inventoryContext, pluginContainerDeployment);
ResourceDiscoveryContext resourceDiscoveryContext = new ResourceDiscoveryContext(resourceType, component,
context, systemInfo, Collections.emptyList(), Collections.emptyList(), pluginContainerName,
pluginContainerDeployment);
@@ -200,9 +205,10 @@ public abstract class ComponentTest {
EventContext eventContext = new EventContextImpl(resource);
AvailabilityContext availContext = new AvailabilityContextImpl(resource, Executors.newCachedThreadPool());
+ InventoryContext inventoryContext = new InventoryContextImpl(resource);
ResourceContext context = new ResourceContext(cresource, parentComponent, parentContext,
resourceDiscoveryComponent, systemInfo, temporaryDirectory, dataDirectory, pluginContainerName,
- eventContext, operationContext, contentContext, availContext, pluginContainerDeployment);
+ eventContext, operationContext, contentContext, availContext, inventoryContext, pluginContainerDeployment);
component.start(context);
components.put(component, cresource);
diff --git a/modules/plugins/snmptrapd/src/test/java/org/rhq/plugins/snmptrapd/ComponentTest.java b/modules/plugins/snmptrapd/src/test/java/org/rhq/plugins/snmptrapd/ComponentTest.java
index b023609..cd90737 100644
--- a/modules/plugins/snmptrapd/src/test/java/org/rhq/plugins/snmptrapd/ComponentTest.java
+++ b/modules/plugins/snmptrapd/src/test/java/org/rhq/plugins/snmptrapd/ComponentTest.java
@@ -24,11 +24,13 @@ import org.rhq.core.pc.availability.AvailabilityContextImpl;
import org.rhq.core.pc.content.ContentContextImpl;
import org.rhq.core.pc.event.EventContextImpl;
import org.rhq.core.pc.event.EventManager;
+import org.rhq.core.pc.inventory.InventoryContextImpl;
import org.rhq.core.pc.operation.OperationContextImpl;
import org.rhq.core.pc.upgrade.plugins.multi.base.NothingDiscoveringDiscoveryComponent;
import org.rhq.core.pluginapi.availability.AvailabilityContext;
import org.rhq.core.pluginapi.content.ContentContext;
import org.rhq.core.pluginapi.event.EventContext;
+import org.rhq.core.pluginapi.inventory.InventoryContext;
import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
import org.rhq.core.pluginapi.inventory.ResourceContext;
@@ -97,9 +99,10 @@ public abstract class ComponentTest {
ContentContext contentContext = new ContentContextImpl(0);
PluginContainerDeployment pluginContainerDeployment = null;
AvailabilityContext availContext = new AvailabilityContextImpl(resource, Executors.newCachedThreadPool());
+ InventoryContext inventoryContext = new InventoryContextImpl(resource);
ResourceContext context = new ResourceContext(resource, parentResourceComponent, parentResourceContext,
resourceDiscoveryComponent, systemInfo, temporaryDirectory, dataDirectory, pluginContainerName,
- eventContext, operationContext, contentContext, availContext, pluginContainerDeployment);
+ eventContext, operationContext, contentContext, availContext, inventoryContext, pluginContainerDeployment);
Assert.assertNotNull(context.getEventContext());
component.start(context);
}
commit 579776f3fe66776d0b013bf13eba8114fe7ff89a
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu Aug 9 13:53:35 2012 -0700
Remove unused parameter. Ended up not needing the criteria parameter.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
index 9f640dc..e269475 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
@@ -26,7 +26,6 @@ import static org.rhq.enterprise.gui.coregui.client.inventory.groups.ResourceGro
import static org.rhq.enterprise.gui.coregui.client.inventory.groups.ResourceGroupDataSourceField.PLUGIN;
import static org.rhq.enterprise.gui.coregui.client.inventory.groups.ResourceGroupDataSourceField.TYPE;
-import java.util.ArrayList;
import java.util.List;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -126,8 +125,7 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
processResponse(request.getRequestId(), response);
}
- private PageList<ResourceGroupComposite> filterEmptyMemberGroups(ResourceGroupCriteria groupCriteria,
- PageList<ResourceGroupComposite> result){
+ private PageList<ResourceGroupComposite> filterEmptyMemberGroups(PageList<ResourceGroupComposite> result){
PageList<ResourceGroupComposite> pageList = new PageList<ResourceGroupComposite>(result.getPageControl());
@@ -141,7 +139,7 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
}
public void onSuccess(PageList<ResourceGroupComposite> result) {
- PageList<ResourceGroupComposite> filteredResult = filterEmptyMemberGroups(criteria,result);
+ PageList<ResourceGroupComposite> filteredResult = filterEmptyMemberGroups(result);
response.setData(buildRecords(filteredResult));
response.setTotalRows(filteredResult.getTotalSize()); // for paging to work we have to specify size of full result set
processResponse(request.getRequestId(), response);
commit 901fc3d0ecb9b5f800c6c5c3dc59dabebb61a87c
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed Aug 8 17:33:53 2012 -0700
Take out search optimization of not doing a search if the search term is the same as the last search. This is causing some stickiness and sometimes the search doesnt run if it was already cached and it thinks it has done a search but it hasnt (probably because of timing issues).
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
index f56c81e..e0e004d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
@@ -48,7 +48,6 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message;
*/
public class BasicSearchStrategy extends AbstractSearchStrategy {
- private String lastExpression;
public BasicSearchStrategy(EnhancedSearchBar searchBar) {
super(searchBar);
@@ -175,12 +174,9 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
private void getTabAwareSearchSuggestions(final SearchSubsystem searchSubsystem, final String expression,
int caretPosition) {
- if (null != expression && expression.equals(lastExpression)) {
- // short-circuit if we dont really need to do a search
- Log.debug("search tab aware Suggestions: ignoring duplicate search for: " + expression);
+ if(null == expression || expression.isEmpty()){
return;
}
- lastExpression = expression;
final long suggestStart = System.currentTimeMillis();
commit 6b621264526d1490d423e14e482ff18b3ea2f85f
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri Aug 10 09:24:26 2012 -0400
[Bug 847138 - RFE: Add indication that resource tree is loading or expanding]
Replace the default TreeGrid loading message, which was weak and only showed
up briefly at initial tree creation, with more robust loading... message
display when loading, expanding or updating the tree. This helps situations
where fairly large tree load/updates take place, typically due to large
numbers of siblings or Autogroup creation/manipulation.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
index 2a5b827..5c58a70 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
@@ -35,6 +35,7 @@ import com.smartgwt.client.data.fields.DataSourceTextField;
import com.smartgwt.client.rpc.RPCResponse;
import com.smartgwt.client.types.DSDataFormat;
import com.smartgwt.client.types.DSProtocol;
+import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.tree.Tree;
import com.smartgwt.client.widgets.tree.TreeGrid;
import com.smartgwt.client.widgets.tree.TreeNode;
@@ -71,10 +72,12 @@ public class ResourceTreeDatasource extends DataSource {
// the encompassing grid. It's unfortunate to have the DS know about the encompassing TreeGrid
// but we have a situation in which a new AG node needs to be able to access its parent TreeNode by ID.
private TreeGrid treeGrid;
+ private Label loadingLabel;
private ResourceGWTServiceAsync resourceService = GWTServiceLookup.getResourceService();
- public ResourceTreeDatasource(List<Resource> initialData, List<Resource> lockedData, TreeGrid treeGrid) {
+ public ResourceTreeDatasource(List<Resource> initialData, List<Resource> lockedData, TreeGrid treeGrid,
+ Label loadingLabel) {
this.setClientOnly(false);
this.setDataProtocol(DSProtocol.CLIENTCUSTOM);
this.setDataFormat(DSDataFormat.CUSTOM);
@@ -82,6 +85,7 @@ public class ResourceTreeDatasource extends DataSource {
this.initialData = initialData;
this.lockedData = (null != lockedData) ? lockedData : new ArrayList<Resource>();
this.treeGrid = treeGrid;
+ this.loadingLabel = loadingLabel;
DataSourceField idDataField = new DataSourceTextField("id", MSG.common_title_id());
idDataField.setPrimaryKey(true);
@@ -131,6 +135,8 @@ public class ResourceTreeDatasource extends DataSource {
public void executeFetch(final String requestId, final DSRequest request, final DSResponse response) {
//final long start = System.currentTimeMillis();
+ loadingLabel.show();
+
final String parentResourceId = request.getCriteria().getAttribute("parentId");
//com.allen_sauer.gwt.log.client.Log.info("All attributes: " + Arrays.toString(request.getCriteria().getAttributes()));
@@ -148,6 +154,8 @@ public class ResourceTreeDatasource extends DataSource {
processResponse(requestId, response);
}
+ loadingLabel.hide();
+
} else {
Log.debug("ResourceTreeDatasource: Loading Resource [" + parentResourceId + "]...");
@@ -161,6 +169,8 @@ public class ResourceTreeDatasource extends DataSource {
CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_loadFailed_children(), caught);
response.setStatus(RPCResponse.STATUS_FAILURE);
processResponse(requestId, response);
+
+ loadingLabel.hide();
}
public void onSuccess(PageList<Resource> result) {
@@ -182,6 +192,8 @@ public class ResourceTreeDatasource extends DataSource {
TreeNode[] treeNodes = buildNodes(result, lockedData, treeGrid);
response.setData(treeNodes);
processResponse(requestId, response);
+
+ loadingLabel.hide();
}
});
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
index 2393f8d..c38e77a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
@@ -43,6 +43,7 @@ import com.smartgwt.client.data.DSCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.types.SelectionStyle;
+import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.SelectionChangedHandler;
import com.smartgwt.client.widgets.grid.events.SelectionEvent;
@@ -79,6 +80,7 @@ import org.rhq.core.domain.resource.composite.ResourcePermission;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.LinkManager;
import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
import org.rhq.enterprise.gui.coregui.client.ViewId;
@@ -111,6 +113,7 @@ public class ResourceTreeView extends LocatableVLayout {
private TreeGrid treeGrid;
private String selectedNodeId;
+ private Label loadingLabel;
private Resource rootResource;
@@ -131,11 +134,17 @@ public class ResourceTreeView extends LocatableVLayout {
@Override
public void onInit() {
+ // manually handle a loading... message at initial load and also subsequent fetches
+ loadingLabel = new Label(MSG.common_msg_loading());
+ loadingLabel.setIcon(ImageManager.getLoadingIcon());
+ loadingLabel.setHeight(20);
+ loadingLabel.hide();
+ addMember(loadingLabel);
+
// TODO (ips): Are we intentionally avoiding calling super.onInit() here? If so, why?
}
private void buildTree() {
-
treeGrid = new CustomResourceTreeGrid(getLocatorId());
treeGrid.setOpenerImage("resources/dir.png");
@@ -149,6 +158,8 @@ public class ResourceTreeView extends LocatableVLayout {
treeGrid.setShowRollOver(false);
treeGrid.setSortField("name");
treeGrid.setShowHeader(false);
+ // disable what the tree grid may do, defer to loadingLabel to handle all of our cases
+ treeGrid.setLoadingDataMessage(null);
treeGrid.setLeaveScrollbarGap(false);
@@ -190,12 +201,15 @@ public class ResourceTreeView extends LocatableVLayout {
disable();
try {
+ loadingLabel.show();
getAutoGroupBackingGroup(agNode, new AsyncCallback<ResourceGroup>() {
public void onSuccess(ResourceGroup result) {
+ loadingLabel.hide();
renderAutoGroup(result);
}
public void onFailure(Throwable caught) {
+ loadingLabel.hide();
// Make sure to re-enable ourselves.
enable();
CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_loadFailed_selection(),
@@ -203,6 +217,7 @@ public class ResourceTreeView extends LocatableVLayout {
}
});
} catch (RuntimeException re) {
+ loadingLabel.hide();
// Make sure to re-enable ourselves.
enable();
CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_loadFailed_selection(), re);
@@ -281,9 +296,11 @@ public class ResourceTreeView extends LocatableVLayout {
criteria.addFilterResourceTypeId(agNode.getResourceType().getId());
criteria.addFilterAutoGroupParentResourceId(agNode.getParentResource().getId());
criteria.addFilterVisible(false);
+ loadingLabel.show();
resourceGroupService.findResourceGroupsByCriteria(criteria, new AsyncCallback<PageList<ResourceGroup>>() {
public void onFailure(Throwable caught) {
+ loadingLabel.hide();
callback.onFailure(new RuntimeException(MSG.view_tree_common_loadFailed_node(), caught));
}
@@ -299,11 +316,13 @@ public class ResourceTreeView extends LocatableVLayout {
resourceGroupService.createPrivateResourceGroup(backingGroup, childIds,
new AsyncCallback<ResourceGroup>() {
public void onFailure(Throwable caught) {
+ loadingLabel.hide();
callback.onFailure(new RuntimeException(MSG.view_tree_common_loadFailed_create(),
caught));
}
public void onSuccess(ResourceGroup result) {
+ loadingLabel.hide();
// store a map entry from backingGroupId to AGTreeNode so we can easily
// get back to this node given the id of the backing group (from the viewpath)
autoGroupNodeMap.put(result.getId(), agNode);
@@ -322,11 +341,13 @@ public class ResourceTreeView extends LocatableVLayout {
resourceGroupService.setAssignedResources(backingGroup.getId(), childIds, false,
new AsyncCallback<Void>() {
public void onFailure(Throwable caught) {
+ loadingLabel.hide();
callback.onFailure(new RuntimeException(MSG.view_tree_common_loadFailed_update(),
caught));
}
public void onSuccess(Void result) {
+ loadingLabel.hide();
callback.onSuccess(backingGroup);
}
});
@@ -895,7 +916,6 @@ public class ResourceTreeView extends LocatableVLayout {
// This is the case where the tree was previously loaded and we get fired to look at a different
// node in the same tree and just have to switch the selection
updateSelection(isRefresh);
-
} else {
// This is for cases where we have to load the tree fresh including down to the currently visible node
loadTree(selectedResourceId, true, null);
@@ -913,10 +933,12 @@ public class ResourceTreeView extends LocatableVLayout {
final ResourceGWTServiceAsync resourceService = GWTServiceLookup.getResourceService();
// This is an expensive call, but loads all nodes that are visible in the tree given a selected resource
+ loadingLabel.show();
resourceService.getResourceLineageAndSiblings(selectedResourceId,
new AsyncCallback<List<ResourceLineageComposite>>() {
public void onFailure(Throwable caught) {
+ loadingLabel.hide();
boolean resourceDoesNotExist = caught.getMessage().contains("ResourceNotFoundException");
// If a Resource with the specified id does not exist, don't emit an error, since
// ResourceDetailView.loadSelectedItem() will take care of emitting one.
@@ -953,7 +975,8 @@ public class ResourceTreeView extends LocatableVLayout {
setRootResource(root);
// seed datasource with initial resource list and which ancestor resources are locked
- ResourceTreeDatasource dataSource = new ResourceTreeDatasource(lineage, lockedData, treeGrid);
+ ResourceTreeDatasource dataSource = new ResourceTreeDatasource(lineage, lockedData, treeGrid,
+ loadingLabel);
treeGrid.setDataSource(dataSource);
addMember(treeGrid);
@@ -963,6 +986,8 @@ public class ResourceTreeView extends LocatableVLayout {
public void execute(DSResponse response, Object rawData, DSRequest request) {
Log.info("Done fetching data for tree.");
+ loadingLabel.hide();
+
if (updateSelection) {
updateSelection();
}
@@ -994,6 +1019,8 @@ public class ResourceTreeView extends LocatableVLayout {
treeGrid.getTree().linkNodes(
ResourceTreeDatasource.buildNodes(lineage, lockedData, treeGrid));
+ loadingLabel.hide();
+
TreeNode selectedNode = treeGrid.getTree().findById(selectedNodeId);
if (selectedNode != null && updateSelection) {
updateSelection();
@@ -1029,9 +1056,11 @@ public class ResourceTreeView extends LocatableVLayout {
criteria.addFilterId(selectedAutoGroupId);
criteria.addFilterVisible(false);
criteria.fetchResourceType(true);
+ loadingLabel.show();
resourceGroupService.findResourceGroupsByCriteria(criteria, new AsyncCallback<PageList<ResourceGroup>>() {
public void onFailure(Throwable caught) {
+ loadingLabel.hide();
CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_loadFailed_node(), caught);
}
@@ -1043,6 +1072,7 @@ public class ResourceTreeView extends LocatableVLayout {
loadTree(backingGroup.getAutoGroupParentResource().getId(), false, new AsyncCallback<Void>() {
public void onFailure(Throwable caught) {
+ loadingLabel.hide();
CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_loadFailed_children(), caught);
}
@@ -1053,6 +1083,8 @@ public class ResourceTreeView extends LocatableVLayout {
AutoGroupTreeNode agNode = (AutoGroupTreeNode) treeGrid.getTree().findById(selectedNodeId);
autoGroupNodeMap.put(backingGroup.getId(), agNode);
updateSelection();
+
+ loadingLabel.hide();
}
});
}
@@ -1061,7 +1093,6 @@ public class ResourceTreeView extends LocatableVLayout {
}
public void renderView(ViewPath viewPath) {
-
ViewId currentViewId = viewPath.getCurrent();
String currentViewIdPath = currentViewId.getPath();
if ("AutoGroup".equals(currentViewIdPath)) {
commit 23b39b07ef79025500b063dd223dc243e12c5004
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri Aug 10 09:20:16 2012 -0400
Get rid of annoying maven warning by specifying to use the latest release
version.
diff --git a/pom.xml b/pom.xml
index 0ae9a07..36b9c62 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1317,6 +1317,7 @@
<plugin>
<groupId>com.googlecode.maven-overview-plugin</groupId>
<artifactId>maven-overview-plugin</artifactId>
+ <version>RELEASE</version>
</plugin>
<!--
commit 71dc21ab49b1a986e4364e52e0fa6f817c96bf89
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu Aug 9 16:09:41 2012 -0400
BZ 838670 Mark more configuration elements as r/w, as underyling AS allows that now.
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 6a6a40c..d27d432 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
@@ -397,33 +397,34 @@
<!ENTITY datasourceReadWriteConfiguration '
<resource-configuration>
- <c:simple-property name="connection-url" required="true" type="string" readOnly="true" description="The JDBC driver connection URL"/>
- <c:simple-property name="driver-name" required="true" type="string" description="Name of the (existing) JDBC driver to use" readOnly="true">
+ <c:simple-property name="connection-url" required="true" type="string" readOnly="false" description="The JDBC driver connection URL"/>
+ <c:simple-property name="driver-name" required="true" type="string" description="Name of the (existing) JDBC driver to use" readOnly="false">
<c:option-source target="resource" expression="type=^Deployment$" filter=".*\.jar"/>
</c:simple-property>
- <c:simple-property name="driver-class" required="false" type="string" readOnly="true" description="The fully qualified name of the JDBC driver class"/>
- <c:simple-property name="jndi-name" required="true" type="string" readOnly="true" description="Specifies the JNDI name for the datasource"/>
+ <c:simple-property name="driver-class" required="false" type="string" readOnly="false" description="The fully qualified name of the JDBC driver class"/>
+ <c:simple-property name="jndi-name" required="true" type="string" readOnly="false" description="Specifies the JNDI name for the datasource"/>
<c:simple-property name="driver" required="false" type="string" readOnly="true" description="Defines the JDBC driver the datasource should use with this format: driver-name>#major-version.minor-version where driver-name is the fully qualified name of the JDBC driver class"/>
- <c:simple-property name="user-name" type="string" readOnly="true" required="false" description="Specify the username used when creating a new connection."/>
- <c:simple-property name="password" type="password" readOnly="true" required="false" description="Specify the password used when creating a new connection."/>
- <c:simple-property name="new-connection-sql" type="string" readOnly="true" required="false" description="Specifies an SQL statement to execute whenever a connection is added to the connection pool."/>
- <c:simple-property name="url-delimiter" type="string" readOnly="true" description="Specifies the delimiter for URLs in connection-url for HA datasources" required="false"/>
- <c:simple-property name="url-selector-strategy-class-name" type="string" readOnly="true" description="A class that implements org.jboss.jca.adapters.jdbc.URLSelectorStrategy" required="false"/>
- <c:simple-property name="use-java-context" type="boolean" readOnly="true" required="false" description="Setting this to false will bind the DataSource into global JNDI;"/>
+ <c:simple-property name="user-name" type="string" readOnly="false" required="false" description="Specify the username used when creating a new connection."/>
+ <c:simple-property name="password" type="password" readOnly="false" required="false" description="Specify the password used when creating a new connection."/>
+ <c:simple-property name="new-connection-sql" type="string" readOnly="false" required="false" description="Specifies an SQL statement to execute whenever a connection is added to the connection pool."/>
+ <c:simple-property name="url-delimiter" type="string" readOnly="false" description="Specifies the delimiter for URLs in connection-url for HA datasources" required="false"/>
+ <c:simple-property name="url-selector-strategy-class-name" type="string" readOnly="false" description="A class that implements org.jboss.jca.adapters.jdbc.URLSelectorStrategy" required="false"/>
+ <c:simple-property name="use-java-context" type="boolean" readOnly="false" required="false" default="true" description="Setting this to false will bind the DataSource into global JNDI;"/>
<c:simple-property name="enabled" type="boolean" readOnly="true" required="false" description="Specifies if the datasource should be enabled"/>
+ <c:simple-property name="jta" type="boolean" readOnly="false" required="false" default="true" description="Enable JTA integration"/>
<c:simple-property name="max-pool-size" type="integer" readOnly="false" required="false" description="The max-pool-size element indicates the maximum number of connections for a pool. No more connections will be created in each sub-pool."/>
<c:simple-property name="min-pool-size" type="integer" readOnly="false" required="false" description="The min-pool-size element 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."/>
- <c:simple-property name="pool-prefill" type="boolean" readOnly="false" required="false" description="Whether to attempt to prefill the connection pool. Changing this value require a server restart."/>
- <c:simple-property name="pool-use-strict-min" type="boolean" readOnly="false" required="false" description="Define if the min-pool-size should be considered a strictly."/>
- <c:simple-property name="security-domain" required="false" type="string" readOnly="true" description="Indicates Subject (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 handleauthentication. This name correlates to the JAAS login-config.xml descriptor application-policy/name attribute."/>
- <c:simple-property name="reauth-plugin-class-name" required="false" type="string" readOnly="true" description="re-authentication plugin implementation provided for specific purpose (i.e vendor)"/>
+ <c:simple-property name="pool-prefill" type="boolean" readOnly="false" required="false" default="false" description="Whether to attempt to prefill the connection pool. Changing this value require a server restart."/>
+ <c:simple-property name="pool-use-strict-min" type="boolean" readOnly="false" required="false" default="false" description="Define if the min-pool-size should be considered a strictly."/>
+ <c:simple-property name="security-domain" required="false" type="string" readOnly="false" description="Indicates Subject (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 handleauthentication. This name correlates to the JAAS login-config.xml descriptor application-policy/name attribute."/>
+ <c:simple-property name="reauth-plugin-class-name" required="false" type="string" readOnly="false" description="re-authentication plugin implementation provided for specific purpose (i.e vendor)"/>
<!--
<c:map-property name="reauth-plugin-properties" description="properties for reauthentication plugin passed to the implementation provided for specific purpose (i.e vendor)">
read-only
configuration
</c:map-property>
-->
- <c:simple-property name="flush-strategy" required="false" type="string" readOnly="true" description="Specifies how the pool should be flush in case of an error." default="FailingConnectionOnly" defaultValue="FailingConnectionOnly">
+ <c:simple-property name="flush-strategy" required="false" type="string" readOnly="false" description="Specifies how the pool should be flush in case of an error." default="FailingConnectionOnly" defaultValue="FailingConnectionOnly">
<c:property-options>
<c:option value="FailingConnectionOnly"/>
<c:option value="IdleConnections"/>
@@ -431,17 +432,24 @@
</c:property-options>
</c:simple-property>
- <c:simple-property name="prepared-statements-cacheSize" type="long" readOnly="true" required="false" description="The number of prepared statements per connection in an LRU cache"/>
- <c:simple-property name="share-prepared-statements" type="boolean" readOnly="true" required="false" description="Whether to share prepare statements, i.e. whether asking for same statement twice without closing uses the same underlying prepared statement"/>
- <c:simple-property name="track-statements" type="string" readOnly="true" required="false" description="Whether to check for unclosed statements when a connection is returned to the pool and result sets are closed when a statement is closed/return to the prepared statement cache. valid values are: false - do not track statements and results true - track statements and result sets and warn when they are not closed nowarn - track statements but do no warn about them being unclosed"/>
- <c:simple-property name="allocation-retry" type="integer" readOnly="true" required="false" description="The allocation retry element indicates the number of times that allocating a connection should be tried before throwing an exception."/>
- <c:simple-property name="allocation-retry-wait-millis" type="long" readOnly="true" required="false" description="Indicates the time in milliseconds to wait between retrying to allocate a connection."/>
+ <c:simple-property name="allow-multiple-users" type="boolean" required="false" readOnly="false" description="Specifies if multiple users will access the datasource through the getConnection(user, password) method and hence if the internal pool type should account for that"/>
+ <c:simple-property name="prepared-statements-cacheSize" type="long" readOnly="false" required="false" description="The number of prepared statements per connection in an LRU cache"/>
+ <c:simple-property name="share-prepared-statements" type="boolean" readOnly="false" required="false" default="false" description="Whether to share prepare statements, i.e. whether asking for same statement twice without closing uses the same underlying prepared statement"/>
+ <c:simple-property name="track-statements" type="string" readOnly="false" required="false" description="Whether to check for unclosed statements when a connection is returned to the pool and result sets are closed when a statement is closed/return to the prepared statement cache. valid values are: false - do not track statements and results true - track statements and result sets and warn when they are not closed nowarn - track statements but do no warn about them being unclosed">
+ <c:property-options>
+ <c:option value="false"/>
+ <c:option value="true"/>
+ <c:option value="NOWARN"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="allocation-retry" type="integer" readOnly="false" required="false" description="The allocation retry element indicates the number of times that allocating a connection should be tried before throwing an exception."/>
+ <c:simple-property name="allocation-retry-wait-millis" type="long" readOnly="false" required="false" description="Indicates the time in milliseconds to wait between retrying to allocate a connection."/>
<c:simple-property name="blocking-timeout-wait-millis" type="long" readOnly="false" required="false" description="The blocking-timeout-millis element 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."/>
<c:simple-property name="idle-timeout-minutes" type="long" readOnly="false" required="false" description="The idle-timeout-minutes elements 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. Changing this value require a server restart."/>
- <c:simple-property name="query-timeout" type="long" readOnly="true" required="false" description="Any configured query timeout in seconds The default is no timeout"/>
- <c:simple-property name="use-try-lock" type="long" readOnly="true" required="false" description="Any configured timeout for internal locks on the resource adapter objects in seconds"/>
- <c:simple-property name="set-tx-query-timeout" type="boolean" readOnly="true" required="false" description="Whether to set the query timeout based on the time remaining until transaction timeout, any configured query timeout will be used if there is no transaction."/>
- <c:simple-property name="transaction-isolation" type="string" readOnly="true" required="false" description="Set java.sql.Connection transaction isolation level to use. The constants defined by transaction-isolation-values are the possible transaction isolation levels.">
+ <c:simple-property name="query-timeout" type="long" readOnly="false" required="false" description="Any configured query timeout in seconds The default is no timeout"/>
+ <c:simple-property name="use-try-lock" type="long" readOnly="false" required="false" description="Any configured timeout for internal locks on the resource adapter objects in seconds"/>
+ <c:simple-property name="set-tx-query-timeout" type="boolean" readOnly="false" required="false" default="false" description="Whether to set the query timeout based on the time remaining until transaction timeout, any configured query timeout will be used if there is no transaction."/>
+ <c:simple-property name="transaction-isolation" type="string" readOnly="false" required="false" description="Set java.sql.Connection transaction isolation level to use. The constants defined by transaction-isolation-values are the possible transaction isolation levels.">
<c:property-options>
<c:option value="TRANSACTION_READ_UNCOMMITTED"/>
<c:option value="TRANSACTION_READ_COMMITTED"/>
@@ -450,16 +458,16 @@
<c:option value="TRANSACTION_NONE"/>
</c:property-options>
</c:simple-property>
- <c:simple-property name="check-valid-connection-sql" type="string" readOnly="true" 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:simple-property name="exception-sorter-class-name" type="string" readOnly="true" required="false" description="An org.jboss.jca.adapters.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"/>
- <c:simple-property name="stale-connection-checker-class-name" type="string" readOnly="true" required="false" description="An org.jboss.jca.adapters.jdbc.StaleConnectionChecker that provides a boolean isStaleConnection(SQLException e) method which if it it returns true will wrap the exception in an org.jboss.jca.adapters.jdbc.StaleConnectionException"/>
- <c:simple-property name="valid-connection-checker-class-name" type="string" readOnly="true" required="false" description="An org.jboss.jca.adapters.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."/>
- <c:simple-property name="background-validation-minutes" type="long" readOnly="false" required="false" description="The background-validation-minutes element specifies the amount of time, in minutes, that background validation will run. Changing this value require a server restart."/>
- <c:simple-property name="background-validation" type="boolean" readOnly="false" required="false" description="An element to specify that connections should be validated on a background thread versus being validated prior to use. Changing this value require a server restart."/>
+ <c:simple-property name="check-valid-connection-sql" type="string" readOnly="false" 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:simple-property name="exception-sorter-class-name" type="string" readOnly="false" required="false" description="An org.jboss.jca.adapters.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"/>
+ <c:simple-property name="stale-connection-checker-class-name" type="string" readOnly="false" required="false" description="An org.jboss.jca.adapters.jdbc.StaleConnectionChecker that provides a boolean isStaleConnection(SQLException e) method which if it it returns true will wrap the exception in an org.jboss.jca.adapters.jdbc.StaleConnectionException"/>
+ <c:simple-property name="valid-connection-checker-class-name" type="string" readOnly="false" required="false" description="An org.jboss.jca.adapters.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."/>
+ <c:simple-property name="background-validation-millis" type="long" readOnly="false" required="false" description="The background-validation-minutes element specifies the amount of time, in minutes, that background validation will run. Changing this value require a server restart."/>
+ <c:simple-property name="background-validation" type="boolean" readOnly="false" required="false" default="false" description="An element to specify that connections should be validated on a background thread versus being validated prior to use. Changing this value require a server restart."/>
<c:simple-property name="use-fast-fail" type="boolean" readOnly="false" required="false" description="Whether fail a connection allocation on the first connection if it is invalid (true) or keep trying until the pool is exhausted of all potential connections (false)"/>
- <c:simple-property name="validate-on-match" type="boolean" readOnly="true" required="false" description="The validate-on-match element indicates whether or not connection level validation should be done when a connection factory attempts to match a managed connection for a given set. This is typically exclusive to the use of background validation"/>
- <c:simple-property name="spy" type="boolean" readOnly="true" required="false" description="whatever spy or not the jdbc connection"/>
- <c:simple-property name="use-ccm" type="boolean" readOnly="true" required="false" description="Enable the use of a cached connection manager"/>
+ <c:simple-property name="validate-on-match" type="boolean" readOnly="false" required="false" default="false" description="The validate-on-match element indicates whether or not connection level validation should be done when a connection factory attempts to match a managed connection for a given set. This is typically exclusive to the use of background validation"/>
+ <c:simple-property name="spy" type="boolean" readOnly="false" required="false" defaultValue="false" description="whatever spy or not the jdbc connection"/>
+ <c:simple-property name="use-ccm" type="boolean" readOnly="false" required="false" description="Enable the use of a cached connection manager"/>
<c:group name="children:connection-properties:pname+-" displayName="Connection Properties">
<c:list-property name="*1" displayName="Connection Property" readOnly="false" required="false">
<c:map-property name="*:pname" displayName="Name" readOnly="false">
commit 77cee38075da30754fa6081dcf5cfe239f547a71
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu Aug 9 14:20:52 2012 -0400
BZ 839320 When a property is required and the user has not explicitly choosen a value and there is a defaultValue, use this.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
index 366f840..86ba37a 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
@@ -500,7 +500,25 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
entry = new SimpleEntry<String, Object>(realName, null);
}
} else {
- Object o = getObjectWithType(propertyDefinition,property.getStringValue());
+ Object o;
+/*
+ If no value is given in the property and the property is required,
+ we'll take the default value from the definition. This can e.g. happen
+ when you have
+ <c:simple-property name="mode" required="true" type="string" readOnly="false" default="SYNC" defaultValue="SYNC">
+ <c:property-options>
+ <c:option value="SYNC"/>
+ <c:option value="ASYNC"/>
+ </c:property-options>
+ </c:simple-property>
+ and the user chooses to just keep the default choice in the ui
+*/
+
+ if (property.getStringValue()==null && propertyDefinition.isRequired()) {
+ o = getObjectWithType(propertyDefinition,propertyDefinition.getDefaultValue());
+ } else {
+ o = getObjectWithType(propertyDefinition,property.getStringValue());
+ }
entry = new SimpleEntry<String, Object>(name, o);
}
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 77bacfb..6a6a40c 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
@@ -11350,7 +11350,7 @@
</c:property-options>
</c:simple-property>
<c:simple-property name="jndi-name" required="false" type="string" readOnly="false" description="The jndi-name to which to bind this cache instance."/>
- <c:simple-property name="mode" required="true" type="string" readOnly="false" default="SYNC" description="Sets the clustered cache mode, ASYNC for asynchronous operation, or SYNC for synchronous operation.">
+ <c:simple-property name="mode" required="true" type="string" readOnly="false" default="SYNC" defaultValue="SYNC" description="Sets the clustered cache mode, ASYNC for asynchronous operation, or SYNC for synchronous operation.">
<c:property-options>
<c:option value="SYNC"/>
<c:option value="ASYNC"/>
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java
index ba2f13c..21e3d5f 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java
@@ -862,4 +862,90 @@ public class ConfigurationUpdatingTest extends AbstractConfigurationHandlingTest
assert cop.numberOfSteps() == 1 : "One step was expected, but got " + cop.numberOfSteps();
}
+
+ /**
+ * Test that if a property is required and has a defaultValue and the user just uses this,
+ * we actually pass this default to the operation, as e.g. the CreateResourceReport may not
+ * include the default value.
+ * @throws Exception If anything goes wrong
+ */
+ public void testSimpleWithDefault1() throws Exception {
+
+ ConfigurationDefinition definition = loadDescriptor("simpleWithDefault1");
+
+ FakeConnection connection = new FakeConnection();
+
+ ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(definition, connection, null);
+
+ Configuration conf = new Configuration();
+ PropertySimple ps = new PropertySimple("mode",null);
+ conf.put(ps);
+
+ CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, new Address());
+
+ assert cop.numberOfSteps() == 1;
+ Operation step1 = cop.step(0);
+ assert step1.getOperation().equals("write-attribute");
+ Map<String, Object> props = step1.getAdditionalProperties();
+ assert props.size() == 2;
+ assert props.get("name").equals("mode");
+ assert props.get("value").equals("SYNC"); // the defaultValue
+ }
+
+ /**
+ * Check that if a property is required and has no defaultValue, but the user provides a value,
+ * that the user provided value ends up in the operation
+ * @throws Exception
+ */
+ public void testSimpleWithDefault2() throws Exception {
+
+ ConfigurationDefinition definition = loadDescriptor("simpleWithDefault2");
+
+ FakeConnection connection = new FakeConnection();
+
+ ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(definition, connection, null);
+
+ Configuration conf = new Configuration();
+ PropertySimple ps = new PropertySimple("mode","ASYNC");
+ conf.put(ps);
+
+ CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, new Address());
+
+ assert cop.numberOfSteps() == 1;
+ Operation step1 = cop.step(0);
+ assert step1.getOperation().equals("write-attribute");
+ Map<String, Object> props = step1.getAdditionalProperties();
+ assert props.size() == 2;
+ assert props.get("name").equals("mode");
+ assert props.get("value").equals("ASYNC"); // the user provided value
+ }
+
+ /**
+ * Check that if a property is required and has no defaultValue, and the user provides null
+ * as value, that we set null
+ * @throws Exception
+ */
+ public void testSimpleWithDefault3() throws Exception {
+
+ ConfigurationDefinition definition = loadDescriptor("simpleWithDefault2");
+
+ FakeConnection connection = new FakeConnection();
+
+ ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(definition, connection, null);
+
+ Configuration conf = new Configuration();
+ PropertySimple ps = new PropertySimple("mode",null);
+ conf.put(ps);
+
+ CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, new Address());
+
+ assert cop.numberOfSteps() == 1;
+ Operation step1 = cop.step(0);
+ assert step1.getOperation().equals("write-attribute");
+ Map<String, Object> props = step1.getAdditionalProperties();
+ assert props.size() == 2;
+ assert props.get("name").equals("mode");
+ assert props.get("value")==null; // no value
+ }
+
}
diff --git a/modules/plugins/jboss-as-7/src/test/resources/test-plugin.xml b/modules/plugins/jboss-as-7/src/test/resources/test-plugin.xml
index 4350230..f10f52b 100644
--- a/modules/plugins/jboss-as-7/src/test/resources/test-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/test/resources/test-plugin.xml
@@ -290,6 +290,37 @@
</resource-configuration>
</server>
+ <server name="simpleWithDefault1"
+ class="BaseComponent"
+ discovery="SubsystemDiscovery">
+
+ <resource-configuration>
+ <c:simple-property name="mode" required="true" type="string" readOnly="false" default="SYNC" defaultValue="SYNC" >
+ <c:property-options>
+ <c:option value="SYNC"/>
+ <c:option value="ASYNC"/>
+ </c:property-options>
+ </c:simple-property>
+ </resource-configuration>
+
+ </server>
+
+ <server name="simpleWithDefault2"
+ class="BaseComponent"
+ discovery="SubsystemDiscovery">
+
+ <resource-configuration>
+ <c:simple-property name="mode" required="true" type="string" readOnly="false" default="SYNC" >
+ <c:property-options>
+ <c:option value="SYNC"/>
+ <c:option value="ASYNC"/>
+ </c:property-options>
+ </c:simple-property>
+ </resource-configuration>
+
+ </server>
+
+
<!-- Simple c:group entries from descriptor with no special handling. -->
<service name="simpleGroupNoSpecial"
class="BaseComponent"
@@ -327,4 +358,6 @@
</resource-configuration>
</service>
+
+
</plugin>
\ No newline at end of file
commit 396b48fde3613c359b49ca4b776ee18fa39f3865
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Aug 9 09:12:57 2012 -0400
[Bug 847014 - Resource tree not complete when more than 200 children]
Allow an unlimited number of children when expanding the tree node. Although
this may create a large vertical expansion, it may also be what the
user wants. See BZ comments for more on the approach and alternatives
but basically, take this [easy] approach until it's clear that users, or UX,
want something else.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
index c072e13..2a5b827 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
@@ -43,6 +43,7 @@ import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceSubCategory;
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.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.Messages;
@@ -152,6 +153,8 @@ public class ResourceTreeDatasource extends DataSource {
ResourceCriteria criteria = new ResourceCriteria();
criteria.addFilterParentResourceId(Integer.parseInt(parentResourceId));
+ // we don't need sorting since we get everything and the tree nodes are already sorted
+ criteria.setPageControl(PageControl.getUnlimitedInstance());
resourceService.findResourcesByCriteria(criteria, new AsyncCallback<PageList<Resource>>() {
public void onFailure(Throwable caught) {
commit c1d401ff6c2b495cb599dfb66e0dd157b6442614
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Aug 9 09:05:46 2012 -0400
[Bug 838683 - If RHQ server is down, UI shows "Server returned FAILURE with no error message"]
More recent versions of Firefox, and possibly other browsers, have changed
the request's response code in this situation. Added updated handling.
Also, fixed an I18N issue.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/rpc/TrackingRequestCallback.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/rpc/TrackingRequestCallback.java
index f461f6e..2702814 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/rpc/TrackingRequestCallback.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/rpc/TrackingRequestCallback.java
@@ -18,7 +18,6 @@
*/
package org.rhq.enterprise.gui.coregui.client.util.rpc;
-import java.util.logging.Logger;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.Response;
@@ -38,6 +37,7 @@ public class TrackingRequestCallback implements RequestCallback {
private long start = System.currentTimeMillis();
private static final int STATUS_CODE_OK = 200;
+ private static final int STATUS_CODE_ERROR_INTERNET_NO_RESPONSE = 0;
private static final int STATUS_CODE_ERROR_INTERNET_CANNOT_CONNECT = 12029;
private static final int STATUS_CODE_ERROR_INTERNET_CONNECTION_ABORTED = 12030;
@@ -69,7 +69,7 @@ public class TrackingRequestCallback implements RequestCallback {
statusCode = response.getStatusCode();
statusText = response.getStatusText();
} catch (Throwable t) {
- // If the server is unreachable or has terminated firefox will generate a JavaScript exception
+ // If the server is unreachable or has terminated firefox may generate a JavaScript exception
// when trying to read the response object. Let the user know the server is unreachable.
// (http://helpful.knobs-dials.com/index.php/0x80004005_%28NS_ERROR_FAILURE%2...
if (UserSessionManager.isLoggedIn()) {
@@ -90,13 +90,15 @@ public class TrackingRequestCallback implements RequestCallback {
callback.onResponseReceived(request, response);
break;
+ // these status codes are known to be returned from various browsers when the server is lost or not responding
+ case STATUS_CODE_ERROR_INTERNET_NO_RESPONSE:
case STATUS_CODE_ERROR_INTERNET_CANNOT_CONNECT:
case STATUS_CODE_ERROR_INTERNET_CONNECTION_ABORTED:
RPCTracker.getInstance().failCall(this);
// If the server is unreachable or has terminated, and the user is still logged in,
// let them know the server is now unreachable.
if (UserSessionManager.isLoggedIn()) {
- CoreGUI.getErrorHandler().handleError("Server unreachable and may be down");
+ CoreGUI.getErrorHandler().handleError(CoreGUI.getMessages().view_core_serverUnreachable());
}
break;
commit 58c9ee2d6dd34ebce6b96aed0cbc35da27374165
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Thu Aug 9 13:16:53 2012 +0200
Fixing the typo in constructor and bad usage of this constructor in 1 test
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java
index 35c9367..84018a8 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java
@@ -95,7 +95,7 @@ public class BundleCriteria extends TaggedCriteria {
}
public void addFilterBundleTypeName(String filterBundleTypeName) {
- this.filterName = filterBundleTypeName;
+ this.filterBundleTypeName = filterBundleTypeName;
}
public void addFilterDescription(String filterDescription) {
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java
index a4d43b8..1621dac 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java
@@ -952,7 +952,7 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// return bundle "two" using all criteria and with all optional data
c.addFilterId(b.getId());
c.addFilterName(b.getName());
- c.addFilterBundleTypeName(b.getName());
+ c.addFilterBundleTypeName(b.getBundleType().getName());
c.fetchBundleVersions(true);
c.fetchRepo(true);
bundles = bundleManager.findBundlesByCriteria(overlord, c);
commit 21e61a1588663c97975580003c00dfd8cbc20798
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Thu Aug 9 13:12:03 2012 +0200
[BZ 822795 - Search filter not working in bundle deployment wizard] Added filtering by the name of the bundle.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java
index 037bc10..eaa4371 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java
@@ -23,6 +23,7 @@ import java.util.LinkedHashMap;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.Criteria;
+import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
@@ -76,7 +77,7 @@ public class BundleSelector extends AbstractSelector<Bundle, BundleCriteria> {
}
protected RPCDataSource<Bundle, BundleCriteria> getDataSource() {
- return new BundlesDataSource();
+ return new SelectedBundlesDataSource();
}
protected Criteria getLatestCriteria(DynamicForm availableFilterForm) {
@@ -94,4 +95,15 @@ public class BundleSelector extends AbstractSelector<Bundle, BundleCriteria> {
protected String getItemTitle() {
return MSG.common_title_bundles();
}
+
+ public class SelectedBundlesDataSource extends BundlesDataSource {
+ @Override
+ protected BundleCriteria getFetchCriteria(final DSRequest request) {
+ BundleCriteria result = super.getFetchCriteria(request);
+ if (null != result) {
+ result.setStrict(false);
+ }
+ return result;
+ }
+ }
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesDataSource.java
index f8389b4..42a3e0d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesDataSource.java
@@ -90,28 +90,12 @@ public class BundlesDataSource extends RPCDataSource<Bundle, BundleCriteria> {
@Override
protected BundleCriteria getFetchCriteria(final DSRequest request) {
BundleCriteria criteria = new BundleCriteria();
-
- if (request.getCriteria().getValues().get("tagNamespace") != null) {
- criteria.addFilterTagNamespace((String) request.getCriteria().getValues().get("tagNamespace"));
- }
-
- if (request.getCriteria().getValues().get("tagSemantic") != null) {
- criteria.addFilterTagSemantic((String) request.getCriteria().getValues().get("tagSemantic"));
- }
-
- if (request.getCriteria().getValues().get("tagName") != null) {
- criteria.addFilterTagName((String) request.getCriteria().getValues().get("tagName"));
- }
-
- if (request.getCriteria().getValues().get("bundleType") != null) {
- criteria.addFilterBundleTypeId(Integer.valueOf(request.getCriteria().getValues().get("bundleType")
- .toString()));
- }
-
- // TODO: this doesn't work like I think it should, figure out how to search on the name column
- // if (request.getCriteria().getValues().get("search") != null) {
- // criteria.setSearchExpression(request.getCriteria().getValues().get("search").toString());
- // }
+ criteria.addFilterTagNamespace(getFilter(request, "tagNamespace", String.class));
+ criteria.addFilterTagSemantic(getFilter(request, "tagSemantic", String.class));
+ criteria.addFilterTagName(getFilter(request, "tagName", String.class));
+ criteria.addFilterBundleTypeId(getFilter(request, "bundleType", Integer.class));
+ criteria.addFilterTagSemantic(getFilter(request, "tagSemantic", String.class));
+ criteria.addFilterName(getFilter(request, "search", String.class));
return criteria;
}
commit 88c286048d73a963eb2e2debd1009d8ed0d595b0
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Aug 8 16:04:19 2012 -0500
[BZ 837510] Prevent the edge case by retrieving the clustered property from AS5 only when the first metric collection occurs. Also marked the getter deprecated to prevent further use of the property outside of this component.
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/WebApplicationContextComponent.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/WebApplicationContextComponent.java
index 6eb7e7e..07708b7 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/WebApplicationContextComponent.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/WebApplicationContextComponent.java
@@ -82,7 +82,7 @@ public class WebApplicationContextComponent extends ManagedComponentComponent {
private String servletComponentNamesRegex;
private ResponseTimeLogParser logParser;
- private boolean clustered;
+ private Boolean clustered;
@Override
public void start(ResourceContext<ProfileServiceComponent<?>> resourceContext) throws Exception {
@@ -97,17 +97,6 @@ public class WebApplicationContextComponent extends ManagedComponentComponent {
this.logParser.setExcludes(responseTimeConfig.getExcludes());
this.logParser.setTransforms(responseTimeConfig.getTransforms());
}
-
- try {
- ManagedProperty distributableProp = getManagedComponent().getProperty(DISTRIBUTABLE_MANAGED_PROPERTY);
- if (distributableProp != null) {
- Boolean distributable = (Boolean) getInnerValue(distributableProp.getValue());
- clustered = distributable != null && distributable.booleanValue();
- }
- } catch (Exception e) {
- log.warn("Failed to determine whether the web app context " + resourceContext.getResourceKey()
- + " is clustered or not.", e);
- }
}
@Override
@@ -144,8 +133,14 @@ public class WebApplicationContextComponent extends ManagedComponentComponent {
// TODO: Communicate this error back to the server for display in the GUI.
}
} else if (metricName.equals(CLUSTERED_TRAIT)) {
- MeasurementDataTrait trait = new MeasurementDataTrait(request, Boolean.toString(clustered));
- report.addData(trait);
+ if(clustered == null){
+ retrieveClusteredProperty();
+ }
+
+ if (clustered != null) {
+ MeasurementDataTrait trait = new MeasurementDataTrait(request, clustered.toString());
+ report.addData(trait);
+ }
} else {
String metricNameToUse = metricName;
if (clustered && !"runState".equals(metricName)) {
@@ -170,10 +165,33 @@ public class WebApplicationContextComponent extends ManagedComponentComponent {
}
}
+ /**
+ * @deprecated The clustered property should be retrieved by the individual component in the
+ * specific use case that requires it. Leaving this method for backwards compatibility
+ * with plugins that use the AS5 plugin and also use reflection.
+ */
+ @Deprecated
public boolean isClustered() {
+ if (clustered == null) {
+ return false;
+ }
+
return clustered;
}
+ private void retrieveClusteredProperty() {
+ try {
+ ManagedProperty distributableProp = getManagedComponent().getProperty(DISTRIBUTABLE_MANAGED_PROPERTY);
+ if (distributableProp != null) {
+ Boolean distributable = (Boolean) getInnerValue(distributableProp.getValue());
+ clustered = distributable != null && distributable.booleanValue();
+ }
+ } catch (Exception e) {
+ log.warn("Failed to determine whether the web app context " + this.getResourceContext().getResourceKey()
+ + " is clustered or not.", e);
+ }
+ }
+
private Double getServletMetric(ManagementView managementView, String metricName) throws Exception {
ComponentType servletComponentType = MoreKnownComponentTypes.MBean.Servlet.getType();
//Set<ManagedComponent> servletComponents = managementView.getMatchingComponents(this.servletComponentNamesRegex,
commit 15552573391da403073ea1c27a8a9a5ffc969e65
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Wed Aug 8 11:45:51 2012 -0700
[BZ 845389 - Group without members with unknown status appears in every availability search result] Get rid of superfluous empty groups that show up as unknown availability.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
index 72f25a4..9f640dc 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
@@ -26,6 +26,7 @@ import static org.rhq.enterprise.gui.coregui.client.inventory.groups.ResourceGro
import static org.rhq.enterprise.gui.coregui.client.inventory.groups.ResourceGroupDataSourceField.PLUGIN;
import static org.rhq.enterprise.gui.coregui.client.inventory.groups.ResourceGroupDataSourceField.TYPE;
+import java.util.ArrayList;
import java.util.List;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -50,6 +51,7 @@ import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
@@ -110,7 +112,7 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
}
@Override
- public void executeFetch(final DSRequest request, final DSResponse response, ResourceGroupCriteria criteria) {
+ public void executeFetch(final DSRequest request, final DSResponse response, final ResourceGroupCriteria criteria ) {
groupService.findResourceGroupCompositesByCriteria(criteria,
new AsyncCallback<PageList<ResourceGroupComposite>>() {
public void onFailure(Throwable caught) {
@@ -123,10 +125,25 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
response.setStatus(RPCResponse.STATUS_FAILURE);
processResponse(request.getRequestId(), response);
}
+
+ private PageList<ResourceGroupComposite> filterEmptyMemberGroups(ResourceGroupCriteria groupCriteria,
+ PageList<ResourceGroupComposite> result){
+
+ PageList<ResourceGroupComposite> pageList = new PageList<ResourceGroupComposite>(result.getPageControl());
+
+ for (ResourceGroupComposite rgc : result) {
+ if (rgc.getExplicitCount() > 0 ){
+ pageList.add(rgc);
+ }
+ }
+
+ return pageList;
+ }
public void onSuccess(PageList<ResourceGroupComposite> result) {
- response.setData(buildRecords(result));
- response.setTotalRows(result.getTotalSize()); // for paging to work we have to specify size of full result set
+ PageList<ResourceGroupComposite> filteredResult = filterEmptyMemberGroups(criteria,result);
+ response.setData(buildRecords(filteredResult));
+ response.setTotalRows(filteredResult.getTotalSize()); // for paging to work we have to specify size of full result set
processResponse(request.getRequestId(), response);
}
});
commit 8ead20e62a892e10b12ed70c20a8b1c4e55ff024
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Tue Aug 7 14:27:26 2012 -0700
Add i18n messages for ResourceGroupCompositeDataSource
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
index 2abefa1..72f25a4 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupCompositeDataSource.java
@@ -47,6 +47,7 @@ import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.ImageManager;
+import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
@@ -57,6 +58,8 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message;
*/
public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGroupComposite, ResourceGroupCriteria> {
+ private static final Messages MSG = CoreGUI.getMessages();
+
public static final String FILTER_GROUP_IDS = "resourceGroupIds";
ResourceGroupGWTServiceAsync groupService = GWTServiceLookup.getResourceGroupService();
@@ -112,7 +115,7 @@ public class ResourceGroupCompositeDataSource extends RPCDataSource<ResourceGrou
new AsyncCallback<PageList<ResourceGroupComposite>>() {
public void onFailure(Throwable caught) {
if (caught.getMessage().contains("SearchExpressionException")) {
- Message message = new Message("Invalid search expression.", Message.Severity.Error);
+ Message message = new Message(MSG.search_invalid_search_expression(), Message.Severity.Error);
CoreGUI.getMessageCenter().notify(message);
} else {
CoreGUI.getErrorHandler().handleError(MSG.view_inventory_groups_loadFailed(), caught);
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index a558db1..f9b75f3 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -413,6 +413,7 @@ filter_from_date = From
filter_to_date = To
group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+search_invalid_search_expression = Invalid search expression.
search_failed_to_save_search = Failed to Save Search: {0}
search_failed_to_retrieve_saved_search = Failed to retrieve saved search
search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index b146b3d..11c4488 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -432,6 +432,7 @@ filter_from_date = Od
filter_to_date = Do
group_tree_groupOfResourceType = Skupina: [{0}]
group_tree_partialClusterTooltip = {0} z {1} členů skupiny má "{2}" zdroj
+##search_invalid_search_expression = Invalid search expression.
##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 7b9effe..71d8367 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -397,6 +397,7 @@ filter_from_date = Von
filter_to_date = Bis
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} der {1} Gruppenmitglieder haben eine ''{2}'' Ressource
+##search_invalid_search_expression = Invalid search expression.
##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index b7c191e..33e39c8 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -410,6 +410,7 @@ filter_from_date = 開始
filter_to_date = 終了
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {1} の中の {0} グループメンバーが ''{2}'' リソースを持っています
+##search_invalid_search_expression = Invalid search expression.
##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 72b2f34..2c1af7e 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -416,6 +416,7 @@ favorites_resources = Recursos Favoritos
##filter_to_date = To
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+##search_invalid_search_expression = Invalid search expression.
##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 5a44858..29a3fa6 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -403,6 +403,7 @@
#filter_from_date = From
#filter_to_date = To
#group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+##search_invalid_search_expression = Invalid search expression.
##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 6ae9e47..cd7f97f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -405,6 +405,7 @@ favorites_resources = \u8d44\u6e90\u6536\u85cf\u5939
##filter_to_date = To
##group_tree_groupOfResourceType = Group of [{0}]
group_tree_partialClusterTooltip = \u9664\u53bb {1},{0}\u7684\u7ec4\u6210\u5458\u62e5\u6709 \u4e00\u4e2a''{2}''\u8d44\u6e90
+##search_invalid_search_expression = Invalid search expression.
##search_failed_to_save_search = Failed to Save Search: {0}
##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
commit b97ed4379723df4bd78d5a101094ada80097025e
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Wed Aug 8 11:37:36 2012 -0500
[BZ 836527] Added a create content method for backwards compatiblity with the SOA-P plugin.
diff --git a/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/util/FileContentDelegate.java b/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/util/FileContentDelegate.java
index f82b5ec..6b967b8 100644
--- a/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/util/FileContentDelegate.java
+++ b/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/util/FileContentDelegate.java
@@ -84,15 +84,14 @@ public class FileContentDelegate {
}
/**
- * Creates a new package described by the specified details. The destination of the content in the provided input
- * stream will be determined by the package name.
+ * Creates a new package described by the specified details. The destination of the content in the provided
+ * file will be determined by the package name.
*
* @param details describes the package being created
- * @param content content to be written for the package. NOTE this Stream will be closed by this method.
+ * @param sourceContentFile content file to be written for the package.
* @param unzip if <code>true</code>, the content stream will be treated like a ZIP file and be unzipped as
* it is written, using the package name as the base directory; if <code>false</code> the
* @param createBackup If <code>true</code>, the original file will be backed up to file.bak
- * @param shaString the SHA-256 of the specified input stream
*/
public void createContent(PackageDetails details, File sourceContentFile, boolean unzip, boolean createBackup) {
File destinationContentFile = getPath(details);
@@ -115,6 +114,37 @@ public class FileContentDelegate {
}
/**
+ * Creates a new package described by the specified details. The destination of the content in the provided input
+ * stream will be determined by the package name.
+ *
+ * @param details describes the package being created
+ * @param content content to be written for the package. NOTE this Stream will be closed by this method.
+ * @param unzip if <code>true</code>, the content stream will be treated like a ZIP file and be unzipped as
+ * it is written, using the package name as the base directory; if <code>false</code> the
+ * @param createBackup If <code>true</code>, the original file will be backed up to file.bak
+ * @deprecated Method deprecated because of SHA256 computations. Method added only for backwards compatibility with SOA-P plugin.
+ * Replaced by {@link #createContent(PackageDetails, File, boolean, boolean)}
+ */
+ @Deprecated
+ public void createContent(PackageDetails details, InputStream content, boolean unzip, boolean createBackup) {
+ File destinationContentFile = getPath(details);
+ try {
+ if (createBackup) {
+ moveToBackup(destinationContentFile, ".bak");
+ }
+ if (unzip) {
+ ZipUtil.unzipFile(content, destinationContentFile);
+ computeAndSaveSHA(destinationContentFile);
+ } else {
+ FileUtil.writeFile(content, destinationContentFile);
+ }
+ details.setFileName(destinationContentFile.getPath());
+ } catch (IOException e) {
+ throw new RuntimeException("Error creating artifact from details: " + destinationContentFile, e);
+ }
+ }
+
+ /**
* Try to move the passed contentFile to a backup named contentFile + suffix
* @param contentFile File object pointing to the original file
* @param suffix the suffix to tack on
commit 581324eeb3d32f4d8879d4749423fbde0f76de8c
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Aug 8 13:41:26 2012 +0200
[BZ 846623] - When creating the "child" alert definitions of group or template alert definitions, pass the real user that creates the alert def and circumvent authz.
This behaves exactly the same as before but instead of bypassing the authz by passing the overlord when creating the child alert,
a new local SLSB method is used that doesn't perform the authz checks and can therefore receive the original user that request the creation of the group/template
alert def.
This is good for the CLI alert sender that, when creating an alert script to be run as "myself", checks if the user creating the alert def is the same as the one set
to run it.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
index c4fdcda..927ae74 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
@@ -196,9 +196,23 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
return results;
}
+ @Override
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public int createDependentAlertDefinition(Subject subject, AlertDefinition alertDefinition, int resourceId)
+ throws InvalidAlertDefinitionException {
+
+ return createAlertDefinitionInternal(subject, alertDefinition, resourceId, false);
+ }
+
+ @Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public int createAlertDefinition(Subject subject, AlertDefinition alertDefinition, Integer resourceId)
throws InvalidAlertDefinitionException {
+
+ return createAlertDefinitionInternal(subject, alertDefinition, resourceId, true);
+ }
+
+ private int createAlertDefinitionInternal(Subject subject, AlertDefinition alertDefinition, Integer resourceId, boolean checkPerms) throws InvalidAlertDefinitionException {
checkAlertDefinition(subject, alertDefinition, resourceId);
// if this is an alert definition, set up the link to a resource
@@ -212,7 +226,7 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
}
// after the resource is set up (in the case of non-templates), we can use the checkPermission on it
- if (checkPermission(subject, alertDefinition) == false) {
+ if (checkPerms && checkPermission(subject, alertDefinition) == false) {
if (alertDefinition.getResourceType() != null) {
throw new PermissionException("User [" + subject.getName()
+ "] does not have permission to create alert templates for type ["
@@ -265,7 +279,7 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
return alertDefinition.getId();
}
-
+
private void fixRecoveryId(AlertDefinition definition) {
try {
if (definition.getParentId() != 0 && definition.getRecoveryId() != 0) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
index d663198..81f0ac0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
@@ -48,6 +48,25 @@ public interface AlertDefinitionManagerLocal {
int createAlertDefinition(Subject subject, AlertDefinition alertDefinition, Integer resourceId)
throws InvalidAlertDefinitionException;
+ /**
+ * This is exactly the same as {@link #createAlertDefinition(Subject, AlertDefinition, Integer)} but
+ * assumes the resource is part of a group (or has given resource type for templates) for which
+ * a group or template alert definition is being created.
+ * <p>
+ * This method assumes the caller already checked the subject has permissions to create a group or template alert
+ * definition on a group / resource type the resource is member of.
+ * <p>
+ * In another words this method is a helper to
+ * {@link GroupAlertDefinitionManagerLocal#createGroupAlertDefinitions(Subject, AlertDefinition, Integer)} and
+ * {@link AlertTemplateManagerLocal#createAlertTemplate(Subject, AlertDefinition, Integer)}.
+ *
+ * @param subject the user that is creating the group or template alert definition
+ * @param alertDefinition the alert definition on the resource
+ * @param resourceId the resource
+ * @return the id of the newly created alert definition
+ */
+ int createDependentAlertDefinition(Subject subject, AlertDefinition alertDefinition, int resourceId);
+
boolean isEnabled(Integer definitionId);
boolean isTemplate(Integer definitionId);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
index 5b4ad77..cda1e0f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
@@ -128,7 +128,6 @@ public class AlertTemplateManagerBean implements AlertTemplateManagerLocal {
+ alertTemplate.toSimpleString(), t);
}
- Subject overlord = subjectManager.getOverlord();
Throwable firstThrowable = null;
List<Integer> resourceIdsForType = getCommittedResourceIdsNeedingTemplateApplication(user, alertTemplateId,
@@ -140,8 +139,8 @@ public class AlertTemplateManagerBean implements AlertTemplateManagerLocal {
AlertDefinition childAlertDefinition = new AlertDefinition(alertTemplate);
childAlertDefinition.setParentId(alertTemplate.getId());
- // persist the child using overlord
- alertDefinitionManager.createAlertDefinition(overlord, childAlertDefinition, resourceId);
+ // persist the child as a dependent alert definition
+ alertDefinitionManager.createDependentAlertDefinition(user, childAlertDefinition, resourceId);
} catch (Throwable t) {
// continue on error, create as many as possible
if (firstThrowable == null) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java
index cde2f04..6df9ae0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java
@@ -137,6 +137,7 @@ public class GroupAlertDefinitionManagerBean implements GroupAlertDefinitionMana
return list;
}
+ @Override
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public int createGroupAlertDefinitions(Subject subject, AlertDefinition groupAlertDefinition,
Integer resourceGroupId) throws InvalidAlertDefinitionException, AlertDefinitionCreationException {
@@ -151,7 +152,6 @@ public class GroupAlertDefinitionManagerBean implements GroupAlertDefinitionMana
+ " with data " + groupAlertDefinition.toSimpleString(), t);
}
- Subject overlord = subjectManager.getOverlord();
Throwable firstThrowable = null;
List<Integer> resourceIdsForGroup = getCommittedResourceIdsNeedingGroupAlertDefinitionApplication(subject,
@@ -164,7 +164,7 @@ public class GroupAlertDefinitionManagerBean implements GroupAlertDefinitionMana
childAlertDefinition.setGroupAlertDefinition(groupAlertDefinition);
// persist the child
- alertDefinitionManager.createAlertDefinition(overlord, childAlertDefinition, resourceId);
+ alertDefinitionManager.createDependentAlertDefinition(subject, childAlertDefinition, resourceId);
} catch (Throwable t) {
// continue on error, create as many as possible
if (firstThrowable == null) {
11 years, 9 months