[rhq] modules/enterprise
by mazz
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
New commits:
commit 74fe0df63135344a74cf0f58edf6f22a5c6c9124
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Dec 20 17:28:21 2011 -0500
[BZ 766574] for some reason, the remote interface was removed from the discovery SLSB. put it back.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java
index fcb2f9e..2ea6234 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java
@@ -99,7 +99,7 @@ import org.rhq.enterprise.server.util.LookupUtil;
* @author Greg Hinkle
*/
@Stateless
-public class DiscoveryBossBean implements DiscoveryBossLocal {
+public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemote {
private final Log log = LogFactory.getLog(DiscoveryBossBean.class.getName());
12 years, 4 months
[rhq] modules/enterprise
by mazz
modules/enterprise/binding/src/main/java/org/rhq/bindings/output/TabularWriter.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
New commits:
commit a638398ba148f419eba537b5851dac8955dad482
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Dec 20 14:40:53 2011 -0500
[BZ 766574] fix NPE if there is no availability yet
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/output/TabularWriter.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/output/TabularWriter.java
index 6ead45c..94a4d05 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/output/TabularWriter.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/output/TabularWriter.java
@@ -44,6 +44,7 @@ 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.measurement.AvailabilityType;
import org.rhq.core.domain.measurement.ResourceAvailability;
import org.rhq.core.domain.resource.ResourceType;
@@ -715,7 +716,8 @@ public class TabularWriter {
} else if (object instanceof ResourceType) {
return ((ResourceType) object).getName();
} else if (object instanceof ResourceAvailability) {
- return ((ResourceAvailability) object).getAvailabilityType().getName();
+ AvailabilityType availType = ((ResourceAvailability) object).getAvailabilityType();
+ return (availType == null) ? "?" : availType.getName();
} else if (object != null && object.getClass().isArray()) {
return Arrays.toString((Object[]) object);
} else {
12 years, 4 months
[rhq] modules/core modules/plugins
by Heiko W. Rupp
modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java | 54 -
modules/core/plugin-container/src/main/java/org/rhq/core/pc/standaloneContainer/Command.java | 4
modules/plugins/jboss-as-7/d2d.sh | 2
modules/plugins/jboss-as-7/pom.xml | 15
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/AS7Authenticator.java | 26
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java | 35
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASUploadConnection.java | 6
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/AbstractBaseDiscovery.java | 246 ++---
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java | 10
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java | 19
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java | 63 +
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationLoadDelegate.java | 9
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java | 57 -
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/Domain2Descriptor.java | 57 -
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/HostControllerComponent.java | 4
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASDiscovery.java | 3
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ServerGroupComponent.java | 2
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java | 2
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/json/Address.java | 27
modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml | 418 +++++----
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/AbstractConfigurationHandlingTest.java | 3
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/ConfigurationUpdatingTest.java | 16
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/XmlFileReadingTest.java | 133 ++
modules/plugins/jboss-as-7/src/test/resources/host1.xml | 92 ++
modules/plugins/jboss-as-7/src/test/resources/host2.xml | 91 ++
modules/plugins/jboss-as-7/src/test/resources/standalone70.xml | 433 +++++++++
modules/plugins/jboss-as-7/src/test/resources/standalone71.xml | 453 ++++++++++
27 files changed, 1897 insertions(+), 383 deletions(-)
New commits:
commit 19097edb5d591dae5ae6fdf7565b682cd5b1506c
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri Nov 18 15:23:26 2011 +0100
Several improvements to the AS7 plugin:
* BZ 754858 - in as7.1 the management port is now determined via socket binding reference. Also allow discover older versions.
The xml parsing code has been rewritten to use XPath expressions.
* BZ 754849 supply authentication to the remote. The JVM calls back to the AS7 Authenticator when needed.
* Prevent a NPE in the case we get no results.
* Add an operation to install a management user.
* BZ 709678 - update jboss web to latest code and enable updating of properties.
* Allow to merge in new/changed properties instead of requiring to supply the whole configuration in the standalone container.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java
index 10b1b1b..07e2965 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java
@@ -21,7 +21,6 @@ package org.rhq.core.pc;
import java.io.*;
import java.util.ArrayList;
import java.util.EnumSet;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -31,6 +30,7 @@ import java.util.Stack;
import org.rhq.core.clientapi.agent.PluginContainerException;
import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.Property;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.configuration.definition.PropertyDefinition;
@@ -75,8 +75,6 @@ public class StandaloneContainer {
InventoryManager inventoryManager;
/** Global operation counter */
Integer opId = 0;
- /** Map of resource plugin configurations */
- Map<Integer, Configuration> resConfigMap = new HashMap<Integer, Configuration>();
/** variable set by find() and which can be used in set() */
int dollarR = 0;
/** Do we read from stdin ? */
@@ -340,32 +338,58 @@ public class StandaloneContainer {
}
- private void setResourcePluginConfig(String[] tokens,boolean pluginConfig) {
+ private void setResourcePluginConfig(String[] tokens,boolean isPluginConfig) throws PluginContainerException {
if (resourceId == 0) {
System.err.println("No resource set");
return;
}
+ Configuration newConfig = null;
Configuration config = null;
- if (tokens.length > 1)
- config = createConfigurationFromString(tokens[1]);
- else {
+ boolean merge=false;
+ int pos = 1;
+ if (tokens.length < 2) {
+ System.err.println("Need at least 1 token");
+ return;
+ }
+ if (tokens[1].equals("-m")) {
+ merge = true;
+ pos++;
+ }
+ if (tokens.length < pos+1) {
System.err.println("Need at least 1 token");
return;
}
- ConfigurationUpdateRequest request = new ConfigurationUpdateRequest(1,config,resourceId);
+ newConfig = createConfigurationFromString(tokens[pos]);
ConfigurationManager cm = pc.getConfigurationManager();
- if (pluginConfig) {
- pc.getInventoryManager().getResourceContainer(resourceId).getResource().setPluginConfiguration(config);
- } else
- cm.updateResourceConfiguration(request);
-
-
+ if (isPluginConfig) {
+ Resource targetResource = pc.getInventoryManager().getResourceContainer(resourceId).getResource();
+ config = targetResource.getPluginConfiguration();
+ if (merge) {
+ // copy over existing properties that are not in newConfig
+ for (Property p : config.getProperties()) {
+ if (newConfig.get(p.getName())==null)
+ newConfig.put(p);
+ }
+ }
+ targetResource.setPluginConfiguration(newConfig);
+ } else {
+ config = pc.getConfigurationManager().loadResourceConfiguration(resourceId);
+ if (merge) {
+ // copy over existing properties that are not in newConfig
+ for (Property p : config.getProperties()) {
+ if (newConfig.get(p.getName())==null)
+ newConfig.put(p);
+ }
+ }
+ ConfigurationUpdateRequest request = new ConfigurationUpdateRequest(1,newConfig,resourceId);
+ cm.updateResourceConfiguration(request);
+ }
}
@@ -715,7 +739,7 @@ public class StandaloneContainer {
}
private void showConfig(Configuration config) {
- System.out.println(config.getProperties());
+ System.out.println(config.getProperties()); // TODO convert to input format or key=value or json
}
}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/standaloneContainer/Command.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/standaloneContainer/Command.java
index c992000..0f1d01d 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/standaloneContainer/Command.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/standaloneContainer/Command.java
@@ -47,8 +47,8 @@ public enum Command {
WAIT("w", "milliseconds", 1, "Waits the given amount of time"),
P_CONFIG("pc", "", 0, "Shows the plugin configuration of the current resource."),
R_CONFIG("rc", "", 0, "Shows the resource configuration of the current resource."),
- SR_CONFIG("rcs", "", 0, "[parameters] set resource config "),
- SP_CONFIG("pcs", "", 0, "[parameters] set plugin config ")
+ SR_CONFIG("rcs", "", 1, "[-m] [parameters] set resource config. '-m' merges with current config; default is overwrite."),
+ SP_CONFIG("pcs", "", 1, "[-m] [parameters] set plugin config.'-m' merges with current config; default is overwrite.")
;
private String abbrev;
diff --git a/modules/plugins/jboss-as-7/d2d.sh b/modules/plugins/jboss-as-7/d2d.sh
index 16c1e57..d36d8e9 100755
--- a/modules/plugins/jboss-as-7/d2d.sh
+++ b/modules/plugins/jboss-as-7/d2d.sh
@@ -1,2 +1,2 @@
#!/bin/sh
-java -cp target/rhq-jboss-as-7-plugin-4.1.0-SNAPSHOT.jar:/im/rhq/modules/enterprise/agent/target/rhq-agent/lib/commons-logging-1.1.0.jboss.jar:/Users/hrupp/.m2/repository/org/codehaus/jackson/jackson-core-asl/1.7.4/jackson-core-asl-1.7.4.jar:/Users/hrupp/.m2/repository/org/codehaus/jackson/jackson-mapper-asl/1.7.4/jackson-mapper-asl-1.7.4.jar org.rhq.modules.plugins.jbossas7.Domain2Descriptor $*
+java -cp target/rhq-jboss-as-7-plugin-4.3.0-SNAPSHOT.jar:/im/rhq/modules/enterprise/agent/target/rhq-agent/lib/commons-logging-1.1.0.jboss.jar:/Users/hrupp/.m2/repository/org/codehaus/jackson/jackson-core-asl/1.7.4/jackson-core-asl-1.7.4.jar:/Users/hrupp/.m2/repository/org/codehaus/jackson/jackson-mapper-asl/1.7.4/jackson-mapper-asl-1.7.4.jar org.rhq.modules.plugins.jbossas7.Domain2Descriptor $*
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index e069be3..8220355 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -17,6 +17,7 @@
<properties>
<json.version>${project.json.version}</json.version>
<jackson.version>1.7.4</jackson.version>
+ <jboss.sasl.version>1.0.0.Beta9</jboss.sasl.version>
</properties>
<build>
@@ -49,6 +50,11 @@
<artifactId>jackson-core-asl</artifactId>
<version>${jackson.version}</version>
</artifactItem>
+ <artifactItem>
+ <groupId>org.jboss.sasl</groupId>
+ <artifactId>jboss-sasl</artifactId>
+ <version>${jboss.sasl.version}</version>
+ </artifactItem>
</artifactItems>
<outputDirectory>${project.build.outputDirectory}/lib</outputDirectory>
@@ -76,7 +82,7 @@
<plugins>
<plugin>
- <artifactId>maven-antrun-plugin</artifactId>
+ <artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
@@ -204,6 +210,13 @@
<scope>provided</scope>
</dependency>
+ <!-- for the password hashing - we may want to copy the relevant stuff over ourselves -->
+ <dependency>
+ <groupId>org.jboss.sasl</groupId>
+ <artifactId>jboss-sasl</artifactId>
+ <version>${jboss.sasl.version}</version>
+ </dependency>
+
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/AS7Authenticator.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/AS7Authenticator.java
new file mode 100644
index 0000000..703e177
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/AS7Authenticator.java
@@ -0,0 +1,26 @@
+package org.rhq.modules.plugins.jbossas7;
+
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+
+/**
+ * Authenticator to authenticate against as7
+ * @author Heiko W. Rupp
+ */
+public class AS7Authenticator extends Authenticator {
+
+ private String user;
+ private String pass;
+
+ public AS7Authenticator(String user, String pass) {
+ this.user = user;
+ this.pass = pass;
+ if (this.pass==null)
+ this.pass=""; // prevent NPE later
+ }
+
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(user,pass.toCharArray());
+ }
+}
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java
index 40561a0..cf0b5b9 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java
@@ -23,15 +23,14 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonNode;
-import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
@@ -51,15 +50,17 @@ public class ASConnection {
String urlString;
private ObjectMapper mapper;
public static boolean verbose = false; // This is a variable on purpose, so devs can switch it on in the debugger or in the agent
- private HttpURLConnection conn;
+ Authenticator passwordAuthenticator ;
/**
* Construct an ASConnection object. The real "physical" connection is done in
* #executeRaw.
* @param host Host of the DomainController or standalone server
* @param port Port of the JSON api.
+ * @param user user needed for authentication
+ * @param password password needed for authentication
*/
- public ASConnection(String host, int port) {
+ public ASConnection(String host, int port, String user, String password) {
try {
url = new URL("http", host, port, MANAGEMENT);
@@ -69,6 +70,9 @@ public class ASConnection {
throw new IllegalArgumentException(e.getMessage());
}
+ passwordAuthenticator = new AS7Authenticator(user,password);
+ Authenticator.setDefault(passwordAuthenticator);
+
// read system property "as7plugin.verbose"
verbose = Boolean.getBoolean("as7plugin.verbose");
@@ -92,14 +96,15 @@ public class ASConnection {
InputStream inputStream = null;
BufferedReader br = null;
InputStream es = null;
+ HttpURLConnection conn=null;
long t1 = System.currentTimeMillis();
try {
-
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
- conn.addRequestProperty("Content-Type","application/json");
+ conn.addRequestProperty("Content-Type", "application/json");
conn.addRequestProperty("Accept","application/json");
+
OutputStream out = conn.getOutputStream();
String result = mapper.writeValueAsString(operation);
@@ -236,6 +241,7 @@ public class ASConnection {
if (node==null) {
log.warn("Operation [" + op + "] returned null");
+ return null;
}
try {
Result res;
@@ -250,22 +256,5 @@ public class ASConnection {
}
}
- public void writeValue(OutputStream out, Object value) throws IOException, JsonGenerationException,
- JsonMappingException {
- // JsonGenerator jgen = _jsonFactory.createJsonGenerator(out, JsonEncoding.UTF8);
- // JsonGenerator jgen = mapper.createJsonGenerator(out, JsonEncoding.UTF8);
- // JsonGenerator jgen = new Js
- // boolean closed = false;
- // try {
- // writeValue(jgen, value);
- // closed = true;
- // jgen.close();
- // } finally {
- // if (!closed) {
- // jgen.close();
- // }
- // }
-
- }
}
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASUploadConnection.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASUploadConnection.java
index d17a311..a5b8bdd 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASUploadConnection.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASUploadConnection.java
@@ -26,6 +26,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
+import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.URL;
@@ -55,15 +56,18 @@ public class ASUploadConnection {
private static final Log log = LogFactory.getLog(ASUploadConnection.class);
+ Authenticator passwordAuthenticator ;
BufferedOutputStream os = null;
InputStream is = null;
private HttpURLConnection connection;
private String host;
private int port;
- public ASUploadConnection(String dcHost, int port) {
+ public ASUploadConnection(String dcHost, int port, String user, String password) {
this.host = dcHost;
this.port = port;
+ passwordAuthenticator = new AS7Authenticator(user,password);
+ Authenticator.setDefault(passwordAuthenticator);
}
public OutputStream getOutputStream(String fileName) {
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/AbstractBaseDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/AbstractBaseDiscovery.java
index 8736495..78b1543 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/AbstractBaseDiscovery.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/AbstractBaseDiscovery.java
@@ -24,15 +24,16 @@ import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-import org.rhq.core.pluginapi.inventory.ResourceComponent;
-import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
import org.rhq.core.system.ProcessInfo;
/**
@@ -40,14 +41,24 @@ import org.rhq.core.system.ProcessInfo;
* in the area of processes and host.xml
* @author Heiko W. Rupp
*/
-public abstract class AbstractBaseDiscovery<T extends ResourceComponent<?>> implements ResourceDiscoveryComponent<T> {
+public class AbstractBaseDiscovery {
static final String DORG_JBOSS_BOOT_LOG_FILE = "-Dorg.jboss.boot.log.file=";
private static final String DJBOSS_SERVER_HOME_DIR = "-Djboss.home.dir";
static final int DEFAULT_MGMT_PORT = 9990;
private static final String JBOSS_AS_PREFIX = "jboss-as-";
+ static final String CALL_READ_STANDALONE_OR_HOST_XML_FIRST = "hostXml is null. You need to call 'readStandaloneOrHostXml' first.";
protected Document hostXml;
protected final Log log = LogFactory.getLog(this.getClass());
private static final String JBOSS_EAP_PREFIX = "jboss-eap-";
+ private XPathFactory factory;
+
+
+
+ protected AbstractBaseDiscovery() {
+ synchronized (this) {
+ factory = XPathFactory.newInstance();
+ }
+ }
/**
* Read the host.xml or standalone.xml file depending on isDomainMode. If isDomainMode is true,
@@ -58,6 +69,10 @@ public abstract class AbstractBaseDiscovery<T extends ResourceComponent<?>> impl
*/
protected void readStandaloneOrHostXml(ProcessInfo processInfo, boolean isDomainMode) {
String hostXmlFile = getHostXmlFileLocation(processInfo,isDomainMode);
+ readStandaloneOrHostXmlFromFile(hostXmlFile);
+ }
+
+ protected void readStandaloneOrHostXmlFromFile(String hostXmlFile) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
@@ -107,99 +122,50 @@ public abstract class AbstractBaseDiscovery<T extends ResourceComponent<?>> impl
*/
protected HostPort getManagementPortFromHostXml(String[] commandLine) {
if (hostXml==null)
- throw new IllegalArgumentException("hostXml is null. You need to call 'readStandaloneOrHostXml' first.");
- Element host = hostXml.getDocumentElement();
- NodeList interfaceParent = host.getElementsByTagName("management-interfaces");
- if (interfaceParent ==null || interfaceParent.getLength()==0) {
- log.warn("No <management-interfaces> found in host.xml");
- return new HostPort();
- }
- NodeList mgmtInterfaces = interfaceParent.item(0).getChildNodes();
- if (mgmtInterfaces==null || mgmtInterfaces.getLength()==0) {
- log.warn("No <*-interface> found in host.xml");
- return new HostPort();
+ throw new IllegalArgumentException(CALL_READ_STANDALONE_OR_HOST_XML_FIRST);
+
+ String portString;
+ String interfaceExpession;
+
+ String socketBindingName = obtainXmlPropertyViaXPath(
+ "//management/management-interfaces/http-interface/socket-binding/@http");
+ if (socketBindingName==null || socketBindingName.isEmpty()) {
+ // old AS7.0, early 7.1 style
+ portString = obtainXmlPropertyViaXPath("//management/management-interfaces/http-interface/@port");
+ String interfaceName = obtainXmlPropertyViaXPath(
+ "//management/management-interfaces/http-interface/@interface");
+ interfaceExpession = obtainXmlPropertyViaXPath(
+ "/server/interfaces/interface[@name='" + interfaceName + "']/inet-address/@value");
}
- for (int i = 0 ; i < mgmtInterfaces.getLength(); i++) {
- if (!(mgmtInterfaces.item(i) instanceof Element))
- continue;
-
- Element mgmtInterface = (Element) mgmtInterfaces.item(i);
- if (mgmtInterface.getNodeName().equals("http-interface")) {
- String tmp = mgmtInterface.getAttribute("port"); // TODO if we don't find it, check for socket-binding
- int port;
- if (!tmp.isEmpty())
- port = Integer.valueOf(tmp);
- else
- port = DEFAULT_MGMT_PORT;
- HostPort hp = new HostPort();
- hp.isLocal=true; // TODO adjust when host != localhost
- hp.port = port;
-
- String nIf = mgmtInterface.getAttribute("interface");
- if (!nIf.isEmpty())
- hp.host = getInterface(nIf, commandLine);
- else
- hp.host = "localhost";
- return hp;
- }
- }
- return new HostPort();
- }
+ else {
+ // later AS7.1 and EAP6
+ portString = obtainXmlPropertyViaXPath(
+ "/server/socket-binding-group/socket-binding[@name='" + socketBindingName + "']/@port");
+ String interfaceName = obtainXmlPropertyViaXPath(
+ "/server/socket-binding-group/socket-binding[@name='" + socketBindingName + "']/@interface");
- /**
- * Try to obtain the management interface IP from the host/standalone.xml files
- *
- * @param nIf Interface to look for
- * @param commandLine Command line arguments of the process
- * @return IP address to use
- */
- private String getInterface(String nIf, String[] commandLine) {
- if (hostXml==null)
- throw new IllegalArgumentException("hostXml is null. You need to call 'readStandaloneOrHostXml' first.");
+ // TODO the next may also be expressed differently
+ interfaceExpession = obtainXmlPropertyViaXPath(
+ "/server/interfaces/interface[@name='" + interfaceName + "']/inet-address/@value");
- Element host = hostXml.getDocumentElement();
- NodeList interfaceParent = host.getElementsByTagName("interfaces");
- if (interfaceParent ==null || interfaceParent.getLength()==0) {
- log.warn("No <interfaces> found in host.xml");
- return null;
- }
- NodeList mgmtInterfaces = interfaceParent.item(0).getChildNodes();
- if (mgmtInterfaces==null || mgmtInterfaces.getLength()==0) {
- log.warn("No <*-interface> found in host.xml");
- return null;
}
- for (int i = 0 ; i < mgmtInterfaces.getLength(); i++) {
- if (!(mgmtInterfaces.item(i) instanceof Element))
- continue;
- Element mgmtInterface = (Element) mgmtInterfaces.item(i);
- if (mgmtInterface.getNodeName().equals("interface")) {
- String name = mgmtInterface.getAttribute("name");
- if (!name.equals(nIf))
- continue;
-
- NodeList nl = mgmtInterface.getChildNodes();
- if (nl!=null) {
- for (int j = 0 ; j < nl.getLength(); j++) {
- if (!(nl.item(j) instanceof Element))
- continue;
-
- String nodeName = nl.item(j).getNodeName();
- if (nodeName.equals("any-ipv4-address"))
- return "0.0.0.0";
-
- String value = ((Element) nl.item(j)).getAttribute("value");
- value = replaceExpression(value, commandLine);
- return value;
-
- // TODO check for <any> and so on
- }
- }
- }
+ HostPort hp = new HostPort();
+
+ if (!interfaceExpession.isEmpty())
+ hp.host = replaceDollarExpression(interfaceExpession, commandLine);
+ else
+ hp.host = "localhost"; // Fallback
+
+ if (portString!=null && !portString.isEmpty()) {
+ hp.port = Integer.valueOf(portString);
}
- return null; // TODO: Customise this generated block
+ else
+ hp.port = 9990; // Fallback to default
+ return hp;
}
+
/**
* Check if the passed value has an expression in the form of ${var} or ${var:default},
* try to resolve it. Resolution is done by looking at the command line to see if
@@ -209,7 +175,7 @@ public abstract class AbstractBaseDiscovery<T extends ResourceComponent<?>> impl
* @param commandLine The command line from the process
* @return resolved value
*/
- private String replaceExpression(String value, String[] commandLine) {
+ private String replaceDollarExpression(String value, String[] commandLine) {
if (!value.contains("${"))
return value;
@@ -250,12 +216,12 @@ public abstract class AbstractBaseDiscovery<T extends ResourceComponent<?>> impl
/**
* Try to determine the host name - that is the name of a standalone server or a
- * host in domain mode by looking at the standalone/host.xml files
+ * host in domain mode by looking at the standalone.xml/host.xml files
* @return server name
*/
protected String findHostName() {
if (hostXml==null)
- throw new IllegalArgumentException("hostXml is null. You need to call 'readStandaloneOrHostXml' first.");
+ throw new IllegalArgumentException(CALL_READ_STANDALONE_OR_HOST_XML_FIRST);
String hostName = hostXml.getDocumentElement().getAttribute("name");
return hostName;
@@ -267,29 +233,53 @@ public abstract class AbstractBaseDiscovery<T extends ResourceComponent<?>> impl
*/
protected HostPort getDomainControllerFromHostXml() {
if (hostXml==null)
- throw new IllegalArgumentException("hostXml is null. You need to call 'readStandaloneOrHostXml' first.");
-
- Element host = hostXml.getDocumentElement();
- NodeList dcParent = host.getElementsByTagName("domain-controller");
- if (dcParent==null || dcParent.getLength()==0)
- return new HostPort(false);
- NodeList interfs = dcParent.item(0).getChildNodes();
- for (int i = 0; i < interfs.getLength(); i++) {
- if (!(interfs.item(i)instanceof Element))
- continue;
-
- Element interf = (Element) interfs.item(i);
- if (interf.getNodeName().equals("local"))
- return new HostPort();
-
- // not local, so get the remote
- HostPort hp = new HostPort(false);
- hp.host = interf.getAttribute("host");
- hp.port = Integer.parseInt(interf.getAttribute("port"));
- return hp;
+ throw new IllegalArgumentException(CALL_READ_STANDALONE_OR_HOST_XML_FIRST);
+
+
+ // first check remote, as we can't distinguish between a missing local element or
+ // and empty one which is the default
+ String remoteHost = obtainXmlPropertyViaXPath("/host/domain-controller/remote/@host");
+ String portString = obtainXmlPropertyViaXPath("/host/domain-controller/remote/@port");
+
+ HostPort hp;
+ if (!remoteHost.isEmpty() && !portString.isEmpty()) {
+ hp = new HostPort(false);
+ hp.host = remoteHost;
+ hp.port = Integer.parseInt(portString);
}
+ else {
+ hp = new HostPort(true);
+ hp.port = 9999;
+ }
+
+ return hp;
+
+ }
+
+ String getManagementSecurtiyRealmFromHostXml() {
+ if (hostXml==null)
+ throw new IllegalArgumentException(CALL_READ_STANDALONE_OR_HOST_XML_FIRST);
+
+ String realm = obtainXmlPropertyViaXPath("//management/management-interfaces/http-interface/@security-realm");
+
+ return realm;
+ }
+
+ String getSecurityPropertyFileFromHostXml(String baseDir, AS7Mode mode, String realm) {
+ if (hostXml==null)
+ throw new IllegalArgumentException(CALL_READ_STANDALONE_OR_HOST_XML_FIRST);
+
+ // TODO make realm variable
+ String fileName = obtainXmlPropertyViaXPath("//security-realms/security-realm[@name='" + realm + "']/authentication/properties/@path");
+ String relDir = obtainXmlPropertyViaXPath("//security-realms/security-realm[@name='" + realm + "']/authentication/properties/@relative-to");
+
+ String fullName ;
+ if (relDir.equals("jboss.server.config.dir"))
+ fullName = baseDir + File.separator + mode.getBaseDir() + File.separator + "configuration" + File.separator + fileName;
+ else
+ fullName = relDir + File.separator + fileName;
- return new HostPort(false);
+ return fullName;
}
/**
@@ -332,6 +322,34 @@ public abstract class AbstractBaseDiscovery<T extends ResourceComponent<?>> impl
}
/**
+ * Run the passed xpathExpression on the prepopulated hostXml document and
+ * return the target element or attribute as a String.
+ * @param xpathExpression XPath Expression to evaluate
+ * @return String value of the Element or Attribute the XPath was pointing to.
+ * Null in case the xpathExpression could not be evaluated.
+ * @throws IllegalArgumentException if hostXml is null
+ *
+ */
+ protected String obtainXmlPropertyViaXPath(String xpathExpression) {
+ if (hostXml==null)
+ throw new IllegalArgumentException(CALL_READ_STANDALONE_OR_HOST_XML_FIRST);
+
+
+ XPath xpath = factory.newXPath();
+ try {
+ XPathExpression expr = xpath.compile(xpathExpression);
+
+ Object result = expr.evaluate(hostXml, XPathConstants.STRING);
+
+ return result.toString();
+ } catch (XPathExpressionException e) {
+ log.error("Evaluation XPath expression failed: " + e.getMessage());
+ return null;
+ }
+ }
+
+
+ /**
* Helper class that holds information about the host,port tuple
*/
protected static class HostPort {
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java
index 7395233..3f03e52 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java
@@ -89,6 +89,8 @@ public class BaseComponent<T extends ResourceComponent<?>> implements ResourceCo
String host;
int port;
private boolean verbose = ASConnection.verbose;
+ String managementUser;
+ String managementPassword;
/**
* Return availability of this resource
@@ -99,7 +101,7 @@ public class BaseComponent<T extends ResourceComponent<?>> implements ResourceCo
ReadResource op = new ReadResource(address);
Result res = connection.execute(op);
- return res.isSuccess()? AvailabilityType.UP: AvailabilityType.DOWN;
+ return (res!=null && res.isSuccess()) ? AvailabilityType.UP: AvailabilityType.DOWN;
}
@@ -115,7 +117,9 @@ public class BaseComponent<T extends ResourceComponent<?>> implements ResourceCo
host = pluginConfiguration.getSimpleValue("hostname", LOCALHOST);
String portString = pluginConfiguration.getSimpleValue("port", DEFAULT_HTTP_MANAGEMENT_PORT);
port = Integer.parseInt(portString);
- connection = new ASConnection(host,port);
+ managementUser = pluginConfiguration.getSimpleValue("user","-unset-");
+ managementPassword = pluginConfiguration.getSimpleValue("password","-unset-");
+ connection = new ASConnection(host,port, managementUser, managementPassword);
}
else {
connection = ((BaseComponent)context.getParentResourceComponent()).getASConnection();
@@ -310,7 +314,7 @@ public class BaseComponent<T extends ResourceComponent<?>> implements ResourceCo
ContentServices contentServices = cctx.getContentServices();
String resourceTypeName = report.getResourceType().getName();
- ASUploadConnection uploadConnection = new ASUploadConnection(host,port);
+ ASUploadConnection uploadConnection = new ASUploadConnection(host,port, managementUser, managementPassword);
OutputStream out = uploadConnection.getOutputStream(details.getFileName());
contentServices.downloadPackageBitsForChildResource(cctx, resourceTypeName, details.getKey(), out);
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
index 54e7e78..3f049dc 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
@@ -75,7 +75,7 @@ public class BaseProcessDiscovery extends AbstractBaseDiscovery implements Resou
String serverNameFull;
String serverName;
String psName = psr.getProcessScan().getName();
- String description = discoveryContext.getResourceType().getDescription();
+ String description;
String homeDir = getHomeDirFromCommandLine(commandLine);
String version = determineServerVersionFromHomeDir(homeDir);
boolean isEAP = false;
@@ -115,7 +115,7 @@ public class BaseProcessDiscovery extends AbstractBaseDiscovery implements Resou
String host = findHost(psr.getProcessInfo(), true);
config.put(new PropertySimple("domainHost", host));
- fillUserPassFromFile(config, "domain", homeDir);
+ fillUserPassFromFile(config, AS7Mode.DOMAIN, homeDir);
// provide running config
String domainConfig = getServerConfigFromCommandLine(commandLine, AS7Mode.DOMAIN);
@@ -157,7 +157,7 @@ public class BaseProcessDiscovery extends AbstractBaseDiscovery implements Resou
config.put(new PropertySimple("config",serverConfig));
config.put(new PropertySimple("startScript",AS7Mode.STANDALONE.getStartScript()));
- fillUserPassFromFile(config, "standalone", serverNameFull);
+ fillUserPassFromFile(config, AS7Mode.STANDALONE, serverNameFull);
//preload server.log file for event log monitoring
logFile = bootLogFile.substring(0, bootLogFile.lastIndexOf("/")) + File.separator + "server.log";
@@ -173,6 +173,8 @@ public class BaseProcessDiscovery extends AbstractBaseDiscovery implements Resou
HostPort managmentPort = getManagementPortFromHostXml(commandLine);
config.put(new PropertySimple("hostname", managmentPort.host));
config.put(new PropertySimple("port", managmentPort.port));
+ config.put(new PropertySimple("realm",getManagementSecurtiyRealmFromHostXml()));
+
// String javaClazz = psr.getProcessInfo().getName();
/*
@@ -207,11 +209,14 @@ public class BaseProcessDiscovery extends AbstractBaseDiscovery implements Resou
}
- private void fillUserPassFromFile(Configuration config, String mode, String baseDir) {
+ private void fillUserPassFromFile(Configuration config, AS7Mode mode, String baseDir) {
+
+// String configDir = baseDir + File.separator + mode + File.separator + "configuration";
+ String realm = getManagementSecurtiyRealmFromHostXml();
+ String fileName = getSecurityPropertyFileFromHostXml(baseDir,mode, realm);
- String configDir = baseDir + File.separator + mode + File.separator + "configuration";
- File file = new File(configDir, "mgmt-users.properties");
+ File file = new File(fileName);
if (!file.exists() || !file.canRead()) {
if (log.isDebugEnabled())
log.debug("No console user properties file found at [" + file.getAbsolutePath()
@@ -234,7 +239,7 @@ public class BaseProcessDiscovery extends AbstractBaseDiscovery implements Resou
String user = line.substring(0, line.indexOf("="));
String pass = line.substring(line.indexOf("=") + 1);
config.put(new PropertySimple("user", user));
- config.put(new PropertySimple("password", pass));
+// config.put(new PropertySimple("password", pass)); // this is now hashed, so no point in supplying it
}
} catch (IOException e) {
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 581c4e1..3a3fa03 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
@@ -19,13 +19,20 @@
package org.rhq.modules.plugins.jbossas7;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.net.ConnectException;
+import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.jboss.sasl.util.UsernamePasswordHashUtil;
+
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.pluginapi.operation.OperationResult;
import org.rhq.core.pluginapi.util.ProcessExecutionUtility;
@@ -137,6 +144,11 @@ public class BaseServerComponent extends BaseComponent {
*/
protected OperationResult postProcessResult(String name, Result res) {
OperationResult operationResult = new OperationResult();
+ if (res==null) {
+ operationResult.setErrorMessage("No result received from server");
+ return operationResult;
+ }
+
if (name.equals("shutdown") || name.equals("reload")) {
/*
* Shutdown needs a special treatment, because after sending the operation, if shutdown suceeds,
@@ -168,4 +180,55 @@ public class BaseServerComponent extends BaseComponent {
return operationResult;
}
+ protected OperationResult installManagementUser(Configuration parameters, Configuration pluginConfig, AS7Mode mode) {
+ String user = parameters.getSimpleValue("user","");
+ String password = parameters.getSimpleValue("password","");
+
+ OperationResult result = new OperationResult();
+ if (user.isEmpty() || password.isEmpty()) {
+ result.setErrorMessage("User and Password must not be empty");
+ return result;
+ }
+
+ String baseDir = pluginConfig.getSimpleValue("baseDir","");
+ if (baseDir.isEmpty()) {
+ result.setErrorMessage("No baseDir found, can not continue");
+ return result;
+ }
+ String standaloneXmlFile = pluginConfig.getSimpleValue("config",mode.getDefaultXmlFile());
+
+ String standaloneXml = baseDir + File.separator + mode.getBaseDir() + File.separator + "configuration" + File.separator + standaloneXmlFile;
+
+ AbstractBaseDiscovery abd = new AbstractBaseDiscovery();
+ abd.readStandaloneOrHostXmlFromFile(standaloneXml);
+
+ String realm = pluginConfig.getSimpleValue("realm","ManagementRealm");
+ String propertiesFilePath = abd.getSecurityPropertyFileFromHostXml(baseDir,mode, realm);
+
+
+ Properties p = new Properties();
+ try {
+ UsernamePasswordHashUtil util = new UsernamePasswordHashUtil();
+ String value = util.generateHashedHexURP(user, realm, password.toCharArray());
+
+
+ FileInputStream fis = new FileInputStream(propertiesFilePath);
+ p.load(fis);
+ fis.close();
+ p.setProperty(user,value);
+ FileOutputStream fos = new FileOutputStream(propertiesFilePath);
+ p.store(fos,null);
+ fos.flush();
+ fos.close();
+ } catch (IOException e) {
+ log.error(e.getMessage());
+ result.setErrorMessage(e.getMessage());
+ } catch (NoSuchAlgorithmException nsae) {
+ log.error(nsae.getMessage());
+ result.setErrorMessage(nsae.getMessage());
+ }
+ result.setSimpleResult("User/Password set or updated");
+
+ return result;
+ }
}
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 c844d78..cbed07e 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
@@ -120,6 +120,15 @@ public class ConfigurationLoadDelegate implements ConfigurationFacet {
operation = new ReadChildrenResources(address,type);
operation.addAdditionalProperty("recursive", "true");
}
+ else if (groupName.startsWith("child:")) {
+ String subPath = groupName.substring("child:".length());
+ if (!subPath.contains("="))
+ throw new IllegalArgumentException("subPath of 'child:' expression has no =");
+
+ Address address1 = new Address(address);
+ address1.addSegment(subPath);
+ operation = new ReadResource(address1);
+ }
else {
throw new IllegalArgumentException("Unknown operation in group name [" + groupName + "]");
}
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 e966ba3..4f07bfc 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
@@ -50,7 +50,7 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
final Log log = LogFactory.getLog(this.getClass());
- private Address address;
+ private Address _address;
private ASConnection connection;
private ConfigurationDefinition configurationDefinition;
private String namePropLocator;
@@ -65,7 +65,7 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
public ConfigurationWriteDelegate(ConfigurationDefinition configDef, ASConnection connection, Address address) {
this.configurationDefinition = configDef;
this.connection = connection;
- this.address = address;
+ this._address = address;
}
/**
@@ -89,7 +89,7 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
Configuration conf = report.getConfiguration();
- CompositeOperation cop = updateGenerateOperationFromProperties(conf);
+ CompositeOperation cop = updateGenerateOperationFromProperties(conf, _address);
Result result = connection.execute(cop);
if (!result.isSuccess()) {
@@ -103,13 +103,13 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
}
- protected CompositeOperation updateGenerateOperationFromProperties(Configuration conf) {
+ protected CompositeOperation updateGenerateOperationFromProperties(Configuration conf, Address address) {
CompositeOperation cop = new CompositeOperation();
for (PropertyDefinition propDef : configurationDefinition.getNonGroupedProperties()) {
- updateProperty(conf, cop, propDef);
+ updateProperty(conf, cop, propDef, address);
}
for (PropertyGroupDefinition pgd: configurationDefinition.getGroupDefinitions()) {
String groupName = pgd.getName();
@@ -126,8 +126,21 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
}
List<PropertyDefinition> definitions = configurationDefinition.getPropertiesInGroup(groupName);
for (PropertyDefinition def : definitions) {
- updateProperty(conf,cop,def);
+ updateProperty(conf,cop,def, address);
}
+ } if (groupName.startsWith("child:")) {
+ String subPath = groupName.substring("child:".length());
+ if (!subPath.contains("="))
+ throw new IllegalArgumentException("subPath of 'child:' expression has no =");
+
+ Address address1 = new Address(address);
+ address1.addSegment(subPath);
+
+ List<PropertyDefinition> definitions = configurationDefinition.getPropertiesInGroup(groupName);
+ for (PropertyDefinition def : definitions) {
+ updateProperty(conf,cop,def, address1);
+ }
+
} // TODO handle attribute: case
}
@@ -135,7 +148,8 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
return cop;
}
- private void updateProperty(Configuration conf, CompositeOperation cop, PropertyDefinition propDef) {
+ private void updateProperty(Configuration conf, CompositeOperation cop, PropertyDefinition propDef,
+ Address baseAddress) {
// Skip over read-only properties, the AS can not use them anyway
if (propDef.isReadOnly())
@@ -147,7 +161,7 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
PropertyList pl = (PropertyList) conf.get("*"); // TODO loop over the list content
for (Property prop2 : pl.getList()) {
- updateHandlePropertyMapSpecial(cop, (PropertyMap) prop2, (PropertyDefinitionMap) propDef);
+ updateHandlePropertyMapSpecial(cop, (PropertyMap) prop2, (PropertyDefinitionMap) propDef, baseAddress);
}
}
else {
@@ -155,25 +169,27 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
Property prop = conf.get(propDef.getName());
if (prop instanceof PropertySimple) {
- updateHandlePropertySimple(cop, (PropertySimple)prop, (PropertyDefinitionSimple) propDef);
+ updateHandlePropertySimple(cop, (PropertySimple)prop, (PropertyDefinitionSimple) propDef, baseAddress);
}
else if (prop instanceof PropertyList) {
- updateHandlePropertyList(cop, (PropertyList) prop, (PropertyDefinitionList) propDef);
+ updateHandlePropertyList(cop, (PropertyList) prop, (PropertyDefinitionList) propDef, baseAddress);
}
else {
- updateHandlePropertyMap(cop,(PropertyMap)prop,(PropertyDefinitionMap)propDef);
+ updateHandlePropertyMap(cop,(PropertyMap)prop,(PropertyDefinitionMap)propDef, baseAddress);
}
}
}
- private void updateHandlePropertyMap(CompositeOperation cop, PropertyMap prop, PropertyDefinitionMap propDef) {
- Map<String,Object> results = updateHandleMap(prop,propDef);
+ private void updateHandlePropertyMap(CompositeOperation cop, PropertyMap prop, PropertyDefinitionMap propDef,
+ Address address) {
+ Map<String,Object> results = updateHandleMap(prop,propDef, address);
Operation writeAttribute = new WriteAttribute(address,prop.getName(),results);
cop.addStep(writeAttribute);
}
- private void updateHandlePropertyMapSpecial(CompositeOperation cop, PropertyMap prop, PropertyDefinitionMap propDef) {
- Map<String,Object> results = updateHandleMap(prop,propDef);
+ private void updateHandlePropertyMapSpecial(CompositeOperation cop, PropertyMap prop, PropertyDefinitionMap propDef,
+ Address address) {
+ Map<String,Object> results = updateHandleMap(prop,propDef, address);
if (prop.get(namePropLocator)==null) {
throw new IllegalArgumentException("There is no element in the map with the name " + namePropLocator);
}
@@ -186,7 +202,8 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
}
}
- private void updateHandlePropertyList(CompositeOperation cop, PropertyList prop, PropertyDefinitionList propDef) {
+ private void updateHandlePropertyList(CompositeOperation cop, PropertyList prop, PropertyDefinitionList propDef,
+ Address address) {
PropertyDefinition memberDef = propDef.getMemberDefinition();
// We need to collect the list members, create an array and attach this to the cop
@@ -201,7 +218,8 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
}
if (memberDef instanceof PropertyDefinitionMap) {
- Map<String,Object> mapResult = updateHandleMap((PropertyMap) inner,(PropertyDefinitionMap)memberDef);
+ Map<String,Object> mapResult = updateHandleMap((PropertyMap) inner,(PropertyDefinitionMap)memberDef,
+ address);
values.add(mapResult);
}
}
@@ -210,7 +228,8 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
}
- private void updateHandlePropertySimple(CompositeOperation cop, PropertySimple propertySimple, PropertyDefinitionSimple propDef) {
+ private void updateHandlePropertySimple(CompositeOperation cop, PropertySimple propertySimple,
+ PropertyDefinitionSimple propDef, Address address) {
// If the property value is null and the property is optional, skip too
if (propertySimple.getStringValue()==null && !propDef.isRequired())
@@ -221,7 +240,7 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
cop.addStep(writeAttribute);
}
- private Map<String, Object> updateHandleMap(PropertyMap map, PropertyDefinitionMap mapDef) {
+ private Map<String, Object> updateHandleMap(PropertyMap map, PropertyDefinitionMap mapDef, Address address) {
Map<String,PropertyDefinition> memberDefinitions = mapDef.getPropertyDefinitions();
Map<String,Object> results = new HashMap<String,Object>();
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/Domain2Descriptor.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/Domain2Descriptor.java
index df5362c..bc7d601 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/Domain2Descriptor.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/Domain2Descriptor.java
@@ -54,28 +54,47 @@ public class Domain2Descriptor {
private void run(String[] args) {
D2DMode mode = null;
+ String user = null;
+ String pass = null;
+
int pos = 0;
- if (args[0].startsWith("-")) {
- if (args[0].equals("-m"))
- mode = D2DMode.METRICS;
- else if (args[0].equals("-p"))
- mode = D2DMode.PROPERTIES;
- else if (args[0].equals("-o"))
- mode = D2DMode.OPERATION;
- else {
- usage();
- return;
+ boolean optionFound=false;
+
+ String arg;
+ do {
+ arg = args[pos];
+ if (arg.startsWith("-")) {
+ if (args[0].equals("-m"))
+ mode = D2DMode.METRICS;
+ else if (arg.equals("-p"))
+ mode = D2DMode.PROPERTIES;
+ else if (arg.equals("-o"))
+ mode = D2DMode.OPERATION;
+ else if (arg.startsWith("-U")) {
+ String tmp = arg.substring(2);
+ if (!tmp.contains(":"))
+ usage();
+ user = tmp.substring(0,tmp.indexOf(":"));
+ pass = tmp.substring(tmp.indexOf(":")+1);
+ }
+ else {
+ usage();
+ return;
+ }
+ pos++;
+ optionFound=true;
}
- pos++;
- }
+ else
+ optionFound=false;
+ }while(optionFound);
- String path = args[pos];
+ String path = arg;
path = path.replaceAll("/",","); // Allow path from jboss-admin.sh's pwd command
String childType = null;
if (args.length>pos+1)
childType = args[pos+1];
- ASConnection conn = new ASConnection("localhost",9990);
+ ASConnection conn = new ASConnection("localhost",9990, user, pass);
Address address = new Address(path);
Operation op = new Operation("read-resource-description",address);
@@ -87,6 +106,10 @@ public class Domain2Descriptor {
op.addAdditionalProperty("include-runtime",true);
ComplexResult res = conn.executeComplex(op);
+ if (res==null) {
+ System.err.println("Got no result");
+ return;
+ }
if (!res.isSuccess()) {
System.err.println("Failure: " + res.getFailureDescription());
return;
@@ -313,6 +336,8 @@ public class Domain2Descriptor {
typeString = "long"; break;
case BIG_DECIMAL:
typeString = "long"; break; // TODO better float or double?
+ case DOUBLE:
+ typeString = "long"; break; // TODO float or double?
case LIST:
typeString = "-list-";
break; // Handled below
@@ -412,6 +437,7 @@ public class Domain2Descriptor {
System.out.println(" -p create properties (default)");
System.out.println(" -m create metrics");
System.out.println(" -o create operations");
+ System.out.println(" -U<user>:<pass> - supply credentials to talk to AS7" );
}
public enum Type {
@@ -421,7 +447,8 @@ public class Domain2Descriptor {
LONG,
BIG_DECIMAL,
OBJECT,
- LIST
+ LIST,
+ DOUBLE
;
}
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 6168dad..f4fa473 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
@@ -61,6 +61,10 @@ public class HostControllerComponent extends BaseServerComponent implements Oper
return postProcessResult(name,res);
}
+ else if (name.equals("installRhqUser")) {
+ return installManagementUser(parameters, pluginConfiguration, AS7Mode.HOST);
+ }
+
// Defer other stuff to the base component for now
return super.invokeOperation(name, parameters);
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 8df1c47..3e90588 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
@@ -48,6 +48,7 @@ import org.rhq.modules.plugins.jbossas7.json.ReadResource;
*
* @author Heiko W. Rupp
*/
+@SuppressWarnings("unused")
public class ManagedASDiscovery extends AbstractBaseDiscovery
{
@@ -138,7 +139,7 @@ public class ManagedASDiscovery extends AbstractBaseDiscovery
}
private ServerInfo getBindingsFromDC(HostPort domainController, String serverGroup) {
- ASConnection dcConnection = new ASConnection(domainController.host, domainController.port);
+ ASConnection dcConnection = new ASConnection(domainController.host, domainController.port, "-TODO-", "-TODO-"); // TODO where do we get these from?
List<PROPERTY_VALUE> address = new ArrayList<PROPERTY_VALUE>();
Address theAddress = new Address("server-group", serverGroup);
Operation op = new ReadResource(theAddress);
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ServerGroupComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ServerGroupComponent.java
index c703635..c5a17a8 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ServerGroupComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ServerGroupComponent.java
@@ -74,7 +74,7 @@ public class ServerGroupComponent extends ManagedASComponent implements ContentF
for (ResourcePackageDetails details : packages) {
- ASUploadConnection uploadConnection = new ASUploadConnection(host,port);
+ ASUploadConnection uploadConnection = new ASUploadConnection(host,port, super.managementUser, super.managementPassword);
String fileName = details.getFileName();
OutputStream out = uploadConnection.getOutputStream(fileName);
contentServices.downloadPackageBits(cctx, details.getKey(), out, false);
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 11a0e4d..f3c3184 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
@@ -40,6 +40,8 @@ public class StandaloneASComponent extends BaseServerComponent implements Operat
} else if (name.equals("restart")) {
return restartServer(parameters, AS7Mode.STANDALONE);
+ } else if (name.equals("installRhqUser")) {
+ return installManagementUser(parameters, pluginConfiguration, AS7Mode.STANDALONE);
}
// reload, shutdown go to the remote server
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/json/Address.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/json/Address.java
index c0a9196..51fc3a2 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/json/Address.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/json/Address.java
@@ -83,11 +83,7 @@ public class Address {
if (tmp.contains("=")) {
// strip / from the start of the key if it happens to be there
- if (tmp.startsWith("/"))
- tmp = tmp.substring(1);
-
- String[] pair = tmp.split("=");
- PROPERTY_VALUE valuePair = new PROPERTY_VALUE(pair[0], pair[1]);
+ PROPERTY_VALUE valuePair = pathFromSegment(tmp);
this.path.add(valuePair);
}
}
@@ -95,6 +91,19 @@ public class Address {
}
/**
+ * Generates a path from a segment in the form of key=value.
+ * @param segment A segment in the form key=value
+ * @return A path
+ */
+ private PROPERTY_VALUE pathFromSegment(String segment) {
+ if (segment.startsWith("/"))
+ segment = segment.substring(1);
+
+ String[] pair = segment.split("=");
+ return new PROPERTY_VALUE(pair[0], pair[1]);
+ }
+
+ /**
* Add a key value pair to the path
* @param key Key part of this path element
* @param value Value part of this path element
@@ -103,6 +112,14 @@ public class Address {
path.add(new PROPERTY_VALUE(key,value));
}
+ public void addSegment(String segment) {
+ if (!segment.contains("="))
+ throw new IllegalArgumentException("Segment [" + segment + "] contains no '='");
+
+ PROPERTY_VALUE pv = pathFromSegment(segment);
+ path.add(pv);
+ }
+
@Override
public String toString() {
StringBuilder builder = new StringBuilder( "Address{" +
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 8048100..ee6b902 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
@@ -50,31 +50,11 @@
xmlns:c="urn:xmlns:rhq-configuration"
>
- <depends plugin="JMX" useClasses="true"/>
-
<!-- TODO I think we should introduce an abstract AS7 plugin that contains some base functionality and then
~~ additional 'Personalities' for the kinds of servers (PM, SM, Standalone AS, Managed AS)
-->
- <!-- TODO do we want to show the process controller at all? We have no benefit from it
- <server name="ProcessController"
- discovery="BaseProcessDiscovery"
- class="BaseComponent"
- description="Reaper process for other AS7 services"
- >
-
- <plugin-configuration>
- <c:simple-property name="hostname" default="localhost" required="true"/>
- <c:simple-property name="port" default="9990" type="integer" required="true"/>
-
- </plugin-configuration>
-
- <process-scan name="ProcessController" query="process|basename|match=^java.*,arg|org.jboss.as.process-controller|match=.*"/>
-
-
- </server>
- -->
<server name="JBossAS7 Host Controller"
discovery="BaseProcessDiscovery"
class="HostControllerComponent"
@@ -84,8 +64,8 @@
<plugin-configuration>
<c:simple-property name="hostname" default="localhost" required="true" description="Host name of the domain API"/>
<c:simple-property name="port" default="9990" type="integer" required="true" description="Port of the domain API"/>
- <c:simple-property name="user" type="string" description="Management user for a secured Host controller" required="false"/>
- <c:simple-property name="password" type="password" description="Password for the management user" required="false"/>
+ <c:simple-property name="user" type="string" default="rhqadmin" description="Management user for a secured Host controller" required="false"/>
+ <c:simple-property name="password" type="password" default="rhqadmin" description="Password for the management user" required="false"/>
<c:simple-property name="domainConfig" type="string" default="domain.xml" description="Running configuration (domain part)" displayName="Domain Configuration"/>
<c:simple-property name="hostConfig" type="string" default="host.xml" description="Running configuration (host part)" displayName="Host Configuration"/>
<c:simple-property name="baseDir" type="file" description="Base directory of the server installation" displayName="Base directory" readOnly="true" required="false"/>
@@ -179,6 +159,15 @@
<c:simple-property name="operationResult" description="Outcome of the stop operation"/>
</results>
</operation>
+ <operation name="installRhqUser" description="Installs a user in the server for management" displayName="Install RHQ user">
+ <parameters>
+ <c:simple-property name="user" displayName="Username" description="Name of the management user" default="rhqadmin"/>
+ <c:simple-property name="password" displayName="Password" description="Password of this management user" default="rhqadmin" type="password"/>
+ </parameters>
+ <results>
+ <c:simple-property name="operationResult"/>
+ </results>
+ </operation>
<metric property="_internal:mgmtRequests" category="performance" dataType="measurement" defaultInterval="120000"
@@ -192,6 +181,11 @@
displayType="summary" measurementType="dynamic" description="Max time for a request since last metric get" units="milliseconds"
displayName="Maximum request time"/>
+ <metric property="server-state" dataType="trait" displayName="Server state" description="Detailed server state"
+ displayType="summary"/>
+ <metric property="release-codename" dataType="trait" displayName="Code name of the release" displayType="summary"/>
+ <metric property="release-version" dataType="trait" displayName="Version of the server" displayType="summary"/>
+
<event name="logEntry" description="an entry in a log file"/>
<resource-configuration>
@@ -206,11 +200,10 @@
</c:group>
-->
- <c:group name="children:extension" displayName="Installed extensions">
-
+ <c:group name="children:extension" displayName="Installed extensions" hiddenByDefault="true">
<c:list-property name="*" displayName="Installed extensions" readOnly="true" required="false">
<c:map-property name="*" displayName="Name" readOnly="true">
- <c:simple-property name="module" displayName="Module name"/>
+ <c:simple-property name="module" displayName="Module name" readOnly="true"/>
</c:map-property>
</c:list-property>
</c:group>
@@ -332,8 +325,8 @@
<plugin-configuration>
<c:simple-property name="hostname" default="localhost" required="true"/>
<c:simple-property name="port" default="9990" type="integer" required="true"/>
- <c:simple-property name="user" type="string" description="Management user for a secured AS" required="false"/>
- <c:simple-property name="password" type="password" description="Password for the management user" required="false"/>
+ <c:simple-property name="user" default="rhqadmin" type="string" description="Management user for a secured AS" required="false"/>
+ <c:simple-property name="password" default="rhqadmin" type="password" description="Password for the management user" required="false"/>
<c:simple-property name="config" type="string" default="standalone.xml" description="Running configuration" displayName="Configuration"/>
<c:simple-property name="baseDir" type="file" description="Base directory of the server installation" displayName="Base directory" readOnly="true" required="false"/>
<c:simple-property name="startScript" type="file" default="bin/standalone.sh" description="Script used to start the server. If the path is not absolute, it is relative to the base directory"/>
@@ -404,6 +397,15 @@
<c:simple-property name="operationResult"/>
</results>
</operation>
+ <operation name="installRhqUser" description="Installs a user in the server for management" displayName="Install RHQ user">
+ <parameters>
+ <c:simple-property name="user" displayName="Username" description="Name of the management user" default="rhqadmin"/>
+ <c:simple-property name="password" displayName="Password" description="Password of this management user" default="rhqadmin" type="password"/>
+ </parameters>
+ <results>
+ <c:simple-property name="operationResult"/>
+ </results>
+ </operation>
<metric property="_internal:mgmtRequests" category="performance" dataType="measurement" defaultInterval="120000"
@@ -416,6 +418,11 @@
displayType="summary" measurementType="dynamic" description="Max time for a request since last metric get" units="milliseconds"
displayName="Maximum request time"/>
+ <metric property="server-state" dataType="trait" displayName="Server state" description="Detailed server state"
+ displayType="summary"/>
+ <metric property="release-codename" dataType="trait" displayName="Code name of the release" displayType="summary"/>
+ <metric property="release-version" dataType="trait" displayName="Version of the server" displayType="summary"/>
+
<event name="logEntry" description="an entry in a log file"/>
<resource-configuration>
@@ -431,11 +438,10 @@
</c:group>
-->
- <c:group name="children:extension" displayName="Installed extensions">
-
+ <c:group name="children:extension" displayName="Installed extensions" hiddenByDefault="true">
<c:list-property name="*" displayName="Installed extensions" readOnly="true" required="false">
<c:map-property name="*" displayName="Name" readOnly="true">
- <c:simple-property name="module" displayName="Module name"/>
+ <c:simple-property name="module" displayName="Module name" readOnly="true"/>
</c:map-property>
</c:list-property>
</c:group>
@@ -515,31 +521,98 @@
</results>
</operation>
- <metric property="status" dataType="trait" displayName="Server state" description="Detailed server state"
+ <metric property="server-state" dataType="trait" displayName="Server state" description="Detailed server state"
displayType="summary"/>
+ <metric property="release-codename" dataType="trait" displayName="Code name of the release" displayType="summary"/>
+ <metric property="release-version" dataType="trait" displayName="Version of the server" displayType="summary"/>
<event name="logEntry" description="an entry in a log file"/>
</server>
- <server name="JBoss AS JVM"
- description="JVM of the JBossAS"
- sourcePlugin="JMX"
- sourceType="JMX Server"
- discovery="org.rhq.plugins.jmx.EmbeddedJMXServerDiscoveryComponent"
- class="org.rhq.plugins.jmx.JMXServerComponent"
- singleton="true">
+ <server name="JVM"
+ discovery="SubsystemDiscovery"
+ class="BaseComponent"
+ description="Information about the underlying JVM"
+ singleton="true">
<runs-inside>
<parent-resource-type name="JBossAS7 Managed Server" plugin="jboss-as-7"/>
<parent-resource-type name="JBossAS7 Standalone Server" plugin="jboss-as-7"/>
</runs-inside>
- </server>
- <server name="Messaging"
+ <plugin-configuration>
+ <c:simple-property name="path" readOnly="true" default="core-service=platform-mbean"/>
+ </plugin-configuration>
+
+ <service name="Operating System"
+ discovery="SubsystemDiscovery"
+ class="BaseComponent"
+ singleton="true"
+ >
+
+ <plugin-configuration>
+ <c:simple-property name="path" readOnly="true" default="type=operating-system"/>
+ </plugin-configuration>
+
+ <metric property="available-processors"
+ description="The number of processors available to the Java virtual machine."/>
+ <metric property="system-load-average"
+ description="The system load average for the last minute. The load average may not be available on some platforms; if the load average is not available, a negative value is returned."/>
+ </service>
+
+ <service name="Runtime"
+ discovery="SubsystemDiscovery"
+ class="BaseComponent"
+ singleton="true"
+ >
+
+ <plugin-configuration>
+ <c:simple-property name="path" readOnly="true" default="type=runtime"/>
+ </plugin-configuration>
+
+ <metric property="uptime" description="The uptime of the Java virtual machine in milliseconds."/>
+ </service>
+
+ <service name="Threading"
+ discovery="SubsystemDiscovery"
+ class="BaseComponent"
+ >
+
+ <plugin-configuration>
+ <c:simple-property name="path" readOnly="true" default="type=threading"/>
+ </plugin-configuration>
+
+ <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."/>
+ <metric property="daemon-thread-count" description="The current number of live daemon threads."/>
+ <metric property="current-thread-cpu-time" description="The total CPU time for the current thread in nanoseconds, or -1 if 'thread-cpu-time-enabled' is 'false'. A Java virtual machine implementation may not support CPU time measurement. If 'thread-cpu-time-supported', is 'false' undefined."/>
+ <metric property="current-thread-user-time" description="The CPU time that the current thread has executed in user mode in nanoseconds, or -1 if 'thread-cpu-time-enabled' is 'false'. A Java virtual machine implementation may not support CPU time measurement. If 'thread-cpu-time-supported', is 'false' the result will be undefined "/>
+
+ <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 und
+ ." >
+ <c:simple-property name="all-thread-ids" />
+ </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."/>
+ <c:simple-property name="object-monitor-usage-supported" required="false" type="boolean" readOnly="true" description="Whether the Java virtual machine supports monitoring of object monitor usage."/>
+ <c:simple-property name="synchronizer-usage-supported" required="false" type="boolean" readOnly="true" description="Whether the Java virtual machine supports monitoring of ownable synchronizer usage."/>
+ </resource-configuration>
+ </service>
+
+
+
+ </server>
+
+ <server name="Messaging-Provider"
discovery="SubsystemDiscovery"
class="BaseComponent"
- description="The HornetQ based messaging subsystem"
+ description="The messaging subsystems"
singleton="true"
>
<runs-inside>
@@ -551,82 +624,94 @@
<c:simple-property name="path" readOnly="true" default="subsystem=messaging"/>
</plugin-configuration>
- <operation name="destination:add" displayName="Add destination" description="Add a Queue or Topic">
- <parameters>
- <c:simple-property name="name" description="Name of the Destination" required="true"/>
- <c:list-property name="entries" description="The JNDI names the destination should be bound to." required="true">
- <c:simple-property name="entry" description="A single JNDI name. Note, this is relative to java:jboss/jms/"/>
- </c:list-property>
- <c:simple-property name="type" description="Type of Destination to create" default="Queue">
- <c:property-options>
- <c:option value="jms-queue" name="Queue"/>
- <c:option value="jms-topic" name="Topic"/>
- </c:property-options>
- </c:simple-property>
- <c:simple-property name="durable" description="Defines whether the queue is durable (for Queues only)." type="boolean" default="false"/>
- </parameters>
- <results>
- <c:simple-property name="operationResult"/>
- </results>
- </operation>
- <operation name="destination:remove" displayName="Remove Destination" description="Remove a destination">
- <parameters>
- <c:simple-property name="name" description="Name of the Destination" required="true"/>
- </parameters>
- <results>
- <c:simple-property name="operationResult"/>
- </results>
- </operation>
-
- <resource-configuration>
- <c:simple-property name="journal-min-files" />
- <c:simple-property name="journal-type" />
- </resource-configuration>
+ <server name="HornetQ"
+ discovery="SubsystemDiscovery"
+ class="BaseComponent"
+ description="The HornetQ based messaging subsystem"
+ >
- <service name="JMS Queue"
- discovery="SubsystemDiscovery"
- class="JmsComponent"
- createDeletePolicy="delete-only"
- >
<plugin-configuration>
- <c:simple-property name="path" readOnly="true" default="jms-queue"/>
+ <c:simple-property name="path" readOnly="true" default="hornetq-server"/>
</plugin-configuration>
+
+ <operation name="destination:add" displayName="Add destination" description="Add a Queue or Topic">
+ <parameters>
+ <c:simple-property name="name" description="Name of the Destination" required="true"/>
+ <c:list-property name="entries" description="The JNDI names the destination should be bound to." required="true">
+ <c:simple-property name="entry" description="A single JNDI name. Note, this is relative to java:jboss/jms/"/>
+ </c:list-property>
+ <c:simple-property name="type" description="Type of Destination to create" default="Queue">
+ <c:property-options>
+ <c:option value="jms-queue" name="Queue"/>
+ <c:option value="jms-topic" name="Topic"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="durable" description="Defines whether the queue is durable (for Queues only)." type="boolean" default="false"/>
+ </parameters>
+ <results>
+ <c:simple-property name="operationResult"/>
+ </results>
+ </operation>
+ <operation name="destination:remove" displayName="Remove Destination" description="Remove a destination">
+ <parameters>
+ <c:simple-property name="name" description="Name of the Destination" required="true"/>
+ </parameters>
+ <results>
+ <c:simple-property name="operationResult"/>
+ </results>
+ </operation>
+
<resource-configuration>
- <c:simple-property name="durable" required="false" type="boolean" readOnly="true" default="false"
- description="Whether the queue is durable or not."/>
- <c:list-property name="entries" required="false" readOnly="true"
- description="The jndi names the queue will be bound to.">
- <c:simple-property name="entries" type="string"/>
- </c:list-property>
- <c:simple-property name="selector" required="false" type="string" readOnly="true" description="The queue selector."/>
- </resource-configuration>
- </service>
- <service name="JMS Topic"
- discovery="SubsystemDiscovery"
- class="JmsComponent"
- createDeletePolicy="delete-only"
- >
- <plugin-configuration>
- <c:simple-property name="path" readOnly="true" default="jms-topic"/>
- </plugin-configuration>
- <resource-configuration>
- <c:list-property name="entries" required="false" readOnly="true"
- description="The jndi names the queue will be bound to.">
- <c:simple-property name="entries" type="string"/>
- </c:list-property>
+ <c:simple-property name="journal-min-files" />
+ <c:simple-property name="journal-type" />
</resource-configuration>
- </service>
- <service name="Connection-Factory"
- discovery="SubsystemDiscovery"
- class="JmsComponent"
- createDeletePolicy="both"
- >
- <plugin-configuration>
- <c:simple-property name="path" readOnly="true" default="connection-factory"/>
- </plugin-configuration>
- </service>
+ <service name="JMS Queue"
+ discovery="SubsystemDiscovery"
+ class="JmsComponent"
+ createDeletePolicy="delete-only"
+ >
+ <plugin-configuration>
+ <c:simple-property name="path" readOnly="true" default="jms-queue"/>
+ </plugin-configuration>
+
+ <resource-configuration>
+ <c:simple-property name="durable" required="false" type="boolean" readOnly="true" default="false"
+ description="Whether the queue is durable or not."/>
+ <c:list-property name="entries" required="false" readOnly="true"
+ description="The jndi names the queue will be bound to.">
+ <c:simple-property name="entries" type="string"/>
+ </c:list-property>
+ <c:simple-property name="selector" required="false" type="string" readOnly="true" description="The queue selector."/>
+ </resource-configuration>
+ </service>
+ <service name="JMS Topic"
+ discovery="SubsystemDiscovery"
+ class="JmsComponent"
+ createDeletePolicy="delete-only"
+ >
+ <plugin-configuration>
+ <c:simple-property name="path" readOnly="true" default="jms-topic"/>
+ </plugin-configuration>
+ <resource-configuration>
+ <c:list-property name="entries" required="false" readOnly="true"
+ description="The jndi names the queue will be bound to.">
+ <c:simple-property name="entries" type="string"/>
+ </c:list-property>
+ </resource-configuration>
+ </service>
+ <service name="Connection-Factory"
+ discovery="SubsystemDiscovery"
+ class="JmsComponent"
+ createDeletePolicy="both"
+ >
+ <plugin-configuration>
+ <c:simple-property name="path" readOnly="true" default="connection-factory"/>
+ </plugin-configuration>
+ </service>
+
+ </server>
</server>
<server name="JBossWeb"
@@ -649,61 +734,64 @@
description="The web container's default virtual server."/>
<c:simple-property name="native" required="false" type="boolean" readOnly="true" defaultValue="true"
description="Add the native initialization listener to the web container."/>
- <c:map-property name="configuration" description="The common web container configuration." >
- <c:map-property name="static-resources" description="Configuration for static resources" >
- <c:simple-property name="listings" required="false" type="boolean" readOnly="true" defaultValue="false"
+ <c:simple-property name="instance-id" readOnly="true" required="false" type="string" description="The identifier for this server instance."/>
+ <c:group name="child:configuration=static-resources" displayName="Static Resources" >
+ <c:simple-property name="listings" required="false" type="boolean" defaultValue="false"
description="Enable folder listings."/>
- <c:simple-property name="sendfile" required="false" type="integer" readOnly="true" defaultValue="49152"
+ <c:simple-property name="sendfile" required="false" type="integer" defaultValue="49152"
description="Enable sendfile if possible, for files bigger than the specified byte size."/>
- <c:simple-property name="read-only" required="false" type="boolean" readOnly="true" defaultValue="true"
+ <c:simple-property name="file-encoding" required="false" description="Force a file encoding." type="string"/>
+ <c:simple-property name="read-only" required="false" type="boolean" defaultValue="true"
description="Allow write HTTP methods (PUT, DELETE)."/>
- <c:simple-property name="webdav" required="false" type="boolean" readOnly="true" defaultValue="false"
+ <c:simple-property name="webdav" required="false" type="boolean" defaultValue="false"
description="Enable WebDAV functionality."/>
<c:simple-property name="secret" required="false" type="string" readOnly="true" description="Secret for WebDAV locking operations."/>
- <c:simple-property name="max-depth" required="false" type="integer" readOnly="true" defaultValue="3"
+ <c:simple-property name="max-depth" required="false" type="integer" defaultValue="3"
description="Maximum recursion for PROPFIND."/>
- <c:simple-property name="disabled" required="false" type="boolean" readOnly="true" defaultValue="false"
+ <c:simple-property name="disabled" required="false" type="boolean" defaultValue="false"
+ description="Enable the default Servlet mapping."/>
+ </c:group>
+ <c:group name="child:configuration=jsp-configuration" displayName="JSP Configuration">
+ <c:simple-property name="development" required="false" type="boolean" default="false"
+ description="Enable the development mode, which gives more information when an error occurs. And also enables automatic JSP recompiles."/>
+ <c:simple-property name="disabled" required="false" type="boolean" defaultValue="false"
description="Enable the JSP container."/>
- </c:map-property>
- <c:map-property name="jsp-configuration" description="JSP container configuration">
- <c:simple-property name="development" required="false" type="boolean" readOnly="true" defaultValue="false"
- description="Enable the development mode, which gives more information when an error occurs."/>
- <c:simple-property name="file-encoding" required="false" type="string" readOnly="true" description="Force a file encoding."/>
- <c:simple-property name="keep-generated" required="false" type="boolean" readOnly="true" defaultValue="true"
+ <c:simple-property name="keep-generated" required="false" type="boolean" defaultValue="true"
description="Keep the generated Servlets."/>
<c:simple-property name="trim-spaces" required="false" type="boolean" readOnly="true" defaultValue="true"
- description="Trim some spaces from the generated Servlet."/>
- <c:simple-property name="tag-pooling" required="false" type="boolean" readOnly="true" defaultValue="true"
+ description="Trim some spaces from the generated Servlet."/> <!-- TODO make r/w when https://issues.jboss.org/browse/AS7-3097 is solved -->
+ <c:simple-property name="tag-pooling" required="false" type="boolean" defaultValue="true"
description="Enable tag pooling."/>
- <c:simple-property name="mapped-file" required="false" type="boolean" readOnly="true" defaultValue="true"
+ <c:simple-property name="mapped-file" required="false" type="boolean" defaultValue="true"
description="Map to the JSP source."/>
- <c:simple-property name="check-interval" required="false" type="integer" readOnly="true" defaultValue="0"
- description="Check interval for JSP updates using a background thread."/>
- <c:simple-property name="modification-test-interval" required="false" type="integer" readOnly="true" defaultValue="4"
+ <c:simple-property name="check-interval" required="false" type="integer" defaultValue="60"
+ description="Check interval for JSP updates using a background thread."/> <!-- TODO revisit default when https://issues.jboss.org/browse/AS7-3098 is fixed -->
+ <c:simple-property name="modification-test-interval" required="false" type="integer" defaultValue="4"
description="Minimum amount of time between two tests for updates, in seconds."/>
- <c:simple-property name="recompile-on-fail" required="false" type="boolean" readOnly="true" defaultValue="false"
+ <c:simple-property name="recompile-on-fail" required="false" type="boolean" defaultValue="false"
description="Retry failed JSP compilations on each request."/>
- <c:simple-property name="smap" required="false" type="boolean" readOnly="true" defaultValue="false"
+ <c:simple-property name="smap" required="false" type="boolean" defaultValue="false"
description="Enable SMAP."/>
- <c:simple-property name="dump-smap" required="false" type="boolean" readOnly="true" defaultValue="false"
+ <c:simple-property name="dump-smap" required="false" type="boolean" defaultValue="false"
description="Write SMAP data to a file."/>
- <c:simple-property name="generate-strings-as-char-arrays" required="false" type="boolean" readOnly="true"
+ <c:simple-property name="generate-strings-as-char-arrays" required="false" type="boolean"
defaultValue="false"
description="Generate String constants as char arrays."/>
- <c:simple-property name="error-on-use-bean-invalid-class-attribute" required="false" type="boolean" readOnly="true" defaultValue="false"
+ <c:simple-property name="error-on-use-bean-invalid-class-attribute" required="false" type="boolean" defaultValue="false"
description="Enable errors when using a bad class in useBean."/>
- <c:simple-property name="scratch-dir" required="false" type="string" readOnly="true" description="Specify a different work directory."/>
- <c:simple-property name="source-vm" required="false" type="string" readOnly="true" defaultValue="1.5"
+ <c:simple-property name="scratch-dir" required="false" type="string" description="Specify a different work directory."/>
+ <c:simple-property name="source-vm" required="false" type="string" defaultValue="1.5"
description="Source VM level for compilation."/>
- <c:simple-property name="target-vm" required="false" type="string" readOnly="true" defaultValue="1.5"
+ <c:simple-property name="target-vm" required="false" type="string" defaultValue="1.5"
description="Target VM level for compilation."/>
- <c:simple-property name="java-encoding" required="false" type="string" readOnly="true" defaultValue="UTF-8"
+ <c:simple-property name="java-encoding" required="false" type="string" defaultValue="UTF-8"
description="Specify the encoding used for Java sources."/>
- <c:simple-property name="x-powered-by" required="false" type="boolean" readOnly="true" defaultValue="true"
+ <c:simple-property name="x-powered-by" required="false" type="boolean" defaultValue="true"
description="Enable advertising the JSP engine in x-powered-by."/>
- <c:simple-property name="display-source-fragment" required="false" type="boolean" readOnly="true" defaultValue="true"
+ <c:simple-property name="display-source-fragment" required="false" type="boolean" defaultValue="true"
description="When a runtime error occurs, attempts to display corresponding JSP source fragment."/>
- </c:map-property>
+ </c:group>
+ <!-- <c:group name="child:configuration=container" displayName="Container">
<c:list-property name="mime-mapping" description="A mime-mapping definition." >
<c:map-property name="mime-mapping" >
<c:simple-property name="name" description="A MIME mapping name"/>
@@ -713,8 +801,8 @@
<c:list-property name="welcome-file" description="A welcome file declaration." >
<c:simple-property name="welcome-file" />
</c:list-property>
- </c:map-property>
- </resource-configuration>
+ </c:group>
+--> </resource-configuration>
<service name="Connector"
discovery="SubsystemDiscovery"
@@ -726,41 +814,41 @@
</plugin-configuration>
- <metric property="bytesSent" measurementType="trendsup"/>
- <metric property="bytesReceived" measurementType="trendsup"/>
- <metric property="processingTime" measurementType="trendsup" units="milliseconds"/>
- <metric property="errorCount" measurementType="trendsup" displayType="summary"/>
- <metric property="maxTime" units="milliseconds"/>
- <metric property="requestCount" measurementType="trendsup" displayType="summary"/>
+ <metric property="bytesSent" measurementType="trendsup" description="Number of byte sent by the connector."/>
+ <metric property="bytesReceived" measurementType="trendsup" description="Number of byte received by the connector (POST data)."/>
+ <metric property="processingTime" measurementType="trendsup" units="milliseconds" description="Processing time used by the connector. Im milli-seconds."/>
+ <metric property="errorCount" measurementType="trendsup" displayType="summary" description="Number of error that occurs when processing requests by the connector."/>
+ <metric property="maxTime" units="milliseconds" description="Max time spent to process a requests."/>
+ <metric property="requestCount" measurementType="trendsup" displayType="summary" description="Number of the request processed by the connector."/>
<resource-configuration>
- <c:simple-property name="protocol" required="true" type="string" readOnly="true" description="The web connector protocol."/>
- <c:simple-property name="socket-binding" required="true" type="string" readOnly="true"
+ <c:simple-property name="protocol" required="true" type="string" description="The web connector protocol."/>
+ <c:simple-property name="socket-binding" required="true" type="string"
description="The web connector socket-binding reference, this connector should be bound to.">
<c:option-source target="configuration" expression="socket-binding=name:type=SocketBindingGroup"/> <!-- TODO different for Domain vs standalone -->
</c:simple-property>
- <c:simple-property name="scheme" type="string" readOnly="true" default="http" description="The web connector scheme." required="true"/>
- <c:simple-property name="executor" type="string" readOnly="true" required="false"
+ <c:simple-property name="scheme" type="string" default="http" description="The web connector scheme." required="true"/>
+ <c:simple-property name="executor" type="string" required="false"
description="The name of the executor that should be used for the processing threads of this connector. Defaults to using an internal pool."/>
- <c:simple-property name="enabled" type="boolean" readOnly="true" defaultValue="true"
+ <c:simple-property name="enabled" type="boolean" default="true"
description="Defines whether the connector should be started on startup."/>
- <c:simple-property name="enable-lookups" type="boolean" readOnly="true" defaultValue="false"
+ <c:simple-property name="enable-lookups" type="boolean" defaultValue="false"
description="Enable DNS lookups for Servlet API."/>
- <c:simple-property name="proxy-name" type="string" readOnly="true" required="false"
+ <c:simple-property name="proxy-name" type="string" required="false"
description="The host name that will be used when sending a redirect. The default value is null."/>
- <c:simple-property name="proxy-port" type="integer" readOnly="true" required="false"
+ <c:simple-property name="proxy-port" type="integer" required="false"
description="The port that will be used when sending a redirect."/>
- <c:simple-property name="max-post-size" type="integer" readOnly="true" defaultValue="2097152"
+ <c:simple-property name="max-post-size" type="integer" defaultValue="2097152"
description="Maximum size in bytes of a POST request that can be parsed by the container."/>
- <c:simple-property name="max-save-post-size" type="integer" readOnly="true" defaultValue="4096"
+ <c:simple-property name="max-save-post-size" type="integer" defaultValue="4096"
description="Maximum size in bytes of a POST request that will be saved during certain authentication schemes."/>
<c:simple-property name="secure" type="boolean" readOnly="true" defaultValue="false"
description="Indicates if content sent or recieved by the connector is secured from the user perspective."/>
<c:simple-property name="redirect-port" type="integer" readOnly="true" defaultValue="8443"
description="The port for redirection to a secure connector."/>
- <c:simple-property name="max-connections" type="integer" readOnly="true" required="false"
+ <c:simple-property name="max-connections" type="integer" required="false"
description="Amount of concurrent connections that can be processed by the connector with optimum performance. The default value depends on the connector used."/>
- <c:list-property name="virtual-server" description="The list of virtual servers that can be accessed through this connector. The default is to allow all virtual servers." readOnly="true" required="false">
+ <c:list-property name="virtual-server" description="The list of virtual servers that can be accessed through this connector. The default is to allow all virtual servers." required="false">
<c:simple-property name="virtual-server" />
</c:list-property>
<c:map-property name="ssl" description="The SSL configuration of the connector." readOnly="true" required="false">
@@ -795,10 +883,10 @@
</plugin-configuration>
<resource-configuration>
- <c:list-property name="alias" >
+ <c:list-property name="alias" description="The virtual server aliases" displayName="Virtual server aliases" >
<c:simple-property name="alias" />
</c:list-property>
- <c:simple-property name="default-web-module" type="string" readOnly="true" defaultValue="ROOT.war"
+ <c:simple-property name="default-web-module" type="string" defaultValue="ROOT.war"
description="The web module deployment name that will be mapped as the root webapp."/>
<c:map-property name="access-log" description="The access log configuration for this virtual server." >
<c:simple-property name="pattern" type="string" readOnly="true" defaultValue="common" required="false" description="The access log pattern."/>
@@ -825,7 +913,7 @@
</c:list-property>
</c:map-property>
</c:list-property>
- <c:simple-property name="enable-welcome-root" type="boolean" />
+ <c:simple-property name="enable-welcome-root" type="boolean" description="Whether or not the bundled welcome directory is used as the root web context."/>
</resource-configuration>
</service>
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/AbstractConfigurationHandlingTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/AbstractConfigurationHandlingTest.java
index 16c94f9..0266071 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/AbstractConfigurationHandlingTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/AbstractConfigurationHandlingTest.java
@@ -28,7 +28,6 @@ import javax.xml.bind.util.ValidationEventCollector;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.JsonNode;
-import org.testng.annotations.BeforeSuite;
import org.rhq.core.clientapi.agent.metadata.ConfigurationMetadataParser;
import org.rhq.core.clientapi.agent.metadata.InvalidPluginDescriptorException;
@@ -97,7 +96,7 @@ public class AbstractConfigurationHandlingTest {
JsonNode content;
public FakeConnection() {
- super("localhost", 1234);
+ super("localhost", 1234, "fake", "fake");
}
public void setContent(JsonNode content) {
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 d021ab2..a512133 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
@@ -62,7 +62,7 @@ public class ConfigurationUpdatingTest extends AbstractConfigurationHandlingTest
conf.put(new PropertySimple("needed","test"));
conf.put(new PropertySimple("optional",null));
- CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf);
+ CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, null);
assert cop.numberOfSteps() == 1;
Operation step1 = cop.step(0);
@@ -89,7 +89,7 @@ public class ConfigurationUpdatingTest extends AbstractConfigurationHandlingTest
conf.put(propertyList);
- CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf);
+ CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, null);
assert cop.numberOfSteps() == 1 : "#Steps should be 1 but were " + cop.numberOfSteps();
Operation step1 = cop.step(0);
@@ -120,7 +120,7 @@ public class ConfigurationUpdatingTest extends AbstractConfigurationHandlingTest
conf.put(propertyMap);
- CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf);
+ CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, null);
assert cop.numberOfSteps() == 1 : "#Steps should be 1 but were " + cop.numberOfSteps();
Operation step1 = cop.step(0);
@@ -148,7 +148,7 @@ public class ConfigurationUpdatingTest extends AbstractConfigurationHandlingTest
conf.put(propertyMap);
- CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf);
+ CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, null);
assert cop.numberOfSteps() == 1 : "#Steps should be 1 but were " + cop.numberOfSteps();
Operation step1 = cop.step(0);
@@ -176,7 +176,7 @@ public class ConfigurationUpdatingTest extends AbstractConfigurationHandlingTest
conf.put(propertyMap);
- CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf);
+ CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, null);
assert cop.numberOfSteps() == 1 : "#Steps should be 1 but were " + cop.numberOfSteps();
Operation step1 = cop.step(0);
@@ -207,7 +207,7 @@ public class ConfigurationUpdatingTest extends AbstractConfigurationHandlingTest
conf.put(propertyList);
- CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf);
+ CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, null);
assert cop.numberOfSteps() == 1 : "#Steps should be 1 but were " + cop.numberOfSteps();
Operation step1 = cop.step(0);
@@ -240,7 +240,7 @@ public class ConfigurationUpdatingTest extends AbstractConfigurationHandlingTest
conf.put(propertyList);
conf.put(new PropertySimple("port-offset",0));
- CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf);
+ CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, null);
assert cop.numberOfSteps() == 3 : "#Steps should be 3 but were " + cop.numberOfSteps();
Operation step1 = cop.step(0);
@@ -289,7 +289,7 @@ public class ConfigurationUpdatingTest extends AbstractConfigurationHandlingTest
conf.put(propertyList);
conf.put(new PropertySimple("port-offset",0));
- CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf);
+ CompositeOperation cop = delegate.updateGenerateOperationFromProperties(conf, null);
assert cop.numberOfSteps() == 5 : "#Steps should be 5 but were " + cop.numberOfSteps();
Operation step1 = cop.step(0);
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/XmlFileReadingTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/XmlFileReadingTest.java
new file mode 100644
index 0000000..2365d19
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/XmlFileReadingTest.java
@@ -0,0 +1,133 @@
+package org.rhq.modules.plugins.jbossas7;
+
+import java.net.URL;
+
+import org.testng.annotations.Test;
+
+/**
+ * Test the ability to read information from the AS7 xml files (standalone.xml and so on)
+ * @author Heiko W. Rupp
+ */
+@Test
+public class XmlFileReadingTest {
+
+ public void hostPort70() throws Exception {
+
+ BaseProcessDiscovery bd = new BaseProcessDiscovery();
+ URL url = getClass().getClassLoader().getResource("standalone70.xml");
+ bd.readStandaloneOrHostXmlFromFile(url.getFile());
+
+ AbstractBaseDiscovery.HostPort hp = bd.getManagementPortFromHostXml(new String[]{});
+ System.out.println(hp);
+ assert hp.host.equals("127.0.0.70") : "Host is " + hp.host;
+ assert hp.port==19990 : "Port is " + hp.port;
+ }
+
+ public void hostPort71() throws Exception {
+
+ BaseProcessDiscovery bd = new BaseProcessDiscovery();
+ URL url = getClass().getClassLoader().getResource("standalone71.xml");
+ bd.readStandaloneOrHostXmlFromFile(url.getFile());
+
+ AbstractBaseDiscovery.HostPort hp = bd.getManagementPortFromHostXml(new String[]{});
+ System.out.println(hp);
+ // hp : HostPort{host='localhost', port=9990, isLocal=true}
+ assert hp.host.equals("127.0.0.71") : "Host is " + hp.host;
+ assert hp.port==29990 : "Port is " + hp.port;
+ }
+
+ public void domainController1() throws Exception {
+
+ BaseProcessDiscovery bd = new BaseProcessDiscovery();
+ URL url = getClass().getClassLoader().getResource("host1.xml");
+ bd.readStandaloneOrHostXmlFromFile(url.getFile());
+
+ AbstractBaseDiscovery.HostPort hp = bd.getDomainControllerFromHostXml();
+ assert hp.isLocal : "DC is not local as expected: " + hp;
+
+ }
+
+ public void domainController2() throws Exception {
+
+ BaseProcessDiscovery bd = new BaseProcessDiscovery();
+ URL url = getClass().getClassLoader().getResource("host2.xml");
+ bd.readStandaloneOrHostXmlFromFile(url.getFile());
+
+ AbstractBaseDiscovery.HostPort hp = bd.getDomainControllerFromHostXml();
+ assert "192.168.100.1".equals(hp.host) : "DC is at " + hp.host;
+ assert hp.port == 9559 : "DC port is at " + hp.port;
+ }
+
+
+
+ public void testXpath70() throws Exception {
+
+ BaseProcessDiscovery bd = new BaseProcessDiscovery();
+ URL url = getClass().getClassLoader().getResource("standalone70.xml");
+ bd.readStandaloneOrHostXmlFromFile(url.getFile());
+
+/*
+ String realm = bd.obtainXmlPropertyViaXPath("/management/management-interfaces/http-interface/@security-realm");
+ assert "ManagementRealm".equals(realm) : "Realm was " + realm;
+*/
+
+ String pathExpr = "//management/management-interfaces/http-interface/@port";
+ String port = bd.obtainXmlPropertyViaXPath(pathExpr);
+ assert "19990".equals(port) : "Port was [" + port + "]";
+
+ pathExpr = "//management/management-interfaces/http-interface/@interface";
+ String interfName = bd.obtainXmlPropertyViaXPath(pathExpr);
+ assert "management".equals(interfName) : "Interface was " + interfName;
+
+ pathExpr = "/server/interfaces/interface[@name='" + interfName + "']/inet-address/@value";
+ String interfElem = bd.obtainXmlPropertyViaXPath(pathExpr);
+ assert "${jboss.bind.address.management:127.0.0.70}".equals(interfElem) : "InterfElem was " + interfElem;
+
+ }
+
+
+ public void testXpath71() throws Exception {
+
+ BaseProcessDiscovery bd = new BaseProcessDiscovery();
+ URL url = getClass().getClassLoader().getResource("standalone71.xml");
+ bd.readStandaloneOrHostXmlFromFile(url.getFile());
+
+ String realm = bd.obtainXmlPropertyViaXPath("//management/management-interfaces/http-interface/@security-realm");
+ assert "ManagementRealm".equals(realm) : "Realm was " + realm;
+ String sbindingRef = bd.obtainXmlPropertyViaXPath(
+ ("//management/management-interfaces/http-interface/socket-binding/@http"));
+ assert "management-http".equals(sbindingRef): "Socketbinding was " + sbindingRef;
+
+ String pathExpr = "/server/socket-binding-group/socket-binding[@name='" + sbindingRef + "']/@port";
+ String port = bd.obtainXmlPropertyViaXPath(pathExpr);
+ assert "29990".equals(port) : "Port was [" + port + "]";
+
+ pathExpr = "/server/socket-binding-group/socket-binding[@name='" + sbindingRef + "']/@interface";
+ String interfName = bd.obtainXmlPropertyViaXPath(pathExpr);
+ assert "management".equals(interfName) : "Interface was " + interfName;
+
+ pathExpr = "/server/interfaces/interface[@name='" + interfName + "']/inet-address/@value";
+ String interfElem = bd.obtainXmlPropertyViaXPath(pathExpr);
+ assert "${jboss.bind.address.management:127.0.0.71}".equals(interfElem) : "InterfElem was " + interfElem;
+
+ }
+
+ public void testGetRealm() throws Exception {
+
+ BaseProcessDiscovery bd = new BaseProcessDiscovery();
+ URL url = getClass().getClassLoader().getResource("standalone71.xml");
+ bd.readStandaloneOrHostXmlFromFile(url.getFile());
+
+ String realm = bd.obtainXmlPropertyViaXPath("//management/management-interfaces/http-interface/@security-realm");
+ assert "ManagementRealm".equals(realm) : "Realm was " + realm;
+
+ String xpathExpression = "//management//security-realm[@name ='%s']/authentication/properties/@path";
+
+ String propsFileName = bd.obtainXmlPropertyViaXPath(String.format(xpathExpression,realm));
+ assert "mgmt-users.properties".equals(propsFileName) : "File name was " + propsFileName;
+
+ String propsFilePathRel = bd.obtainXmlPropertyViaXPath("//management//security-realm[@name ='" + realm + "']/authentication/properties/@relative-to");
+ assert "jboss.server.config.dir".equals(propsFilePathRel) : "Path was " + propsFileName;
+
+ }
+}
diff --git a/modules/plugins/jboss-as-7/src/test/resources/host1.xml b/modules/plugins/jboss-as-7/src/test/resources/host1.xml
new file mode 100644
index 0000000..2e35b78
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/test/resources/host1.xml
@@ -0,0 +1,92 @@
+<!--
+ ~ JBoss, Home of Professional Open Source.
+ ~ Copyright 2010, Red Hat, Inc., 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 is free software; you can redistribute it and/or modify it
+ ~ under the terms of the GNU Lesser General Public License as
+ ~ published by the Free Software Foundation; either version 2.1 of
+ ~ the License, or (at your option) any later version.
+ ~
+ ~ This software 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
+ ~ Lesser General Public License for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public
+ ~ License along with this software; if not, write to the Free
+ ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ -->
+
+<host xmlns="urn:jboss:domain:1.1"
+ name="master">
+
+ <management>
+ <security-realms>
+ <security-realm name="ManagementRealm">
+ <authentication>
+ <properties path="mgmt-users.properties" relative-to="jboss.domain.config.dir"/>
+ </authentication>
+ </security-realm>
+ </security-realms>
+ <management-interfaces>
+ <native-interface security-realm="ManagementRealm">
+ <socket interface="management" port="9999"/>
+ </native-interface>
+ <http-interface security-realm="ManagementRealm">
+ <socket interface="management" port="9990"/>
+ </http-interface>
+ </management-interfaces>
+ </management>
+
+ <domain-controller>
+ <local/>
+ <!-- Alternative remote domain controller configuration with a host and port -->
+ <!-- <remote host="192.168.100.1" port="9999"/> -->
+ </domain-controller>
+
+ <interfaces>
+ <interface name="management">
+ <inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
+ </interface>
+ <interface name="public">
+ <inet-address value="${jboss.bind.address:127.0.0.1}"/>
+ </interface>
+ </interfaces>
+
+ <jvms>
+ <jvm name="default">
+ <heap size="64m" max-size="128m"/>
+ </jvm>
+ </jvms>
+
+ <servers>
+ <server name="server-one" group="main-server-group">
+ <!-- server-one inherits the default socket-group declared in the server-group -->
+ <jvm name="default">
+ <!-- Remote JPDA debugging for a specific server
+ <jvm-options>
+ <option value="-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n"/>
+ </jvm-options>
+ -->
+ </jvm>
+ </server>
+
+ <server name="server-two" group="main-server-group" auto-start="true">
+ <!-- server-two avoids port conflicts by incrementing the ports in
+ the default socket-group declared in the server-group -->
+ <socket-binding-group ref="standard-sockets" port-offset="150"/>
+ <jvm name="default">
+ <heap size="64m" max-size="256m"/>
+ </jvm>
+ </server>
+
+ <server name="server-three" group="other-server-group" auto-start="false">
+ <!-- server-three avoids port conflicts by incrementing the ports in
+ the default socket-group declared in the server-group -->
+ <socket-binding-group ref="ha-sockets" port-offset="250"/>
+ </server>
+ </servers>
+</host>
diff --git a/modules/plugins/jboss-as-7/src/test/resources/host2.xml b/modules/plugins/jboss-as-7/src/test/resources/host2.xml
new file mode 100644
index 0000000..38ada1a
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/test/resources/host2.xml
@@ -0,0 +1,91 @@
+<!--
+ ~ JBoss, Home of Professional Open Source.
+ ~ Copyright 2010, Red Hat, Inc., 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 is free software; you can redistribute it and/or modify it
+ ~ under the terms of the GNU Lesser General Public License as
+ ~ published by the Free Software Foundation; either version 2.1 of
+ ~ the License, or (at your option) any later version.
+ ~
+ ~ This software 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
+ ~ Lesser General Public License for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public
+ ~ License along with this software; if not, write to the Free
+ ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ -->
+
+<host xmlns="urn:jboss:domain:1.1"
+ name="master">
+
+ <management>
+ <security-realms>
+ <security-realm name="ManagementRealm">
+ <authentication>
+ <properties path="mgmt-users.properties" relative-to="jboss.domain.config.dir"/>
+ </authentication>
+ </security-realm>
+ </security-realms>
+ <management-interfaces>
+ <native-interface security-realm="ManagementRealm">
+ <socket interface="management" port="9999"/>
+ </native-interface>
+ <http-interface security-realm="ManagementRealm">
+ <socket interface="management" port="9990"/>
+ </http-interface>
+ </management-interfaces>
+ </management>
+
+ <domain-controller>
+ <!-- Alternative remote domain controller configuration with a host and port -->
+ <remote host="192.168.100.1" port="9559"/>
+ </domain-controller>
+
+ <interfaces>
+ <interface name="management">
+ <inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
+ </interface>
+ <interface name="public">
+ <inet-address value="${jboss.bind.address:127.0.0.1}"/>
+ </interface>
+ </interfaces>
+
+ <jvms>
+ <jvm name="default">
+ <heap size="64m" max-size="128m"/>
+ </jvm>
+ </jvms>
+
+ <servers>
+ <server name="server-one" group="main-server-group">
+ <!-- server-one inherits the default socket-group declared in the server-group -->
+ <jvm name="default">
+ <!-- Remote JPDA debugging for a specific server
+ <jvm-options>
+ <option value="-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n"/>
+ </jvm-options>
+ -->
+ </jvm>
+ </server>
+
+ <server name="server-two" group="main-server-group" auto-start="true">
+ <!-- server-two avoids port conflicts by incrementing the ports in
+ the default socket-group declared in the server-group -->
+ <socket-binding-group ref="standard-sockets" port-offset="150"/>
+ <jvm name="default">
+ <heap size="64m" max-size="256m"/>
+ </jvm>
+ </server>
+
+ <server name="server-three" group="other-server-group" auto-start="false">
+ <!-- server-three avoids port conflicts by incrementing the ports in
+ the default socket-group declared in the server-group -->
+ <socket-binding-group ref="ha-sockets" port-offset="250"/>
+ </server>
+ </servers>
+</host>
diff --git a/modules/plugins/jboss-as-7/src/test/resources/standalone70.xml b/modules/plugins/jboss-as-7/src/test/resources/standalone70.xml
new file mode 100644
index 0000000..e07b9ef
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/test/resources/standalone70.xml
@@ -0,0 +1,433 @@
+<!--
+ ~ JBoss, Home of Professional Open Source.
+ ~ Copyright 2011, Red Hat, Inc., 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 is free software; you can redistribute it and/or modify it
+ ~ under the terms of the GNU Lesser General Public License as
+ ~ published by the Free Software Foundation; either version 2.1 of
+ ~ the License, or (at your option) any later version.
+ ~
+ ~ This software 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
+ ~ Lesser General Public License for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public
+ ~ License along with this software; if not, write to the Free
+ ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ -->
+
+<server xmlns="urn:jboss:domain:1.1">
+
+ <extensions>
+ <extension module="org.jboss.as.clustering.infinispan"/>
+ <extension module="org.jboss.as.connector"/>
+ <extension module="org.jboss.as.deployment-scanner"/>
+ <extension module="org.jboss.as.ee"/>
+ <extension module="org.jboss.as.ejb3"/>
+ <extension module="org.jboss.as.jacorb"/>
+ <extension module="org.jboss.as.jaxrs"/>
+ <extension module="org.jboss.as.jmx"/>
+ <extension module="org.jboss.as.jpa"/>
+ <extension module="org.jboss.as.logging"/>
+ <extension module="org.jboss.as.mail"/>
+ <extension module="org.jboss.as.messaging"/>
+ <extension module="org.jboss.as.naming"/>
+ <extension module="org.jboss.as.osgi"/>
+ <extension module="org.jboss.as.remoting"/>
+ <extension module="org.jboss.as.sar"/>
+ <extension module="org.jboss.as.security"/>
+ <extension module="org.jboss.as.threads"/>
+ <extension module="org.jboss.as.transactions"/>
+ <extension module="org.jboss.as.web"/>
+ <extension module="org.jboss.as.webservices"/>
+ <extension module="org.jboss.as.weld"/>
+ </extensions>
+
+ <management>
+ <security-realms>
+ <security-realm name="PropertiesMgmtSecurityRealm">
+ <authentication>
+ <properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
+ </authentication>
+ </security-realm>
+ </security-realms>
+ <management-interfaces>
+ <native-interface interface="management" port="9999"/>
+ <http-interface interface="management" port="19990"/>
+ </management-interfaces>
+ </management>
+
+ <profile>
+ <subsystem xmlns="urn:jboss:domain:logging:1.1">
+ <console-handler name="CONSOLE">
+ <level name="INFO"/>
+ <formatter>
+ <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
+ </formatter>
+ </console-handler>
+
+ <periodic-rotating-file-handler name="FILE">
+ <level name="INFO"/>
+ <formatter>
+ <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
+ </formatter>
+ <file relative-to="jboss.server.log.dir" path="server.log"/>
+ <suffix value=".yyyy-MM-dd"/>
+ </periodic-rotating-file-handler>
+
+ <logger category="com.arjuna">
+ <level name="WARN"/>
+ </logger>
+ <logger category="org.apache.tomcat.util.modeler">
+ <level name="WARN"/>
+ </logger>
+ <logger category="sun.rmi">
+ <level name="WARN"/>
+ </logger>
+ <logger category="jacorb">
+ <level name="WARN"/>
+ </logger>
+ <!-- set jacorb.config to ERROR to avoid the "jacorb.properties not found" messages during startup -->
+ <logger category="jacorb.config">
+ <level name="ERROR"/>
+ </logger>
+
+ <root-logger>
+ <level name="INFO"/>
+ <handlers>
+ <handler name="CONSOLE"/>
+ <handler name="FILE"/>
+ </handlers>
+ </root-logger>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:datasources:1.0">
+ <datasources>
+ <datasource jndi-name="java:jboss/datasources/ExampleDS" enabled="true" use-java-context="true"
+ pool-name="H2DS">
+ <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
+ <driver>h2</driver>
+ <pool></pool>
+ <security>
+ <user-name>sa</user-name>
+ <password>sa</password>
+ </security>
+ </datasource>
+ <drivers>
+ <driver name="h2" module="com.h2database.h2">
+ <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
+ </driver>
+ </drivers>
+ </datasources>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:deployment-scanner:1.0">
+ <deployment-scanner scan-interval="5000" relative-to="jboss.server.base.dir" path="deployments"/>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:ee:1.0" />
+ <subsystem xmlns="urn:jboss:domain:ejb3:1.2" >
+
+ <remote connector-ref="remoting-connector" thread-pool-name="default" />
+ <async thread-pool-name="default" />
+
+ <timer-service thread-pool-name="default" >
+ <data-store path="timer-service-data" relative-to="jboss.server.data.dir"/>
+ </timer-service>
+
+ <!-- EJB3 pools -->
+ <pools>
+ <bean-instance-pools>
+ <strict-max-pool name="slsb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5"
+ instance-acquisition-timeout-unit="MINUTES"/>
+
+ <strict-max-pool name="mdb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5"
+ instance-acquisition-timeout-unit="MINUTES"/>
+ </bean-instance-pools>
+ </pools>
+
+ <!-- Default MDB configurations -->
+ <mdb>
+ <resource-adapter-ref resource-adapter-name="hornetq-ra"/>
+ <bean-instance-pool-ref pool-name="mdb-strict-max-pool"/>
+ </mdb>
+
+ <!-- Session bean configurations -->
+ <session-bean>
+ <stateless>
+ <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
+ </stateless>
+ </session-bean>
+
+ <default-stateful-access-timeout>5000</default-stateful-access-timeout>
+ <default-singleton-access-timeout>5000</default-singleton-access-timeout>
+
+ <thread-pools>
+ <thread-pool name="default" max-threads="10" keepalive-time="100" />
+ </thread-pools>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:infinispan:1.0" default-cache-container="hibernate">
+ <cache-container name="hibernate" default-cache="local-query">
+ <local-cache name="entity">
+ <eviction strategy="LRU" max-entries="10000"/>
+ <expiration max-idle="100000"/>
+ </local-cache>
+ <local-cache name="local-query">
+ <eviction strategy="LRU" max-entries="10000"/>
+ <expiration max-idle="100000"/>
+ </local-cache>
+ <local-cache name="timestamps">
+ <eviction strategy="NONE"/>
+ </local-cache>
+ </cache-container>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:jacorb:1.0">
+ <orb name="JBoss" print-version="off" giop-minor-version="2">
+ <connection max-managed-buf-size="24" outbuf-cache-timeout="-1"/>
+ <naming root-context="JBoss/Naming/root" export-corbaloc="on"/>
+ </orb>
+ <poa monitoring="off" queue-wait="off">
+ <request-processors pool-size="2" max-threads="8"/>
+ </poa>
+ <interop sun="on" chunk-custom-rmi-valuetypes="on" strict-check-on-tc-creation="off"/>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:jaxrs:1.0"/>
+ <subsystem xmlns="urn:jboss:domain:jca:1.0">
+ <archive-validation enabled="false"/>
+ <bean-validation enabled="false"/>
+ <default-workmanager>
+ <short-running-threads blocking="true">
+ <core-threads count="10" per-cpu="20"/>
+ <queue-length count="10" per-cpu="20"/>
+ <max-threads count="10" per-cpu="20"/>
+ <keepalive-time time="10" unit="seconds"/>
+ </short-running-threads>
+ <long-running-threads blocking="true">
+ <core-threads count="10" per-cpu="20"/>
+ <queue-length count="10" per-cpu="20"/>
+ <max-threads count="10" per-cpu="20"/>
+ <keepalive-time time="10" unit="seconds"/>
+ </long-running-threads>
+ </default-workmanager>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:jmx:1.1" show-model="true">
+ <jmx-connector registry-binding="jmx-connector-registry" server-binding="jmx-connector-server" />
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:jpa:1.0">
+ <jpa default-datasource=""/>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:mail:1.0">
+ <mail-session jndi-name="java:jboss/mail/Default">
+ <smtp-server address="localhost" port="25"/>
+ </mail-session>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:messaging:1.1">
+ <hornetq-server>
+ <!-- Default journal file size is 10Mb, reduced here to 100k for faster first boot -->
+ <journal-file-size>102400</journal-file-size>
+ <journal-min-files>2</journal-min-files>
+ <journal-type>NIO</journal-type>
+ <!-- disable messaging persistence -->
+ <persistence-enabled>false</persistence-enabled>
+
+ <connectors>
+ <netty-connector name="netty" socket-binding="messaging"/>
+ <netty-connector name="netty-throughput" socket-binding="messaging-throughput">
+ <param key="batch-delay" value="50"/>
+ </netty-connector>
+ <in-vm-connector name="in-vm" server-id="0"/>
+ </connectors>
+
+ <acceptors>
+ <netty-acceptor name="netty" socket-binding="messaging"/>
+ <netty-acceptor name="netty-throughput" socket-binding="messaging-throughput">
+ <param key="batch-delay" value="50"/>
+ <param key="direct-deliver" value="false"/>
+ </netty-acceptor>
+ <in-vm-acceptor name="in-vm" server-id="0"/>
+ </acceptors>
+
+ <security-settings>
+ <security-setting match="#">
+ <permission type="createNonDurableQueue" roles="guest"/>
+ <permission type="deleteNonDurableQueue" roles="guest"/>
+ <permission type="consume" roles="guest"/>
+ <permission type="send" roles="guest"/>
+ </security-setting>
+ </security-settings>
+
+ <address-settings>
+ <!--default for catch all-->
+ <address-setting match="#">
+ <dead-letter-address>jms.queue.DLQ</dead-letter-address>
+ <expiry-address>jms.queue.ExpiryQueue</expiry-address>
+ <redelivery-delay>0</redelivery-delay>
+ <max-size-bytes>10485760</max-size-bytes>
+ <message-counter-history-day-limit>10</message-counter-history-day-limit>
+ <address-full-policy>BLOCK</address-full-policy>
+ </address-setting>
+ </address-settings>
+
+ <!--JMS Stuff-->
+ <jms-connection-factories>
+ <connection-factory name="InVmConnectionFactory">
+ <connectors>
+ <connector-ref connector-name="in-vm"/>
+ </connectors>
+ <entries>
+ <entry name="java:/ConnectionFactory"/>
+ </entries>
+ </connection-factory>
+ <connection-factory name="RemoteConnectionFactory">
+ <connectors>
+ <connector-ref connector-name="netty"/>
+ </connectors>
+ <entries>
+ <entry name="RemoteConnectionFactory"/>
+ </entries>
+ </connection-factory>
+ <pooled-connection-factory name="hornetq-ra">
+ <transaction mode="xa"/>
+ <connectors>
+ <connector-ref connector-name="in-vm"/>
+ </connectors>
+ <entries>
+ <entry name="java:/JmsXA"/>
+ </entries>
+ </pooled-connection-factory>
+ </jms-connection-factories>
+
+ <jms-destinations>
+ <jms-queue name="testQueue">
+ <entry name="queue/test"/>
+ </jms-queue>
+ <jms-topic name="testTopic">
+ <entry name="topic/test"/>
+ </jms-topic>
+ </jms-destinations>
+ </hornetq-server>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:naming:1.0"/>
+ <subsystem xmlns="urn:jboss:domain:osgi:1.1" activation="lazy">
+ <configuration pid="org.apache.felix.webconsole.internal.servlet.OsgiManager">
+ <property name="manager.root" value="jboss-osgi"/>
+ </configuration>
+ <properties>
+ <!-- Specifies the beginning start level of the framework -->
+ <property name="org.osgi.framework.startlevel.beginning">1</property>
+ </properties>
+ <capabilities>
+ <!-- modules registered with the OSGi layer on startup -->
+ <capability name="javax.api"/>
+ <capability name="javax.servlet.api"/>
+ <capability name="javax.transaction.api"/>
+ <!-- bundles installed on startup -->
+ <capability name="org.apache.aries.util"/>
+ <capability name="org.jboss.osgi.webconsole"/>
+ <capability name="org.osgi.compendium"/>
+ <!-- bundles started in startlevel 1 -->
+ <capability name="org.apache.felix.log" startlevel="1"/>
+ <capability name="org.jboss.osgi.logging" startlevel="1"/>
+ <capability name="org.apache.felix.configadmin" startlevel="1"/>
+ <capability name="org.jboss.as.osgi.configadmin" startlevel="1"/>
+ <!-- bundles started in startlevel 2 -->
+ <capability name="org.apache.aries.jmx" startlevel="2"/>
+ <capability name="org.apache.felix.eventadmin" startlevel="2"/>
+ <capability name="org.apache.felix.metatype" startlevel="2"/>
+ <capability name="org.apache.felix.scr" startlevel="2"/>
+ <capability name="org.apache.felix.webconsole" startlevel="2"/>
+ <capability name="org.jboss.netty" startlevel="2"/>
+ <capability name="org.jboss.osgi.jmx" startlevel="2"/>
+ <capability name="org.jboss.osgi.http" startlevel="2"/>
+ <capability name="org.projectodd.stilts" startlevel="2"/>
+ <!-- bundles started in startlevel 3 -->
+ <capability name="org.jboss.osgi.blueprint" startlevel="3"/>
+ <capability name="org.jboss.osgi.webapp" startlevel="3"/>
+ <capability name="org.jboss.osgi.xerces" startlevel="3"/>
+ </capabilities>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:remoting:1.0">
+ <connector name="remoting-connector" socket-binding="remoting"/>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:resource-adapters:1.0" />
+ <subsystem xmlns="urn:jboss:domain:sar:1.0"/>
+ <subsystem xmlns="urn:jboss:domain:security:1.0">
+ <security-domains>
+ <security-domain name="other" cache-type="default">
+ <authentication>
+ <login-module code="UsersRoles" flag="required"/>
+ </authentication>
+ </security-domain>
+ </security-domains>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:threads:1.0"/>
+ <subsystem xmlns="urn:jboss:domain:transactions:1.0">
+ <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>
+ <core-environment>
+ <process-id>
+ <uuid/>
+ </process-id>
+ </core-environment>
+ <coordinator-environment default-timeout="300"/>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:web:1.0" default-virtual-server="default-host">
+ <connector name="http" scheme="http" protocol="HTTP/1.1" socket-binding="http"/>
+ <virtual-server name="default-host" enable-welcome-root="true">
+ <alias name="localhost"/>
+ <alias name="example.com"/>
+ </virtual-server>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:webservices:1.0">
+ <modify-wsdl-address>true</modify-wsdl-address>
+ <wsdl-host>localhost</wsdl-host>
+ <!--
+ <wsdl-port>8080</wsdl-port>
+ <wsdl-secure-port>8443</wsdl-secure-port>
+ -->
+ <endpoint-config xmlns:ws="urn:jboss:jbossws-jaxws-config:4.0">
+ <ws:config-name>Standard-Endpoint-Config</ws:config-name>
+ </endpoint-config>
+ <endpoint-config xmlns:ws="urn:jboss:jbossws-jaxws-config:4.0">
+ <ws:config-name>Recording-Endpoint-Config</ws:config-name>
+ <ws:pre-handler-chains>
+ <handler-chain xmlns="http://java.sun.com/xml/ns/javaee">
+ <protocol-bindings>##SOAP11_HTTP ##SOAP11_HTTP_MTOM ##SOAP12_HTTP ##SOAP12_HTTP_MTOM
+ </protocol-bindings>
+ <handler>
+ <handler-name>RecordingHandler</handler-name>
+ <handler-class>org.jboss.ws.common.invocation.RecordingServerHandler</handler-class>
+ </handler>
+ </handler-chain>
+ </ws:pre-handler-chains>
+ </endpoint-config>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:weld:1.0"/>
+ </profile>
+
+ <interfaces>
+ <interface name="management">
+ <inet-address value="${jboss.bind.address.management:127.0.0.70}"/>
+ </interface>
+ <interface name="public">
+ <inet-address value="${jboss.bind.address:127.0.0.70}"/>
+ </interface>
+ </interfaces>
+
+ <socket-binding-group name="standard-sockets" default-interface="public">
+ <socket-binding name="http" port="8080"/>
+ <socket-binding name="https" port="8443"/>
+ <socket-binding name="jacorb" port="3528"/>
+ <socket-binding name="jacorb-ssl" port="3529"/>
+ <socket-binding name="jmx-connector-registry" interface="management" port="1090"/>
+ <socket-binding name="jmx-connector-server" interface="management" port="1091"/>
+ <socket-binding name="jndi" port="1099"/>
+ <socket-binding name="messaging" port="5445"/>
+ <socket-binding name="messaging-throughput" port="5455"/>
+ <socket-binding name="osgi-http" interface="management" port="8090"/>
+ <socket-binding name="remoting" port="4447"/>
+ <socket-binding name="txn-recovery-environment" port="4712"/>
+ <socket-binding name="txn-status-manager" port="4713"/>
+ </socket-binding-group>
+
+</server>
diff --git a/modules/plugins/jboss-as-7/src/test/resources/standalone71.xml b/modules/plugins/jboss-as-7/src/test/resources/standalone71.xml
new file mode 100644
index 0000000..0de6d00
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/test/resources/standalone71.xml
@@ -0,0 +1,453 @@
+<!--
+ ~ JBoss, Home of Professional Open Source.
+ ~ Copyright 2011, Red Hat, Inc., 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 is free software; you can redistribute it and/or modify it
+ ~ under the terms of the GNU Lesser General Public License as
+ ~ published by the Free Software Foundation; either version 2.1 of
+ ~ the License, or (at your option) any later version.
+ ~
+ ~ This software 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
+ ~ Lesser General Public License for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public
+ ~ License along with this software; if not, write to the Free
+ ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ -->
+
+<server xmlns="urn:jboss:domain:1.1">
+
+ <extensions>
+ <extension module="org.jboss.as.clustering.infinispan"/>
+ <extension module="org.jboss.as.cmp"/>
+ <extension module="org.jboss.as.connector"/>
+ <extension module="org.jboss.as.deployment-scanner"/>
+ <extension module="org.jboss.as.ee"/>
+ <extension module="org.jboss.as.ejb3"/>
+ <extension module="org.jboss.as.jacorb"/>
+ <extension module="org.jboss.as.jaxr"/>
+ <extension module="org.jboss.as.jaxrs"/>
+ <extension module="org.jboss.as.jdr"/>
+ <extension module="org.jboss.as.jmx"/>
+ <extension module="org.jboss.as.jpa"/>
+ <extension module="org.jboss.as.logging"/>
+ <extension module="org.jboss.as.mail"/>
+ <extension module="org.jboss.as.messaging"/>
+ <extension module="org.jboss.as.naming"/>
+ <extension module="org.jboss.as.osgi"/>
+ <extension module="org.jboss.as.pojo"/>
+ <extension module="org.jboss.as.remoting"/>
+ <extension module="org.jboss.as.sar"/>
+ <extension module="org.jboss.as.security"/>
+ <extension module="org.jboss.as.threads"/>
+ <extension module="org.jboss.as.transactions"/>
+ <extension module="org.jboss.as.web"/>
+ <extension module="org.jboss.as.webservices"/>
+ <extension module="org.jboss.as.weld"/>
+ </extensions>
+
+ <management>
+ <security-realms>
+ <security-realm name="ManagementRealm">
+ <authentication>
+ <properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
+ </authentication>
+ </security-realm>
+ </security-realms>
+ <management-interfaces>
+ <native-interface security-realm="ManagementRealm">
+ <socket-binding native="management-native"/>
+ </native-interface>
+ <http-interface security-realm="ManagementRealm">
+ <socket-binding http="management-http"/>
+ </http-interface>
+ </management-interfaces>
+ </management>
+
+ <profile>
+ <subsystem xmlns="urn:jboss:domain:logging:1.1">
+ <console-handler name="CONSOLE">
+ <level name="INFO"/>
+ <formatter>
+ <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
+ </formatter>
+ </console-handler>
+
+ <periodic-rotating-file-handler name="FILE">
+ <formatter>
+ <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
+ </formatter>
+ <file relative-to="jboss.server.log.dir" path="server.log"/>
+ <suffix value=".yyyy-MM-dd"/>
+ <append value="true"/>
+ </periodic-rotating-file-handler>
+
+ <logger category="com.arjuna">
+ <level name="WARN"/>
+ </logger>
+ <logger category="org.apache.tomcat.util.modeler">
+ <level name="WARN"/>
+ </logger>
+ <logger category="sun.rmi">
+ <level name="WARN"/>
+ </logger>
+ <logger category="jacorb">
+ <level name="WARN"/>
+ </logger>
+ <!-- set jacorb.config to ERROR to avoid the "jacorb.properties not found" messages during startup -->
+ <logger category="jacorb.config">
+ <level name="ERROR"/>
+ </logger>
+
+ <root-logger>
+ <level name="INFO"/>
+ <handlers>
+ <handler name="CONSOLE"/>
+ <handler name="FILE"/>
+ </handlers>
+ </root-logger>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:cmp:1.0"/>
+ <subsystem xmlns="urn:jboss:domain:datasources:1.0">
+ <datasources>
+ <datasource jndi-name="java:jboss/datasources/ExampleDS" enabled="true" use-java-context="true"
+ pool-name="H2DS">
+ <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
+ <driver>h2</driver>
+ <pool></pool>
+ <security>
+ <user-name>sa</user-name>
+ <password>sa</password>
+ </security>
+ </datasource>
+ <drivers>
+ <driver name="h2" module="com.h2database.h2">
+ <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
+ </driver>
+ </drivers>
+ </datasources>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:deployment-scanner:1.0">
+ <deployment-scanner scan-interval="5000" relative-to="jboss.server.base.dir" path="deployments"/>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:ee:1.0" />
+ <subsystem xmlns="urn:jboss:domain:ejb3:1.2" >
+
+ <remote connector-ref="remoting-connector" thread-pool-name="default" />
+ <async thread-pool-name="default" />
+
+ <timer-service thread-pool-name="default" >
+ <data-store path="timer-service-data" relative-to="jboss.server.data.dir"/>
+ </timer-service>
+
+ <!-- EJB3 pools -->
+ <pools>
+ <bean-instance-pools>
+ <strict-max-pool name="slsb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5"
+ instance-acquisition-timeout-unit="MINUTES"/>
+
+ <strict-max-pool name="mdb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5"
+ instance-acquisition-timeout-unit="MINUTES"/>
+ </bean-instance-pools>
+ </pools>
+
+ <!-- Default MDB configurations -->
+ <mdb>
+ <resource-adapter-ref resource-adapter-name="hornetq-ra"/>
+ <bean-instance-pool-ref pool-name="mdb-strict-max-pool"/>
+ </mdb>
+
+ <!-- Session bean configurations -->
+ <session-bean>
+ <stateless>
+ <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
+ </stateless>
+ <stateful default-access-timeout="5000"/>
+ <singleton default-access-timeout="5000"/>
+ </session-bean>
+
+ <thread-pools>
+ <thread-pool name="default" max-threads="10" keepalive-time="100" />
+ </thread-pools>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:infinispan:1.0" default-cache-container="hibernate">
+ <cache-container name="hibernate" default-cache="local-query">
+ <local-cache name="entity">
+ <eviction strategy="LRU" max-entries="10000"/>
+ <expiration max-idle="100000"/>
+ </local-cache>
+ <local-cache name="local-query">
+ <eviction strategy="LRU" max-entries="10000"/>
+ <expiration max-idle="100000"/>
+ </local-cache>
+ <local-cache name="timestamps">
+ <eviction strategy="NONE"/>
+ </local-cache>
+ </cache-container>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:jacorb:1.1"/>
+ <subsystem xmlns="urn:jboss:domain:jaxr:1.0">
+ <datasource jndi-name="java:jboss/datasources/ExampleDS"/>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:jaxrs:1.0"/>
+ <subsystem xmlns="urn:jboss:domain:jca:1.0">
+ <archive-validation enabled="false"/>
+ <bean-validation enabled="false"/>
+ <default-workmanager>
+ <short-running-threads blocking="true">
+ <core-threads count="10" per-cpu="20"/>
+ <queue-length count="10" per-cpu="20"/>
+ <max-threads count="10" per-cpu="20"/>
+ <keepalive-time time="10" unit="seconds"/>
+ </short-running-threads>
+ <long-running-threads blocking="true">
+ <core-threads count="10" per-cpu="20"/>
+ <queue-length count="10" per-cpu="20"/>
+ <max-threads count="10" per-cpu="20"/>
+ <keepalive-time time="10" unit="seconds"/>
+ </long-running-threads>
+ </default-workmanager>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:jdr:1.0"/>
+ <subsystem xmlns="urn:jboss:domain:jmx:1.1" show-model="true">
+ <jmx-connector registry-binding="jmx-connector-registry" server-binding="jmx-connector-server" />
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:jpa:1.0">
+ <jpa default-datasource=""/>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:mail:1.0">
+ <mail-session jndi-name="java:jboss/mail/Default">
+ <smtp-server address="localhost" port="25"/>
+ </mail-session>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:messaging:1.1">
+ <hornetq-server>
+ <!-- Default journal file size is 10Mb, reduced here to 100k for faster first boot -->
+ <journal-file-size>102400</journal-file-size>
+ <journal-min-files>2</journal-min-files>
+ <!-- disable messaging persistence -->
+ <persistence-enabled>false</persistence-enabled>
+
+ <connectors>
+ <netty-connector name="netty" socket-binding="messaging-client"/>
+ <netty-connector name="netty-throughput" socket-binding="messaging-throughput-client">
+ <param key="batch-delay" value="50"/>
+ </netty-connector>
+ <in-vm-connector name="in-vm" server-id="0"/>
+ </connectors>
+
+ <acceptors>
+ <netty-acceptor name="netty" socket-binding="messaging"/>
+ <netty-acceptor name="netty-throughput" socket-binding="messaging-throughput">
+ <param key="batch-delay" value="50"/>
+ <param key="direct-deliver" value="false"/>
+ </netty-acceptor>
+ <in-vm-acceptor name="in-vm" server-id="0"/>
+ </acceptors>
+
+ <security-settings>
+ <security-setting match="#">
+ <permission type="createNonDurableQueue" roles="guest"/>
+ <permission type="deleteNonDurableQueue" roles="guest"/>
+ <permission type="consume" roles="guest"/>
+ <permission type="send" roles="guest"/>
+ </security-setting>
+ </security-settings>
+
+ <address-settings>
+ <!--default for catch all-->
+ <address-setting match="#">
+ <dead-letter-address>jms.queue.DLQ</dead-letter-address>
+ <expiry-address>jms.queue.ExpiryQueue</expiry-address>
+ <redelivery-delay>0</redelivery-delay>
+ <max-size-bytes>10485760</max-size-bytes>
+ <message-counter-history-day-limit>10</message-counter-history-day-limit>
+ <address-full-policy>BLOCK</address-full-policy>
+ </address-setting>
+ </address-settings>
+
+ <!--JMS Stuff-->
+ <jms-connection-factories>
+ <connection-factory name="InVmConnectionFactory">
+ <connectors>
+ <connector-ref connector-name="in-vm"/>
+ </connectors>
+ <entries>
+ <entry name="java:/ConnectionFactory"/>
+ </entries>
+ </connection-factory>
+ <connection-factory name="RemoteConnectionFactory">
+ <connectors>
+ <connector-ref connector-name="netty"/>
+ </connectors>
+ <entries>
+ <entry name="RemoteConnectionFactory"/>
+ </entries>
+ </connection-factory>
+ <pooled-connection-factory name="hornetq-ra">
+ <transaction mode="xa"/>
+ <connectors>
+ <connector-ref connector-name="in-vm"/>
+ </connectors>
+ <entries>
+ <entry name="java:/JmsXA"/>
+ </entries>
+ </pooled-connection-factory>
+ </jms-connection-factories>
+
+ <jms-destinations>
+ <jms-queue name="testQueue">
+ <entry name="queue/test"/>
+ </jms-queue>
+ <jms-topic name="testTopic">
+ <entry name="topic/test"/>
+ </jms-topic>
+ </jms-destinations>
+ </hornetq-server>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:naming:1.0"/>
+ <subsystem xmlns="urn:jboss:domain:osgi:1.1" activation="lazy">
+ <configuration pid="org.apache.felix.webconsole.internal.servlet.OsgiManager">
+ <property name="manager.root" value="jboss-osgi"/>
+ </configuration>
+ <properties>
+ <!-- Specifies the beginning start level of the framework -->
+ <property name="org.osgi.framework.startlevel.beginning">1</property>
+ </properties>
+ <capabilities>
+ <!-- modules registered with the OSGi layer on startup -->
+ <capability name="javax.api"/>
+ <capability name="javax.servlet.api"/>
+ <capability name="javax.transaction.api"/>
+ <!-- bundles installed on startup -->
+ <capability name="org.apache.aries.util"/>
+ <capability name="org.jboss.osgi.webconsole"/>
+ <capability name="org.osgi.compendium"/>
+ <!-- bundles started in startlevel 1 -->
+ <capability name="org.apache.felix.log" startlevel="1"/>
+ <capability name="org.jboss.osgi.logging" startlevel="1"/>
+ <capability name="org.apache.felix.configadmin" startlevel="1"/>
+ <capability name="org.jboss.as.osgi.configadmin" startlevel="1"/>
+ <!-- bundles started in startlevel 2 -->
+ <capability name="org.apache.aries.jmx" startlevel="2"/>
+ <capability name="org.apache.felix.eventadmin" startlevel="2"/>
+ <capability name="org.apache.felix.metatype" startlevel="2"/>
+ <capability name="org.apache.felix.scr" startlevel="2"/>
+ <capability name="org.apache.felix.webconsole" startlevel="2"/>
+ <capability name="org.jboss.netty" startlevel="2"/>
+ <capability name="org.jboss.osgi.jmx" startlevel="2"/>
+ <capability name="org.jboss.osgi.http" startlevel="2"/>
+ <capability name="org.projectodd.stilts" startlevel="2"/>
+ <!-- bundles started in startlevel 3 -->
+ <capability name="org.jboss.osgi.blueprint" startlevel="3"/>
+ <capability name="org.jboss.osgi.webapp" startlevel="3"/>
+ <capability name="org.jboss.osgi.xerces" startlevel="3"/>
+ </capabilities>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:pojo:1.0" />
+ <subsystem xmlns="urn:jboss:domain:remoting:1.0">
+ <connector name="remoting-connector" socket-binding="remoting"/>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:resource-adapters:1.0" />
+ <subsystem xmlns="urn:jboss:domain:sar:1.0"/>
+ <subsystem xmlns="urn:jboss:domain:security:1.0">
+ <security-domains>
+ <security-domain name="other" cache-type="default">
+ <authentication>
+ <login-module code="UsersRoles" flag="required"/>
+ </authentication>
+ </security-domain>
+ <security-domain name="jboss-web-policy" cache-type="default">
+ <authorization>
+ <policy-module code="Delegating" flag="required"/>
+ </authorization>
+ </security-domain>
+ <security-domain name="jboss-ejb-policy" cache-type="default">
+ <authorization>
+ <policy-module code="Delegating" flag="required"/>
+ </authorization>
+ </security-domain>
+ </security-domains>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:threads:1.0"/>
+ <subsystem xmlns="urn:jboss:domain:transactions:1.1">
+ <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>
+ <core-environment>
+ <process-id>
+ <uuid/>
+ </process-id>
+ </core-environment>
+ <coordinator-environment default-timeout="300"/>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:web:1.0" default-virtual-server="default-host">
+ <connector name="http" scheme="http" protocol="HTTP/1.1" socket-binding="http"/>
+ <virtual-server name="default-host" enable-welcome-root="true">
+ <alias name="localhost"/>
+ <alias name="example.com"/>
+ </virtual-server>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:webservices:1.0">
+ <modify-wsdl-address>true</modify-wsdl-address>
+ <wsdl-host>${jboss.bind.address:127.0.0.1}</wsdl-host>
+ <!--
+ <wsdl-port>8080</wsdl-port>
+ <wsdl-secure-port>8443</wsdl-secure-port>
+ -->
+ <endpoint-config xmlns:ws="urn:jboss:jbossws-jaxws-config:4.0">
+ <ws:config-name>Standard-Endpoint-Config</ws:config-name>
+ </endpoint-config>
+ <endpoint-config xmlns:ws="urn:jboss:jbossws-jaxws-config:4.0">
+ <ws:config-name>Recording-Endpoint-Config</ws:config-name>
+ <ws:pre-handler-chains>
+ <handler-chain xmlns="http://java.sun.com/xml/ns/javaee">
+ <protocol-bindings>##SOAP11_HTTP ##SOAP11_HTTP_MTOM ##SOAP12_HTTP ##SOAP12_HTTP_MTOM
+ </protocol-bindings>
+ <handler>
+ <handler-name>RecordingHandler</handler-name>
+ <handler-class>org.jboss.ws.common.invocation.RecordingServerHandler</handler-class>
+ </handler>
+ </handler-chain>
+ </ws:pre-handler-chains>
+ </endpoint-config>
+ </subsystem>
+ <subsystem xmlns="urn:jboss:domain:weld:1.0"/>
+ </profile>
+
+ <interfaces>
+ <interface name="management">
+ <inet-address value="${jboss.bind.address.management:127.0.0.71}"/>
+ </interface>
+ <interface name="public">
+ <inet-address value="${jboss.bind.address:127.0.0.71}"/>
+ </interface>
+ </interfaces>
+
+ <socket-binding-group name="standard-sockets" default-interface="public">
+ <socket-binding name="http" port="8080"/>
+ <socket-binding name="https" port="8443"/>
+ <socket-binding name="jacorb" port="3528"/>
+ <socket-binding name="jacorb-ssl" port="3529"/>
+ <socket-binding name="jmx-connector-registry" interface="management" port="1090"/>
+ <socket-binding name="jmx-connector-server" interface="management" port="1091"/>
+ <socket-binding name="management-native" interface="management" port="9999"/>
+ <socket-binding name="management-http" interface="management" port="29990"/>
+ <socket-binding name="messaging" port="5445"/>
+ <socket-binding name="messaging-throughput" port="5455"/>
+ <socket-binding name="osgi-http" interface="management" port="8090"/>
+ <socket-binding name="remoting" port="4447"/>
+ <socket-binding name="txn-recovery-environment" port="4712"/>
+ <socket-binding name="txn-status-manager" port="4713"/>
+ <outbound-socket-binding name="messaging-client">
+ <local-destination socket-binding-ref="messaging"/>
+ </outbound-socket-binding>
+ <outbound-socket-binding name="messaging-throughput-client">
+ <local-destination socket-binding-ref="messaging-throughput"/>
+ </outbound-socket-binding>
+ </socket-binding-group>
+
+</server>
12 years, 4 months
[rhq] Branch 'release_jon2.4.2.GA' - modules/cli-tests modules/common modules/core modules/enterprise modules/helpers modules/plugins modules/pom.xml modules/test-utils pom.xml
by rhqci
modules/cli-tests/pom.xml | 2 +-
modules/common/ant-bundle/pom.xml | 2 +-
modules/common/filetemplate-bundle/pom.xml | 2 +-
modules/common/jboss-as/pom.xml | 2 +-
modules/common/pom.xml | 2 +-
modules/core/client-api/pom.xml | 2 +-
modules/core/comm-api/pom.xml | 2 +-
modules/core/dbutils/pom.xml | 2 +-
modules/core/domain/pom.xml | 2 +-
modules/core/gui/pom.xml | 2 +-
modules/core/native-system/pom.xml | 2 +-
modules/core/plugin-api/pom.xml | 2 +-
modules/core/plugin-container/pom.xml | 2 +-
modules/core/plugin-validator/pom.xml | 2 +-
modules/core/plugindoc/pom.xml | 2 +-
modules/core/pom.xml | 2 +-
modules/core/util/pom.xml | 2 +-
modules/enterprise/agent/pom.xml | 2 +-
modules/enterprise/agentupdate/pom.xml | 2 +-
modules/enterprise/comm/pom.xml | 2 +-
modules/enterprise/gui/base-perspective-jar/pom.xml | 2 +-
modules/enterprise/gui/base-perspective-war/pom.xml | 2 +-
modules/enterprise/gui/content_http-war/pom.xml | 2 +-
modules/enterprise/gui/coregui/pom.xml | 2 +-
modules/enterprise/gui/installer-war/pom.xml | 2 +-
modules/enterprise/gui/pom.xml | 2 +-
modules/enterprise/gui/portal-war/pom.xml | 2 +-
modules/enterprise/gui/webdav-war/pom.xml | 2 +-
modules/enterprise/pom.xml | 2 +-
modules/enterprise/remoting/cli/pom.xml | 2 +-
modules/enterprise/remoting/client-api/pom.xml | 2 +-
modules/enterprise/remoting/pom.xml | 2 +-
modules/enterprise/remoting/webservices/pom.xml | 2 +-
modules/enterprise/server/container-lib/pom.xml | 2 +-
modules/enterprise/server/container/pom.xml | 2 +-
modules/enterprise/server/ear/pom.xml | 2 +-
modules/enterprise/server/jar/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-email/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-irc/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-microblog/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-mobicents/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-operations/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-roles/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-snmp/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-subject/pom.xml | 2 +-
modules/enterprise/server/plugins/ant-bundle/pom.xml | 2 +-
modules/enterprise/server/plugins/cobbler/pom.xml | 2 +-
modules/enterprise/server/plugins/disk/pom.xml | 2 +-
modules/enterprise/server/plugins/filetemplate-bundle/pom.xml | 2 +-
modules/enterprise/server/plugins/jboss-software/pom.xml | 2 +-
modules/enterprise/server/plugins/perspectives/core/perspective/pom.xml | 2 +-
modules/enterprise/server/plugins/perspectives/core/pom.xml | 2 +-
modules/enterprise/server/plugins/pom.xml | 2 +-
modules/enterprise/server/plugins/rhnhosted/pom.xml | 2 +-
modules/enterprise/server/plugins/url/pom.xml | 2 +-
modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml | 2 +-
modules/enterprise/server/plugins/yum/pom.xml | 2 +-
modules/enterprise/server/safe-invoker/pom.xml | 2 +-
modules/enterprise/server/sars/agent-sar/pom.xml | 2 +-
modules/enterprise/server/sars/pom.xml | 2 +-
modules/enterprise/server/xml-schemas/pom.xml | 2 +-
modules/helpers/pluginAnnotations/pom.xml | 2 +-
modules/helpers/pluginGen/pom.xml | 2 +-
modules/helpers/pom.xml | 2 +-
modules/helpers/rtfilter/pom.xml | 2 +-
modules/plugins/aliases/pom.xml | 2 +-
modules/plugins/ant-bundle/pom.xml | 2 +-
modules/plugins/apache/pom.xml | 2 +-
modules/plugins/augeas/pom.xml | 2 +-
modules/plugins/cobbler/pom.xml | 2 +-
modules/plugins/cron/pom.xml | 2 +-
modules/plugins/database/pom.xml | 2 +-
modules/plugins/filetemplate-bundle/pom.xml | 2 +-
modules/plugins/grub/pom.xml | 2 +-
modules/plugins/hibernate/pom.xml | 2 +-
modules/plugins/hosts/pom.xml | 2 +-
modules/plugins/hudson/pom.xml | 2 +-
modules/plugins/iis/pom.xml | 2 +-
modules/plugins/jboss-as-5/pom.xml | 2 +-
modules/plugins/jboss-as/pom.xml | 2 +-
modules/plugins/jboss-cache-v3/pom.xml | 2 +-
modules/plugins/jboss-cache/pom.xml | 2 +-
modules/plugins/jmx/pom.xml | 2 +-
modules/plugins/mysql/pom.xml | 2 +-
modules/plugins/netservices/pom.xml | 2 +-
modules/plugins/oracle/pom.xml | 2 +-
modules/plugins/perftest/pom.xml | 2 +-
modules/plugins/platform/pom.xml | 2 +-
modules/plugins/pom.xml | 2 +-
modules/plugins/postfix/pom.xml | 2 +-
modules/plugins/postgres/pom.xml | 2 +-
modules/plugins/rhq-agent/pom.xml | 2 +-
modules/plugins/rhq-server/pom.xml | 2 +-
modules/plugins/samba/pom.xml | 2 +-
modules/plugins/script/pom.xml | 2 +-
modules/plugins/snmptrapd/pom.xml | 2 +-
modules/plugins/sshd/pom.xml | 2 +-
modules/plugins/sudoers/pom.xml | 2 +-
modules/plugins/tomcat/pom.xml | 2 +-
modules/plugins/twitter/pom.xml | 2 +-
modules/plugins/validate-all-plugins/pom.xml | 2 +-
modules/pom.xml | 2 +-
modules/test-utils/pom.xml | 2 +-
pom.xml | 2 +-
104 files changed, 104 insertions(+), 104 deletions(-)
New commits:
commit b7eff2a6e619d5f07229fdd964977025fcb9416d
Author: Hudson <jboss-qa-internal(a)redhat.com>
Date: Mon Dec 19 15:55:39 2011 -0500
development RHQ_3.0.1.JON243.GA
diff --git a/modules/cli-tests/pom.xml b/modules/cli-tests/pom.xml
index 8d68360..81bd003 100644
--- a/modules/cli-tests/pom.xml
+++ b/modules/cli-tests/pom.xml
@@ -8,7 +8,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<artifactId>rhq-cli-tests</artifactId>
diff --git a/modules/common/ant-bundle/pom.xml b/modules/common/ant-bundle/pom.xml
index 9e85b18..c201a7d 100644
--- a/modules/common/ant-bundle/pom.xml
+++ b/modules/common/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/common/filetemplate-bundle/pom.xml b/modules/common/filetemplate-bundle/pom.xml
index 1142bfa..4d91cbb 100644
--- a/modules/common/filetemplate-bundle/pom.xml
+++ b/modules/common/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/common/jboss-as/pom.xml b/modules/common/jboss-as/pom.xml
index de73f6f..5be13a7 100644
--- a/modules/common/jboss-as/pom.xml
+++ b/modules/common/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/common/pom.xml b/modules/common/pom.xml
index d72fcfb..f98b351 100644
--- a/modules/common/pom.xml
+++ b/modules/common/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/client-api/pom.xml b/modules/core/client-api/pom.xml
index cb2d087..69973e7 100644
--- a/modules/core/client-api/pom.xml
+++ b/modules/core/client-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/comm-api/pom.xml b/modules/core/comm-api/pom.xml
index 3fd2792..3936cdd 100644
--- a/modules/core/comm-api/pom.xml
+++ b/modules/core/comm-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index eaea6a2..48ae40c 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/domain/pom.xml b/modules/core/domain/pom.xml
index 743bc69..488c7a0 100644
--- a/modules/core/domain/pom.xml
+++ b/modules/core/domain/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/gui/pom.xml b/modules/core/gui/pom.xml
index d6f8396..bece1b9 100644
--- a/modules/core/gui/pom.xml
+++ b/modules/core/gui/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/native-system/pom.xml b/modules/core/native-system/pom.xml
index f9fba7b..71b368c 100644
--- a/modules/core/native-system/pom.xml
+++ b/modules/core/native-system/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-api/pom.xml b/modules/core/plugin-api/pom.xml
index 67b3838..c23624e 100644
--- a/modules/core/plugin-api/pom.xml
+++ b/modules/core/plugin-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-container/pom.xml b/modules/core/plugin-container/pom.xml
index e9d85a1..863d577 100644
--- a/modules/core/plugin-container/pom.xml
+++ b/modules/core/plugin-container/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-validator/pom.xml b/modules/core/plugin-validator/pom.xml
index cb8b277..7f31a24 100644
--- a/modules/core/plugin-validator/pom.xml
+++ b/modules/core/plugin-validator/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugindoc/pom.xml b/modules/core/plugindoc/pom.xml
index d9db30a..b378a12 100644
--- a/modules/core/plugindoc/pom.xml
+++ b/modules/core/plugindoc/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/pom.xml b/modules/core/pom.xml
index fbdf3ef..6756c03 100644
--- a/modules/core/pom.xml
+++ b/modules/core/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/util/pom.xml b/modules/core/util/pom.xml
index f2eac27..7aac4a4 100644
--- a/modules/core/util/pom.xml
+++ b/modules/core/util/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/agent/pom.xml b/modules/enterprise/agent/pom.xml
index cd971d6..ddf41eb 100644
--- a/modules/enterprise/agent/pom.xml
+++ b/modules/enterprise/agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/agentupdate/pom.xml b/modules/enterprise/agentupdate/pom.xml
index 8915cfd..634bd77 100644
--- a/modules/enterprise/agentupdate/pom.xml
+++ b/modules/enterprise/agentupdate/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/comm/pom.xml b/modules/enterprise/comm/pom.xml
index 47bc23d..8533639 100644
--- a/modules/enterprise/comm/pom.xml
+++ b/modules/enterprise/comm/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/base-perspective-jar/pom.xml b/modules/enterprise/gui/base-perspective-jar/pom.xml
index 770ffff..d15d563 100644
--- a/modules/enterprise/gui/base-perspective-jar/pom.xml
+++ b/modules/enterprise/gui/base-perspective-jar/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/base-perspective-war/pom.xml b/modules/enterprise/gui/base-perspective-war/pom.xml
index fee340c..28c7857 100644
--- a/modules/enterprise/gui/base-perspective-war/pom.xml
+++ b/modules/enterprise/gui/base-perspective-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/content_http-war/pom.xml b/modules/enterprise/gui/content_http-war/pom.xml
index 7c00862..080b26c 100644
--- a/modules/enterprise/gui/content_http-war/pom.xml
+++ b/modules/enterprise/gui/content_http-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-gui-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index bb3de86..59adb06 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/installer-war/pom.xml b/modules/enterprise/gui/installer-war/pom.xml
index 8be360e..33c788d 100644
--- a/modules/enterprise/gui/installer-war/pom.xml
+++ b/modules/enterprise/gui/installer-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/pom.xml b/modules/enterprise/gui/pom.xml
index 9fe206d..cb63145 100644
--- a/modules/enterprise/gui/pom.xml
+++ b/modules/enterprise/gui/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/portal-war/pom.xml b/modules/enterprise/gui/portal-war/pom.xml
index 14c917e..889f742 100644
--- a/modules/enterprise/gui/portal-war/pom.xml
+++ b/modules/enterprise/gui/portal-war/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/webdav-war/pom.xml b/modules/enterprise/gui/webdav-war/pom.xml
index 16aca09..60372aa 100644
--- a/modules/enterprise/gui/webdav-war/pom.xml
+++ b/modules/enterprise/gui/webdav-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/pom.xml b/modules/enterprise/pom.xml
index d050076..45ca321 100644
--- a/modules/enterprise/pom.xml
+++ b/modules/enterprise/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/remoting/cli/pom.xml b/modules/enterprise/remoting/cli/pom.xml
index 4526487..21de954 100644
--- a/modules/enterprise/remoting/cli/pom.xml
+++ b/modules/enterprise/remoting/cli/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<artifactId>rhq-remoting-cli</artifactId>
diff --git a/modules/enterprise/remoting/client-api/pom.xml b/modules/enterprise/remoting/client-api/pom.xml
index be3cf45..739f025 100644
--- a/modules/enterprise/remoting/client-api/pom.xml
+++ b/modules/enterprise/remoting/client-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<artifactId>rhq-remoting-client-api</artifactId>
diff --git a/modules/enterprise/remoting/pom.xml b/modules/enterprise/remoting/pom.xml
index 4a2c7ee..caabd84 100644
--- a/modules/enterprise/remoting/pom.xml
+++ b/modules/enterprise/remoting/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<artifactId>rhq-remoting-parent</artifactId>
diff --git a/modules/enterprise/remoting/webservices/pom.xml b/modules/enterprise/remoting/webservices/pom.xml
index ca723a9..07459eb 100644
--- a/modules/enterprise/remoting/webservices/pom.xml
+++ b/modules/enterprise/remoting/webservices/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<artifactId>rhq-remoting-webservices</artifactId>
diff --git a/modules/enterprise/server/container-lib/pom.xml b/modules/enterprise/server/container-lib/pom.xml
index 192836e..f585e4a 100644
--- a/modules/enterprise/server/container-lib/pom.xml
+++ b/modules/enterprise/server/container-lib/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/container/pom.xml b/modules/enterprise/server/container/pom.xml
index 5f551b0..ca47a1e 100644
--- a/modules/enterprise/server/container/pom.xml
+++ b/modules/enterprise/server/container/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index 92e1873..fe9ee45 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index c4d018a..0b47a1b 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/alert-email/pom.xml b/modules/enterprise/server/plugins/alert-email/pom.xml
index ff4ed8e..3cc1986 100644
--- a/modules/enterprise/server/plugins/alert-email/pom.xml
+++ b/modules/enterprise/server/plugins/alert-email/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/alert-irc/pom.xml b/modules/enterprise/server/plugins/alert-irc/pom.xml
index 3135d45..0c3bc07 100644
--- a/modules/enterprise/server/plugins/alert-irc/pom.xml
+++ b/modules/enterprise/server/plugins/alert-irc/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/alert-microblog/pom.xml b/modules/enterprise/server/plugins/alert-microblog/pom.xml
index fa8cbec..d44a127 100644
--- a/modules/enterprise/server/plugins/alert-microblog/pom.xml
+++ b/modules/enterprise/server/plugins/alert-microblog/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/alert-mobicents/pom.xml b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
index 69d276c..0c2840c 100644
--- a/modules/enterprise/server/plugins/alert-mobicents/pom.xml
+++ b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/alert-operations/pom.xml b/modules/enterprise/server/plugins/alert-operations/pom.xml
index 4aa06f7..6f99a04 100644
--- a/modules/enterprise/server/plugins/alert-operations/pom.xml
+++ b/modules/enterprise/server/plugins/alert-operations/pom.xml
@@ -2,7 +2,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/alert-roles/pom.xml b/modules/enterprise/server/plugins/alert-roles/pom.xml
index e3552c3..f62613e 100644
--- a/modules/enterprise/server/plugins/alert-roles/pom.xml
+++ b/modules/enterprise/server/plugins/alert-roles/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/alert-snmp/pom.xml b/modules/enterprise/server/plugins/alert-snmp/pom.xml
index 8cbe65b..66272fc 100644
--- a/modules/enterprise/server/plugins/alert-snmp/pom.xml
+++ b/modules/enterprise/server/plugins/alert-snmp/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/alert-subject/pom.xml b/modules/enterprise/server/plugins/alert-subject/pom.xml
index b97190d..b5b6abb 100644
--- a/modules/enterprise/server/plugins/alert-subject/pom.xml
+++ b/modules/enterprise/server/plugins/alert-subject/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/ant-bundle/pom.xml b/modules/enterprise/server/plugins/ant-bundle/pom.xml
index 47caebf..b88f0b2 100644
--- a/modules/enterprise/server/plugins/ant-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/cobbler/pom.xml b/modules/enterprise/server/plugins/cobbler/pom.xml
index 5214721..e08ef1a 100644
--- a/modules/enterprise/server/plugins/cobbler/pom.xml
+++ b/modules/enterprise/server/plugins/cobbler/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/disk/pom.xml b/modules/enterprise/server/plugins/disk/pom.xml
index 5ea374a..ad35350 100644
--- a/modules/enterprise/server/plugins/disk/pom.xml
+++ b/modules/enterprise/server/plugins/disk/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
index e3e9032..66f3286 100644
--- a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/jboss-software/pom.xml b/modules/enterprise/server/plugins/jboss-software/pom.xml
index 23a8eb8..bb29080 100644
--- a/modules/enterprise/server/plugins/jboss-software/pom.xml
+++ b/modules/enterprise/server/plugins/jboss-software/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/perspectives/core/perspective/pom.xml b/modules/enterprise/server/plugins/perspectives/core/perspective/pom.xml
index fb34937..d6db8c5 100644
--- a/modules/enterprise/server/plugins/perspectives/core/perspective/pom.xml
+++ b/modules/enterprise/server/plugins/perspectives/core/perspective/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/perspectives/core/pom.xml b/modules/enterprise/server/plugins/perspectives/core/pom.xml
index f312157..290b7ba 100644
--- a/modules/enterprise/server/plugins/perspectives/core/pom.xml
+++ b/modules/enterprise/server/plugins/perspectives/core/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/pom.xml b/modules/enterprise/server/plugins/pom.xml
index dcb8c9a..a1cef09 100644
--- a/modules/enterprise/server/plugins/pom.xml
+++ b/modules/enterprise/server/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/rhnhosted/pom.xml b/modules/enterprise/server/plugins/rhnhosted/pom.xml
index bd8654f..404c6df 100644
--- a/modules/enterprise/server/plugins/rhnhosted/pom.xml
+++ b/modules/enterprise/server/plugins/rhnhosted/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/url/pom.xml b/modules/enterprise/server/plugins/url/pom.xml
index c98c2ea..77c19b2 100644
--- a/modules/enterprise/server/plugins/url/pom.xml
+++ b/modules/enterprise/server/plugins/url/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
index 5cce22a..6380dcc 100644
--- a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
+++ b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/yum/pom.xml b/modules/enterprise/server/plugins/yum/pom.xml
index 79a4ead..28a14c5 100644
--- a/modules/enterprise/server/plugins/yum/pom.xml
+++ b/modules/enterprise/server/plugins/yum/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/safe-invoker/pom.xml b/modules/enterprise/server/safe-invoker/pom.xml
index e8ceb5d..430f32e 100644
--- a/modules/enterprise/server/safe-invoker/pom.xml
+++ b/modules/enterprise/server/safe-invoker/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/sars/agent-sar/pom.xml b/modules/enterprise/server/sars/agent-sar/pom.xml
index 099b56f..f6733c3 100644
--- a/modules/enterprise/server/sars/agent-sar/pom.xml
+++ b/modules/enterprise/server/sars/agent-sar/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-sars-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/sars/pom.xml b/modules/enterprise/server/sars/pom.xml
index 5531eac..394d986 100644
--- a/modules/enterprise/server/sars/pom.xml
+++ b/modules/enterprise/server/sars/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/xml-schemas/pom.xml b/modules/enterprise/server/xml-schemas/pom.xml
index f4b89b0..f906f0a 100644
--- a/modules/enterprise/server/xml-schemas/pom.xml
+++ b/modules/enterprise/server/xml-schemas/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/helpers/pluginAnnotations/pom.xml b/modules/helpers/pluginAnnotations/pom.xml
index 3d3ac05..434f799 100644
--- a/modules/helpers/pluginAnnotations/pom.xml
+++ b/modules/helpers/pluginAnnotations/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/pluginGen/pom.xml b/modules/helpers/pluginGen/pom.xml
index 5e0db42..1308a8d 100644
--- a/modules/helpers/pluginGen/pom.xml
+++ b/modules/helpers/pluginGen/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/pom.xml b/modules/helpers/pom.xml
index 7412383..749e324 100644
--- a/modules/helpers/pom.xml
+++ b/modules/helpers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/rtfilter/pom.xml b/modules/helpers/rtfilter/pom.xml
index df0d64c..46de38f 100644
--- a/modules/helpers/rtfilter/pom.xml
+++ b/modules/helpers/rtfilter/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-helpers</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/aliases/pom.xml b/modules/plugins/aliases/pom.xml
index ef3090a..15e2750 100644
--- a/modules/plugins/aliases/pom.xml
+++ b/modules/plugins/aliases/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/ant-bundle/pom.xml b/modules/plugins/ant-bundle/pom.xml
index a822ab8..86eecd2 100644
--- a/modules/plugins/ant-bundle/pom.xml
+++ b/modules/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/apache/pom.xml b/modules/plugins/apache/pom.xml
index fd08ccc..2ff5eb0 100644
--- a/modules/plugins/apache/pom.xml
+++ b/modules/plugins/apache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/augeas/pom.xml b/modules/plugins/augeas/pom.xml
index d879477..3c482de 100644
--- a/modules/plugins/augeas/pom.xml
+++ b/modules/plugins/augeas/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cobbler/pom.xml b/modules/plugins/cobbler/pom.xml
index 13d3c3f..a19cdc7 100644
--- a/modules/plugins/cobbler/pom.xml
+++ b/modules/plugins/cobbler/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cron/pom.xml b/modules/plugins/cron/pom.xml
index 03beb20..de737b4 100644
--- a/modules/plugins/cron/pom.xml
+++ b/modules/plugins/cron/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/database/pom.xml b/modules/plugins/database/pom.xml
index d464b41..918d04f 100644
--- a/modules/plugins/database/pom.xml
+++ b/modules/plugins/database/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/filetemplate-bundle/pom.xml b/modules/plugins/filetemplate-bundle/pom.xml
index d9df461..8839e5c 100644
--- a/modules/plugins/filetemplate-bundle/pom.xml
+++ b/modules/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/grub/pom.xml b/modules/plugins/grub/pom.xml
index ed5cfb4..38a225b 100644
--- a/modules/plugins/grub/pom.xml
+++ b/modules/plugins/grub/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hibernate/pom.xml b/modules/plugins/hibernate/pom.xml
index baffb10..f276e11 100644
--- a/modules/plugins/hibernate/pom.xml
+++ b/modules/plugins/hibernate/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<!-- Bypass the jopr-plugins-parent which can not have children. It must build after the plugins in order to execute integration tests on them. -->
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/hosts/pom.xml b/modules/plugins/hosts/pom.xml
index f63d05e..374e5df 100644
--- a/modules/plugins/hosts/pom.xml
+++ b/modules/plugins/hosts/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hudson/pom.xml b/modules/plugins/hudson/pom.xml
index b8fe900..eceaf87 100644
--- a/modules/plugins/hudson/pom.xml
+++ b/modules/plugins/hudson/pom.xml
@@ -6,7 +6,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/iis/pom.xml b/modules/plugins/iis/pom.xml
index 97835f0..9620308 100644
--- a/modules/plugins/iis/pom.xml
+++ b/modules/plugins/iis/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/jboss-as-5/pom.xml b/modules/plugins/jboss-as-5/pom.xml
index 9f2522f..542142e 100644
--- a/modules/plugins/jboss-as-5/pom.xml
+++ b/modules/plugins/jboss-as-5/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-as/pom.xml b/modules/plugins/jboss-as/pom.xml
index 2abe0de..653ee35 100644
--- a/modules/plugins/jboss-as/pom.xml
+++ b/modules/plugins/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache-v3/pom.xml b/modules/plugins/jboss-cache-v3/pom.xml
index 8656715..e68e38b 100644
--- a/modules/plugins/jboss-cache-v3/pom.xml
+++ b/modules/plugins/jboss-cache-v3/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache/pom.xml b/modules/plugins/jboss-cache/pom.xml
index b0eef7a..4e168bc 100644
--- a/modules/plugins/jboss-cache/pom.xml
+++ b/modules/plugins/jboss-cache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jmx/pom.xml b/modules/plugins/jmx/pom.xml
index e3bc18a..41ffc43 100644
--- a/modules/plugins/jmx/pom.xml
+++ b/modules/plugins/jmx/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/mysql/pom.xml b/modules/plugins/mysql/pom.xml
index 38684e0..10ec9aa 100644
--- a/modules/plugins/mysql/pom.xml
+++ b/modules/plugins/mysql/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/netservices/pom.xml b/modules/plugins/netservices/pom.xml
index 8147c2d..ff25638 100644
--- a/modules/plugins/netservices/pom.xml
+++ b/modules/plugins/netservices/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/oracle/pom.xml b/modules/plugins/oracle/pom.xml
index 77ef2d4..86976d2 100644
--- a/modules/plugins/oracle/pom.xml
+++ b/modules/plugins/oracle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/perftest/pom.xml b/modules/plugins/perftest/pom.xml
index de9bc6d..b1ec92c 100644
--- a/modules/plugins/perftest/pom.xml
+++ b/modules/plugins/perftest/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/platform/pom.xml b/modules/plugins/platform/pom.xml
index 654d23e..8a1ea38 100644
--- a/modules/plugins/platform/pom.xml
+++ b/modules/plugins/platform/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index 70a80a1..5d98306 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/postfix/pom.xml b/modules/plugins/postfix/pom.xml
index 0db1680..578c1e1 100644
--- a/modules/plugins/postfix/pom.xml
+++ b/modules/plugins/postfix/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/postgres/pom.xml b/modules/plugins/postgres/pom.xml
index 6a1bdac..3841124 100644
--- a/modules/plugins/postgres/pom.xml
+++ b/modules/plugins/postgres/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-agent/pom.xml b/modules/plugins/rhq-agent/pom.xml
index e43228b..3d514c3 100644
--- a/modules/plugins/rhq-agent/pom.xml
+++ b/modules/plugins/rhq-agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-server/pom.xml b/modules/plugins/rhq-server/pom.xml
index 11521dc..9f3a224 100644
--- a/modules/plugins/rhq-server/pom.xml
+++ b/modules/plugins/rhq-server/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/samba/pom.xml b/modules/plugins/samba/pom.xml
index ec50f41..30f3fba 100644
--- a/modules/plugins/samba/pom.xml
+++ b/modules/plugins/samba/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/script/pom.xml b/modules/plugins/script/pom.xml
index c874e1b..ba24f88 100644
--- a/modules/plugins/script/pom.xml
+++ b/modules/plugins/script/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/snmptrapd/pom.xml b/modules/plugins/snmptrapd/pom.xml
index ac7a7a9..afe7f79 100644
--- a/modules/plugins/snmptrapd/pom.xml
+++ b/modules/plugins/snmptrapd/pom.xml
@@ -2,7 +2,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/plugins/sshd/pom.xml b/modules/plugins/sshd/pom.xml
index 931f8ba..4f954bb 100644
--- a/modules/plugins/sshd/pom.xml
+++ b/modules/plugins/sshd/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/sudoers/pom.xml b/modules/plugins/sudoers/pom.xml
index 76157ee..01c934b 100644
--- a/modules/plugins/sudoers/pom.xml
+++ b/modules/plugins/sudoers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/tomcat/pom.xml b/modules/plugins/tomcat/pom.xml
index 5de4a62..f5afa1d 100644
--- a/modules/plugins/tomcat/pom.xml
+++ b/modules/plugins/tomcat/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/twitter/pom.xml b/modules/plugins/twitter/pom.xml
index 9c9cc4b..e39c5e1 100644
--- a/modules/plugins/twitter/pom.xml
+++ b/modules/plugins/twitter/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/validate-all-plugins/pom.xml b/modules/plugins/validate-all-plugins/pom.xml
index 972f4b1..658021f 100644
--- a/modules/plugins/validate-all-plugins/pom.xml
+++ b/modules/plugins/validate-all-plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/pom.xml b/modules/pom.xml
index ac0e4ce..16c8532 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/test-utils/pom.xml b/modules/test-utils/pom.xml
index 2c364cf..d898ed7 100644
--- a/modules/test-utils/pom.xml
+++ b/modules/test-utils/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>rhq-modules-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
</parent>
<artifactId>test-utils</artifactId>
<name>RHQ Test Utils</name>
diff --git a/pom.xml b/pom.xml
index 1b80668..9663c8b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.JON242.GA</version>
+ <version>3.0.1.JON243.GA</version>
<packaging>pom</packaging>
<name>RHQ</name>
12 years, 4 months
[rhq] Changes to 'refs/tags/RHQ_3_0_1_JON242_GA'
by rhqci
Changes since RHQ_3_0_1_GA:
Filip Drabek (1):
BZ-669542 - Deploying exploded WAR to JBoss EAP 5 throws NPE operation fails
Hudson (1):
tag RHQ_3_0_1_JON242_GA
Ian Springer (3):
handle plugin jars whose manifest is not the 2nd entry in the jarfile (https://bugzilla.redhat.com/show_bug.cgi?id=682116)
a new 3.0.4 release of pluginAnnotations and pluginGen modules that changes the
[BZ 752981] remove duplicate call to FileSystemInfo.refresh(), which was resulting in invalid metric values (https://bugzilla.redhat.com/show_bug.cgi?id=752981); use switch-case rather than if-else in getValues() to make code more readable
Jay Shaughnessy (4):
New and Improved HibernateDetachUtility, now with enhanced collision
Update release script for build automation
The old version of this file requires on a static name and location for
Tried to repair this but the later versions are not compatible
John Mazzitelli (2):
cherry pick - this only does server-side alert engine - no UI support for RANGE alert conditions yet
[BZ 735262] this finishes the back port into release-3.0.1 to support alerting on a range of values. this still needs some testing
John Sanda (10):
[maven-release-plugin] prepare for next development iteration
Updating module versions to 3.0.1.GA
[BZ 677349] Do not obtain PC read lock prematurely
[BZ 677349] Adding logic to avoid deadlock during PC initialization
Removing file that was accidentally committed from merge conflict
[BZ 690430] Adding support for disabling SSL cert verification
[BZ 690430,690412] Adding additional logging for SSL exceptions
[BZ 690430] Removing plugin config for disabling cert validation
Further parameterizeing dbreset script
Refactoring logic in dbreset script for use with upgrade db
Larry O'Leary (10):
[Bug 700121] LDAP Group Member search doesn't escape special characters
[BZ 712192] [JON 2.4.1] Configuration hibernate proxy not being detached by HibernateDetachUtility and resulting in ClassNotFoundException
BZ-721151: Java Memory Leak caused by leaked Augeas resources
[BZ-732089] A fix to the identity collision logic, preventing falling through to the
Bug 736792 - CLI retrieveBackingContent gives a file not found exception on the agent
Fix build issues due to recent commits
BZ 753226: log message reporting invalid numeric metrics at DEBUG, rather than WARN, to avoid flooding the agent log with repetitive messages
Fix Maven SureFire Plugin property maven.surefire.debug in parent pom as it contained a line break that was being passed to the Java command-line resulting in a build error when test.debug is used
Fix build error due to pluginGen and pluginAnnotations being dependent on rhq-parent 4.0.1 instead of 3.0.1.GA (the version in release-3.0.1)
Fixed reliability of a couple of unit tests
Lukas Krejci (23):
need to update vhost::getNode() to not use the matching. basically I need
BZ 700616 - First pass at converting the discovery to using the runtime configuration.
BZ 700616 - apache server discovery component uses runtime discovery as well now
BZ 700616 - apache vhost resource configuration loading/update converted to take advantage of the SNMP WWW Service Index property, no imperfect RK matching anymore.
BZ 700616 - adding a new operation to apache server resource to detect the SNMP WWW Service Index values for individual virtual hosts. This is to a) support users when upgrading from RHQ 3.0.1 vanilla and b) to aid the users with reconfiguring the monitoring of vhosts after they changed order in the configuration files.
BZ 700461 - ResourceContext.getNativeProcess() now always reports the current process info or null if no process exists for given resource.
BZ 700616 - runtime config extracted even in the case server root was redefined in the config files.
BZ 700616 - porting over the alphabetic order awareness in glob patterns from master
Tests for the inclusion order and IfModule and IfDefine detection.
BZ 700616 - behave the same as apache when handling the corner case of unresolvable hostnames in virtual host address definition.
Adding IfVersion detection tests, removed the vhost-names test that will come in as standalone test because their not part of the runtime configuration extraction
Adding tests for the ability to produce the same server and port identifications as advertised by SNMP module in various scenarios.
BZ 700616 - Augeas tree abstraction now replaces the Include nodes with their contents instead of just appending their contents to their children list.
BZ 700616 - adding a default value to the new snmpWwwServiceIndex property so that updating the plugin actually works when there are some inventoried vhosts already on the server. Also removing the constraint so that the user is free to enter < 1 values to disable monitoring.
BZ 700616 - using the legacy code to create the virtual host resource keys to ensure the backwards compatibility with previous versions of the plugin.
BZ 700616 - ported over the code from master to handle the user provided module name <-> source file mappings for apache modules.
BZ 700616 - make sure to call getVersion() instead of resourceContext.getVersion() directly. This is just to workaround the possible null version being returned from the resourceContext in rare circumstances.
BZ 704486 - Improving the logging behavior of the unknown apache modules.
PERF - don't compile the regex patterns each time we instantiate a directive
BZ 694476 - fixing the handling of loaded modules.
BZ 690435 - Changing the main server vhost to always use the SNMP-like resource key to prevent the appearance of duplicates when parent server's URL property changes.
BZ 721151 - fixing the augeas memory leak - cherrypicked over from release-3.0.0
BZ 738027 - Working around the property names inconsistency in the clustered web app contexts.
Simeon Pinder (2):
BZ-689992: adding customizing for max start/stop WAIT_MAX times.
BZ 707342: JON 2.4 not allowing update of Resource name.
Stefan Negrea (2):
Fixing the formating for inline pom code.
BZ729991 - Updated the group alerts history gui expressions for sort to match the generated sql query.
---
.classpath | 5
modules/cli-tests/pom.xml | 2
modules/common/ant-bundle/pom.xml | 2
modules/common/filetemplate-bundle/pom.xml | 2
modules/common/jboss-as/pom.xml | 2
modules/common/pom.xml | 2
modules/core/client-api/pom.xml | 2
modules/core/client-api/src/main/java/org/rhq/core/clientapi/descriptor/PluginTransformer.java | 27
modules/core/comm-api/pom.xml | 2
modules/core/dbutils/pom.xml | 37
modules/core/domain/pom.xml | 2
modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java | 43
modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionCategory.java | 4
modules/core/domain/src/main/java/org/rhq/core/domain/alert/composite/AlertConditionRangeCategoryComposite.java | 48
modules/core/gui/pom.xml | 2
modules/core/native-system/pom.xml | 2
modules/core/plugin-api/pom.xml | 2
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java | 22
modules/core/plugin-container/pom.xml | 2
modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java | 42
modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventContextImpl.java | 29
modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementSenderRunner.java | 27
modules/core/plugin-validator/pom.xml | 2
modules/core/plugindoc/pom.xml | 2
modules/core/pom.xml | 2
modules/core/util/pom.xml | 2
modules/enterprise/agent/pom.xml | 2
modules/enterprise/agentupdate/pom.xml | 2
modules/enterprise/comm/pom.xml | 2
modules/enterprise/gui/base-perspective-jar/pom.xml | 2
modules/enterprise/gui/base-perspective-war/pom.xml | 2
modules/enterprise/gui/content_http-war/pom.xml | 2
modules/enterprise/gui/coregui/pom.xml | 2
modules/enterprise/gui/installer-war/pom.xml | 2
modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallatonTest.java | 169 -
modules/enterprise/gui/pom.xml | 2
modules/enterprise/gui/portal-war/pom.xml | 2
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/AlertDefUtil.java | 33
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/ViewAlertAction.java | 2
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/config/ConditionBean.java | 28
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/config/DefinitionForm.java | 6
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/config/condition/ConverterValidatorManager.java | 2
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/config/condition/MeasurementConverterValidator.java | 53
modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties | 4
modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/config/DefinitionCondition.jsp | 23
modules/enterprise/gui/portal-war/src/main/webapp/rhq/group/alert/listGroupAlertHistory.xhtml | 6
modules/enterprise/gui/webdav-war/pom.xml | 2
modules/enterprise/pom.xml | 2
modules/enterprise/remoting/cli/pom.xml | 2
modules/enterprise/remoting/client-api/pom.xml | 2
modules/enterprise/remoting/pom.xml | 2
modules/enterprise/remoting/webservices/pom.xml | 2
modules/enterprise/server/container-lib/pom.xml | 2
modules/enterprise/server/container/pom.xml | 2
modules/enterprise/server/ear/pom.xml | 2
modules/enterprise/server/jar/pom.xml | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerBean.java | 3
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java | 63
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AgentConditionCache.java | 54
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AlertConditionCacheUtils.java | 17
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElement.java | 95
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java | 38
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceFactoryManagerBean.java | 26
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceFactoryManagerLocal.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceFactoryManagerRemote.java | 6
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java | 138 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java | 6
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElementTest.java | 96
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java | 27
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/operation/OperationManagerBeanTest.java | 205 +
modules/enterprise/server/plugins/alert-email/pom.xml | 2
modules/enterprise/server/plugins/alert-irc/pom.xml | 2
modules/enterprise/server/plugins/alert-microblog/pom.xml | 2
modules/enterprise/server/plugins/alert-mobicents/pom.xml | 2
modules/enterprise/server/plugins/alert-operations/pom.xml | 2
modules/enterprise/server/plugins/alert-roles/pom.xml | 2
modules/enterprise/server/plugins/alert-snmp/pom.xml | 2
modules/enterprise/server/plugins/alert-subject/pom.xml | 2
modules/enterprise/server/plugins/ant-bundle/pom.xml | 2
modules/enterprise/server/plugins/cobbler/pom.xml | 2
modules/enterprise/server/plugins/disk/pom.xml | 2
modules/enterprise/server/plugins/filetemplate-bundle/pom.xml | 2
modules/enterprise/server/plugins/jboss-software/pom.xml | 2
modules/enterprise/server/plugins/perspectives/core/perspective/pom.xml | 2
modules/enterprise/server/plugins/perspectives/core/pom.xml | 2
modules/enterprise/server/plugins/pom.xml | 2
modules/enterprise/server/plugins/rhnhosted/pom.xml | 2
modules/enterprise/server/plugins/url/pom.xml | 2
modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml | 2
modules/enterprise/server/plugins/yum/pom.xml | 2
modules/enterprise/server/safe-invoker/pom.xml | 2
modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java | 300 ++
modules/enterprise/server/sars/agent-sar/pom.xml | 2
modules/enterprise/server/sars/pom.xml | 2
modules/enterprise/server/xml-schemas/pom.xml | 2
modules/helpers/pluginAnnotations/pom.xml | 13
modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/DataType.java | 2
modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/DisplayType.java | 2
modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/MeasurementType.java | 1
modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/Metric.java | 7
modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/Operation.java | 7
modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/Parameter.java | 3
modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/Units.java | 1
modules/helpers/pluginGen/pom.xml | 21
modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java | 65
modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl | 12
modules/helpers/pom.xml | 2
modules/helpers/rtfilter/pom.xml | 2
modules/plugins/aliases/pom.xml | 2
modules/plugins/ant-bundle/pom.xml | 2
modules/plugins/apache/pom.xml | 2
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheDirectoryComponent.java | 122 -
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheDirectoryDiscoveryComponent.java | 79
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheIfModuleComponent.java | 135 -
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheIfModuleDirectoryComponent.java | 65
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheIfModuleDirectoryDiscoveryComponent.java | 60
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheIfModuleDiscoveryComponent.java | 61
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerComponent.java | 503 ++--
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java | 171 +
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerOperationsDelegate.java | 72
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheVirtualHostServiceComponent.java | 509 +---
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheVirtualHostServiceDiscoveryComponent.java | 293 ++
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/augeas/ApacheAugeasNode.java | 69
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/augeas/AugeasConfigurationApache.java | 6
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/augeas/AugeasTreeBuilderApache.java | 25
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/parser/ApacheDirective.java | 33
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/parser/ApacheDirectiveTree.java | 10
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/parser/ApacheParserImpl.java | 2
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/util/ApacheBinaryInfo.java | 70
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/util/HttpdAddressUtility.java | 193 +
modules/plugins/apache/src/main/java/org/rhq/plugins/apache/util/RuntimeApacheConfiguration.java | 542 +++++
modules/plugins/apache/src/main/java/org/rhq/plugins/www/util/WWWUtils.java | 73
modules/plugins/apache/src/main/resources/META-INF/rhq-plugin.xml | 52
modules/plugins/apache/src/test/java/org/rhq/plugins/apache/ApacheAugeasTest.java | 242 +-
modules/plugins/apache/src/test/java/org/rhq/plugins/apache/RuntimeConfigurationTest.java | 208 +
modules/plugins/apache/src/test/java/org/rhq/plugins/apache/SnmpMappingTest.java | 140 +
modules/plugins/apache/src/test/java/org/rhq/plugins/apache/util/MockApacheBinaryInfo.java | 126 +
modules/plugins/apache/src/test/java/org/rhq/plugins/apache/util/MockProcessInfo.java | 51
modules/plugins/apache/src/test/resources/runtime-config/conditional/httpd.conf | 2
modules/plugins/apache/src/test/resources/runtime-config/conditional/ifdefine-defined.conf | 5
modules/plugins/apache/src/test/resources/runtime-config/conditional/ifdefine-undefined.conf | 5
modules/plugins/apache/src/test/resources/runtime-config/conditional/ifmodule-loaded.conf | 13
modules/plugins/apache/src/test/resources/runtime-config/conditional/ifmodule-not-loaded.conf | 11
modules/plugins/apache/src/test/resources/runtime-config/conditional/ifversion.conf | 43
modules/plugins/apache/src/test/resources/runtime-config/conditional/nested-mess.conf | 51
modules/plugins/apache/src/test/resources/runtime-config/incl-order/a.conf | 1
modules/plugins/apache/src/test/resources/runtime-config/incl-order/b.conf | 1
modules/plugins/apache/src/test/resources/runtime-config/incl-order/c.conf | 1
modules/plugins/apache/src/test/resources/runtime-config/incl-order/httpd.conf | 1
modules/plugins/apache/src/test/resources/snmp-mapping/httpd.conf | 5
modules/plugins/apache/src/test/resources/snmp-mapping/vhost-with-servername-by-ip.conf | 3
modules/plugins/apache/src/test/resources/snmp-mapping/vhost-with-servername-by-unresolvable-hostname.conf | 3
modules/plugins/apache/src/test/resources/snmp-mapping/vhost-without-servername-resolvable-ip.conf | 3
modules/plugins/apache/src/test/resources/snmp-mapping/vhost-without-servername-unresolvable-hostname.conf | 3
modules/plugins/apache/src/test/resources/snmp-mapping/vhost-without-servername-unresolvable-ip.conf | 3
modules/plugins/augeas/pom.xml | 2
modules/plugins/augeas/src/main/java/org/rhq/augeas/AugeasComponent.java | 52
modules/plugins/augeas/src/main/java/org/rhq/augeas/AugeasProxy.java | 60
modules/plugins/augeas/src/main/java/org/rhq/augeas/config/AugeasConfigurationSimple.java | 2
modules/plugins/augeas/src/main/java/org/rhq/augeas/util/Glob.java | 48
modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java | 203 +
modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java | 18
modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/AugeasRawConfigHelper.java | 28
modules/plugins/augeas/src/main/java/org/rhq/rhqtransform/AugeasRHQComponent.java | 22
modules/plugins/augeas/src/main/java/org/rhq/rhqtransform/impl/PluginDescriptorBasedAugeasConfiguration.java | 2
modules/plugins/cobbler/pom.xml | 2
modules/plugins/cron/pom.xml | 2
modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronComponent.java | 78
modules/plugins/database/pom.xml | 2
modules/plugins/filetemplate-bundle/pom.xml | 2
modules/plugins/grub/pom.xml | 2
modules/plugins/hibernate/pom.xml | 2
modules/plugins/hosts/pom.xml | 2
modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java | 4
modules/plugins/hudson/pom.xml | 2
modules/plugins/iis/pom.xml | 2
modules/plugins/jboss-as-5/pom.xml | 2
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java | 1057 ++++------
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerPluginConfigurationProperties.java | 2
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ManagedComponentComponent.java | 56
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/StandaloneManagedDeploymentComponent.java | 14
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/WebApplicationContextComponent.java | 53
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/deploy/ManagedComponentDeployer.java | 64
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/util/DeploymentUtils.java | 50
modules/plugins/jboss-as-5/src/main/resources/META-INF/rhq-plugin.xml | 19
modules/plugins/jboss-as/pom.xml | 2
modules/plugins/jboss-cache-v3/pom.xml | 2
modules/plugins/jboss-cache/pom.xml | 2
modules/plugins/jmx/pom.xml | 2
modules/plugins/mysql/pom.xml | 2
modules/plugins/netservices/pom.xml | 2
modules/plugins/oracle/pom.xml | 2
modules/plugins/perftest/pom.xml | 2
modules/plugins/platform/pom.xml | 2
modules/plugins/platform/src/main/java/org/rhq/plugins/platform/FileSystemComponent.java | 46
modules/plugins/pom.xml | 2
modules/plugins/postfix/pom.xml | 2
modules/plugins/postgres/pom.xml | 2
modules/plugins/rhq-agent/pom.xml | 2
modules/plugins/rhq-server/pom.xml | 2
modules/plugins/samba/pom.xml | 2
modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaShareComponent.java | 21
modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaShareDiscoveryComponent.java | 54
modules/plugins/script/pom.xml | 2
modules/plugins/snmptrapd/pom.xml | 2
modules/plugins/sshd/pom.xml | 2
modules/plugins/sudoers/pom.xml | 2
modules/plugins/tomcat/pom.xml | 2
modules/plugins/twitter/pom.xml | 2
modules/plugins/validate-all-plugins/pom.xml | 2
modules/pom.xml | 2
modules/test-utils/pom.xml | 2
pom.xml | 6
release.sh | 967 +++++----
rhq_bash.lib | 253 ++
215 files changed, 6395 insertions(+), 2870 deletions(-)
---
12 years, 4 months
[rhq] Branch 'release_jon2.4.2.GA' - modules/cli-tests modules/common modules/core modules/enterprise modules/helpers modules/plugins modules/pom.xml modules/test-utils pom.xml
by rhqci
modules/cli-tests/pom.xml | 2 +-
modules/common/ant-bundle/pom.xml | 2 +-
modules/common/filetemplate-bundle/pom.xml | 2 +-
modules/common/jboss-as/pom.xml | 2 +-
modules/common/pom.xml | 2 +-
modules/core/client-api/pom.xml | 2 +-
modules/core/comm-api/pom.xml | 2 +-
modules/core/dbutils/pom.xml | 2 +-
modules/core/domain/pom.xml | 2 +-
modules/core/gui/pom.xml | 2 +-
modules/core/native-system/pom.xml | 2 +-
modules/core/plugin-api/pom.xml | 2 +-
modules/core/plugin-container/pom.xml | 2 +-
modules/core/plugin-validator/pom.xml | 2 +-
modules/core/plugindoc/pom.xml | 2 +-
modules/core/pom.xml | 2 +-
modules/core/util/pom.xml | 2 +-
modules/enterprise/agent/pom.xml | 2 +-
modules/enterprise/agentupdate/pom.xml | 2 +-
modules/enterprise/comm/pom.xml | 2 +-
modules/enterprise/gui/base-perspective-jar/pom.xml | 2 +-
modules/enterprise/gui/base-perspective-war/pom.xml | 2 +-
modules/enterprise/gui/content_http-war/pom.xml | 2 +-
modules/enterprise/gui/coregui/pom.xml | 2 +-
modules/enterprise/gui/installer-war/pom.xml | 2 +-
modules/enterprise/gui/pom.xml | 2 +-
modules/enterprise/gui/portal-war/pom.xml | 2 +-
modules/enterprise/gui/webdav-war/pom.xml | 2 +-
modules/enterprise/pom.xml | 2 +-
modules/enterprise/remoting/cli/pom.xml | 2 +-
modules/enterprise/remoting/client-api/pom.xml | 2 +-
modules/enterprise/remoting/pom.xml | 2 +-
modules/enterprise/remoting/webservices/pom.xml | 2 +-
modules/enterprise/server/container-lib/pom.xml | 2 +-
modules/enterprise/server/container/pom.xml | 2 +-
modules/enterprise/server/ear/pom.xml | 2 +-
modules/enterprise/server/jar/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-email/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-irc/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-microblog/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-mobicents/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-operations/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-roles/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-snmp/pom.xml | 2 +-
modules/enterprise/server/plugins/alert-subject/pom.xml | 2 +-
modules/enterprise/server/plugins/ant-bundle/pom.xml | 2 +-
modules/enterprise/server/plugins/cobbler/pom.xml | 2 +-
modules/enterprise/server/plugins/disk/pom.xml | 2 +-
modules/enterprise/server/plugins/filetemplate-bundle/pom.xml | 2 +-
modules/enterprise/server/plugins/jboss-software/pom.xml | 2 +-
modules/enterprise/server/plugins/perspectives/core/perspective/pom.xml | 2 +-
modules/enterprise/server/plugins/perspectives/core/pom.xml | 2 +-
modules/enterprise/server/plugins/pom.xml | 2 +-
modules/enterprise/server/plugins/rhnhosted/pom.xml | 2 +-
modules/enterprise/server/plugins/url/pom.xml | 2 +-
modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml | 2 +-
modules/enterprise/server/plugins/yum/pom.xml | 2 +-
modules/enterprise/server/safe-invoker/pom.xml | 2 +-
modules/enterprise/server/sars/agent-sar/pom.xml | 2 +-
modules/enterprise/server/sars/pom.xml | 2 +-
modules/enterprise/server/xml-schemas/pom.xml | 2 +-
modules/helpers/pluginAnnotations/pom.xml | 2 +-
modules/helpers/pluginGen/pom.xml | 2 +-
modules/helpers/pom.xml | 2 +-
modules/helpers/rtfilter/pom.xml | 2 +-
modules/plugins/aliases/pom.xml | 2 +-
modules/plugins/ant-bundle/pom.xml | 2 +-
modules/plugins/apache/pom.xml | 2 +-
modules/plugins/augeas/pom.xml | 2 +-
modules/plugins/cobbler/pom.xml | 2 +-
modules/plugins/cron/pom.xml | 2 +-
modules/plugins/database/pom.xml | 2 +-
modules/plugins/filetemplate-bundle/pom.xml | 2 +-
modules/plugins/grub/pom.xml | 2 +-
modules/plugins/hibernate/pom.xml | 2 +-
modules/plugins/hosts/pom.xml | 2 +-
modules/plugins/hudson/pom.xml | 2 +-
modules/plugins/iis/pom.xml | 2 +-
modules/plugins/jboss-as-5/pom.xml | 2 +-
modules/plugins/jboss-as/pom.xml | 2 +-
modules/plugins/jboss-cache-v3/pom.xml | 2 +-
modules/plugins/jboss-cache/pom.xml | 2 +-
modules/plugins/jmx/pom.xml | 2 +-
modules/plugins/mysql/pom.xml | 2 +-
modules/plugins/netservices/pom.xml | 2 +-
modules/plugins/oracle/pom.xml | 2 +-
modules/plugins/perftest/pom.xml | 2 +-
modules/plugins/platform/pom.xml | 2 +-
modules/plugins/pom.xml | 2 +-
modules/plugins/postfix/pom.xml | 2 +-
modules/plugins/postgres/pom.xml | 2 +-
modules/plugins/rhq-agent/pom.xml | 2 +-
modules/plugins/rhq-server/pom.xml | 2 +-
modules/plugins/samba/pom.xml | 2 +-
modules/plugins/script/pom.xml | 2 +-
modules/plugins/snmptrapd/pom.xml | 2 +-
modules/plugins/sshd/pom.xml | 2 +-
modules/plugins/sudoers/pom.xml | 2 +-
modules/plugins/tomcat/pom.xml | 2 +-
modules/plugins/twitter/pom.xml | 2 +-
modules/plugins/validate-all-plugins/pom.xml | 2 +-
modules/pom.xml | 2 +-
modules/test-utils/pom.xml | 2 +-
pom.xml | 2 +-
104 files changed, 104 insertions(+), 104 deletions(-)
New commits:
commit 1afdc60a4385d7efdce3f8bb5c004a50c0e75e78
Author: Hudson <jboss-qa-internal(a)redhat.com>
Date: Mon Dec 19 15:55:06 2011 -0500
tag RHQ_3_0_1_JON242_GA
diff --git a/modules/cli-tests/pom.xml b/modules/cli-tests/pom.xml
index e2c6fe2..8d68360 100644
--- a/modules/cli-tests/pom.xml
+++ b/modules/cli-tests/pom.xml
@@ -8,7 +8,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<artifactId>rhq-cli-tests</artifactId>
diff --git a/modules/common/ant-bundle/pom.xml b/modules/common/ant-bundle/pom.xml
index e16c969..9e85b18 100644
--- a/modules/common/ant-bundle/pom.xml
+++ b/modules/common/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/common/filetemplate-bundle/pom.xml b/modules/common/filetemplate-bundle/pom.xml
index 284b2d0..1142bfa 100644
--- a/modules/common/filetemplate-bundle/pom.xml
+++ b/modules/common/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/common/jboss-as/pom.xml b/modules/common/jboss-as/pom.xml
index f857ff9..de73f6f 100644
--- a/modules/common/jboss-as/pom.xml
+++ b/modules/common/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/common/pom.xml b/modules/common/pom.xml
index b506670..d72fcfb 100644
--- a/modules/common/pom.xml
+++ b/modules/common/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/client-api/pom.xml b/modules/core/client-api/pom.xml
index da5d92d..cb2d087 100644
--- a/modules/core/client-api/pom.xml
+++ b/modules/core/client-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/comm-api/pom.xml b/modules/core/comm-api/pom.xml
index 8adbb53..3fd2792 100644
--- a/modules/core/comm-api/pom.xml
+++ b/modules/core/comm-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index 4f71c07..eaea6a2 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/domain/pom.xml b/modules/core/domain/pom.xml
index cbdef52..743bc69 100644
--- a/modules/core/domain/pom.xml
+++ b/modules/core/domain/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/gui/pom.xml b/modules/core/gui/pom.xml
index f2abcbe..d6f8396 100644
--- a/modules/core/gui/pom.xml
+++ b/modules/core/gui/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/native-system/pom.xml b/modules/core/native-system/pom.xml
index 7a93130..f9fba7b 100644
--- a/modules/core/native-system/pom.xml
+++ b/modules/core/native-system/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-api/pom.xml b/modules/core/plugin-api/pom.xml
index 6f1649f..67b3838 100644
--- a/modules/core/plugin-api/pom.xml
+++ b/modules/core/plugin-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-container/pom.xml b/modules/core/plugin-container/pom.xml
index 63ccf25..e9d85a1 100644
--- a/modules/core/plugin-container/pom.xml
+++ b/modules/core/plugin-container/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-validator/pom.xml b/modules/core/plugin-validator/pom.xml
index 6cb6145..cb8b277 100644
--- a/modules/core/plugin-validator/pom.xml
+++ b/modules/core/plugin-validator/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugindoc/pom.xml b/modules/core/plugindoc/pom.xml
index dc0ed50..d9db30a 100644
--- a/modules/core/plugindoc/pom.xml
+++ b/modules/core/plugindoc/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/pom.xml b/modules/core/pom.xml
index ab07d73..fbdf3ef 100644
--- a/modules/core/pom.xml
+++ b/modules/core/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/util/pom.xml b/modules/core/util/pom.xml
index 0ebec9b..f2eac27 100644
--- a/modules/core/util/pom.xml
+++ b/modules/core/util/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/agent/pom.xml b/modules/enterprise/agent/pom.xml
index e2cba96..cd971d6 100644
--- a/modules/enterprise/agent/pom.xml
+++ b/modules/enterprise/agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/agentupdate/pom.xml b/modules/enterprise/agentupdate/pom.xml
index 06cecca..8915cfd 100644
--- a/modules/enterprise/agentupdate/pom.xml
+++ b/modules/enterprise/agentupdate/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/comm/pom.xml b/modules/enterprise/comm/pom.xml
index f385a3f..47bc23d 100644
--- a/modules/enterprise/comm/pom.xml
+++ b/modules/enterprise/comm/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/base-perspective-jar/pom.xml b/modules/enterprise/gui/base-perspective-jar/pom.xml
index 95fd1b2..770ffff 100644
--- a/modules/enterprise/gui/base-perspective-jar/pom.xml
+++ b/modules/enterprise/gui/base-perspective-jar/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/base-perspective-war/pom.xml b/modules/enterprise/gui/base-perspective-war/pom.xml
index b6cfbf0..fee340c 100644
--- a/modules/enterprise/gui/base-perspective-war/pom.xml
+++ b/modules/enterprise/gui/base-perspective-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/content_http-war/pom.xml b/modules/enterprise/gui/content_http-war/pom.xml
index 03199e5..7c00862 100644
--- a/modules/enterprise/gui/content_http-war/pom.xml
+++ b/modules/enterprise/gui/content_http-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-gui-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index 872d763..bb3de86 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/installer-war/pom.xml b/modules/enterprise/gui/installer-war/pom.xml
index 5bdab57..8be360e 100644
--- a/modules/enterprise/gui/installer-war/pom.xml
+++ b/modules/enterprise/gui/installer-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/pom.xml b/modules/enterprise/gui/pom.xml
index 9e9abdf..9fe206d 100644
--- a/modules/enterprise/gui/pom.xml
+++ b/modules/enterprise/gui/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/portal-war/pom.xml b/modules/enterprise/gui/portal-war/pom.xml
index 90b1a23..14c917e 100644
--- a/modules/enterprise/gui/portal-war/pom.xml
+++ b/modules/enterprise/gui/portal-war/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/webdav-war/pom.xml b/modules/enterprise/gui/webdav-war/pom.xml
index 844eaf4..16aca09 100644
--- a/modules/enterprise/gui/webdav-war/pom.xml
+++ b/modules/enterprise/gui/webdav-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/pom.xml b/modules/enterprise/pom.xml
index d8531c8..d050076 100644
--- a/modules/enterprise/pom.xml
+++ b/modules/enterprise/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/remoting/cli/pom.xml b/modules/enterprise/remoting/cli/pom.xml
index 427373f..4526487 100644
--- a/modules/enterprise/remoting/cli/pom.xml
+++ b/modules/enterprise/remoting/cli/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<artifactId>rhq-remoting-cli</artifactId>
diff --git a/modules/enterprise/remoting/client-api/pom.xml b/modules/enterprise/remoting/client-api/pom.xml
index 815c268..be3cf45 100644
--- a/modules/enterprise/remoting/client-api/pom.xml
+++ b/modules/enterprise/remoting/client-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<artifactId>rhq-remoting-client-api</artifactId>
diff --git a/modules/enterprise/remoting/pom.xml b/modules/enterprise/remoting/pom.xml
index 4dd8834..4a2c7ee 100644
--- a/modules/enterprise/remoting/pom.xml
+++ b/modules/enterprise/remoting/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<artifactId>rhq-remoting-parent</artifactId>
diff --git a/modules/enterprise/remoting/webservices/pom.xml b/modules/enterprise/remoting/webservices/pom.xml
index 89703b8..ca723a9 100644
--- a/modules/enterprise/remoting/webservices/pom.xml
+++ b/modules/enterprise/remoting/webservices/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<artifactId>rhq-remoting-webservices</artifactId>
diff --git a/modules/enterprise/server/container-lib/pom.xml b/modules/enterprise/server/container-lib/pom.xml
index fc6d36c..192836e 100644
--- a/modules/enterprise/server/container-lib/pom.xml
+++ b/modules/enterprise/server/container-lib/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/container/pom.xml b/modules/enterprise/server/container/pom.xml
index 5ca49e4..5f551b0 100644
--- a/modules/enterprise/server/container/pom.xml
+++ b/modules/enterprise/server/container/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index f8695eb..92e1873 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index e767f5b..c4d018a 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/alert-email/pom.xml b/modules/enterprise/server/plugins/alert-email/pom.xml
index 7da5bfe..ff4ed8e 100644
--- a/modules/enterprise/server/plugins/alert-email/pom.xml
+++ b/modules/enterprise/server/plugins/alert-email/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/alert-irc/pom.xml b/modules/enterprise/server/plugins/alert-irc/pom.xml
index 4608407..3135d45 100644
--- a/modules/enterprise/server/plugins/alert-irc/pom.xml
+++ b/modules/enterprise/server/plugins/alert-irc/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/alert-microblog/pom.xml b/modules/enterprise/server/plugins/alert-microblog/pom.xml
index 045540c..fa8cbec 100644
--- a/modules/enterprise/server/plugins/alert-microblog/pom.xml
+++ b/modules/enterprise/server/plugins/alert-microblog/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/alert-mobicents/pom.xml b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
index fbf1d2f..69d276c 100644
--- a/modules/enterprise/server/plugins/alert-mobicents/pom.xml
+++ b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/alert-operations/pom.xml b/modules/enterprise/server/plugins/alert-operations/pom.xml
index a4618a5..4aa06f7 100644
--- a/modules/enterprise/server/plugins/alert-operations/pom.xml
+++ b/modules/enterprise/server/plugins/alert-operations/pom.xml
@@ -2,7 +2,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/alert-roles/pom.xml b/modules/enterprise/server/plugins/alert-roles/pom.xml
index 2673436..e3552c3 100644
--- a/modules/enterprise/server/plugins/alert-roles/pom.xml
+++ b/modules/enterprise/server/plugins/alert-roles/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/alert-snmp/pom.xml b/modules/enterprise/server/plugins/alert-snmp/pom.xml
index 9b90e7b..8cbe65b 100644
--- a/modules/enterprise/server/plugins/alert-snmp/pom.xml
+++ b/modules/enterprise/server/plugins/alert-snmp/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/alert-subject/pom.xml b/modules/enterprise/server/plugins/alert-subject/pom.xml
index 781d5ad..b97190d 100644
--- a/modules/enterprise/server/plugins/alert-subject/pom.xml
+++ b/modules/enterprise/server/plugins/alert-subject/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/ant-bundle/pom.xml b/modules/enterprise/server/plugins/ant-bundle/pom.xml
index 3f59440..47caebf 100644
--- a/modules/enterprise/server/plugins/ant-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/cobbler/pom.xml b/modules/enterprise/server/plugins/cobbler/pom.xml
index 7dd6631..5214721 100644
--- a/modules/enterprise/server/plugins/cobbler/pom.xml
+++ b/modules/enterprise/server/plugins/cobbler/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/enterprise/server/plugins/disk/pom.xml b/modules/enterprise/server/plugins/disk/pom.xml
index 31adf15..5ea374a 100644
--- a/modules/enterprise/server/plugins/disk/pom.xml
+++ b/modules/enterprise/server/plugins/disk/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
index 9efc65d..e3e9032 100644
--- a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/jboss-software/pom.xml b/modules/enterprise/server/plugins/jboss-software/pom.xml
index 17522cf..23a8eb8 100644
--- a/modules/enterprise/server/plugins/jboss-software/pom.xml
+++ b/modules/enterprise/server/plugins/jboss-software/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/perspectives/core/perspective/pom.xml b/modules/enterprise/server/plugins/perspectives/core/perspective/pom.xml
index 9ed8b81..fb34937 100644
--- a/modules/enterprise/server/plugins/perspectives/core/perspective/pom.xml
+++ b/modules/enterprise/server/plugins/perspectives/core/perspective/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/perspectives/core/pom.xml b/modules/enterprise/server/plugins/perspectives/core/pom.xml
index f8568cd..f312157 100644
--- a/modules/enterprise/server/plugins/perspectives/core/pom.xml
+++ b/modules/enterprise/server/plugins/perspectives/core/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/pom.xml b/modules/enterprise/server/plugins/pom.xml
index e11ef9c..dcb8c9a 100644
--- a/modules/enterprise/server/plugins/pom.xml
+++ b/modules/enterprise/server/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/rhnhosted/pom.xml b/modules/enterprise/server/plugins/rhnhosted/pom.xml
index 53e0508..bd8654f 100644
--- a/modules/enterprise/server/plugins/rhnhosted/pom.xml
+++ b/modules/enterprise/server/plugins/rhnhosted/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/url/pom.xml b/modules/enterprise/server/plugins/url/pom.xml
index 4ca964a..c98c2ea 100644
--- a/modules/enterprise/server/plugins/url/pom.xml
+++ b/modules/enterprise/server/plugins/url/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
index d12f06f..5cce22a 100644
--- a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
+++ b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/yum/pom.xml b/modules/enterprise/server/plugins/yum/pom.xml
index f4767d1..79a4ead 100644
--- a/modules/enterprise/server/plugins/yum/pom.xml
+++ b/modules/enterprise/server/plugins/yum/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/safe-invoker/pom.xml b/modules/enterprise/server/safe-invoker/pom.xml
index 9b40679..e8ceb5d 100644
--- a/modules/enterprise/server/safe-invoker/pom.xml
+++ b/modules/enterprise/server/safe-invoker/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/sars/agent-sar/pom.xml b/modules/enterprise/server/sars/agent-sar/pom.xml
index 8217a38..099b56f 100644
--- a/modules/enterprise/server/sars/agent-sar/pom.xml
+++ b/modules/enterprise/server/sars/agent-sar/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-sars-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/sars/pom.xml b/modules/enterprise/server/sars/pom.xml
index 3e4e5be..5531eac 100644
--- a/modules/enterprise/server/sars/pom.xml
+++ b/modules/enterprise/server/sars/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/xml-schemas/pom.xml b/modules/enterprise/server/xml-schemas/pom.xml
index c9e116f..f4b89b0 100644
--- a/modules/enterprise/server/xml-schemas/pom.xml
+++ b/modules/enterprise/server/xml-schemas/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/helpers/pluginAnnotations/pom.xml b/modules/helpers/pluginAnnotations/pom.xml
index d93cb06..3d3ac05 100644
--- a/modules/helpers/pluginAnnotations/pom.xml
+++ b/modules/helpers/pluginAnnotations/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/pluginGen/pom.xml b/modules/helpers/pluginGen/pom.xml
index 6cbb8da..5e0db42 100644
--- a/modules/helpers/pluginGen/pom.xml
+++ b/modules/helpers/pluginGen/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/pom.xml b/modules/helpers/pom.xml
index b3a39b8..7412383 100644
--- a/modules/helpers/pom.xml
+++ b/modules/helpers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/rtfilter/pom.xml b/modules/helpers/rtfilter/pom.xml
index 2c93677..df0d64c 100644
--- a/modules/helpers/rtfilter/pom.xml
+++ b/modules/helpers/rtfilter/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-helpers</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/aliases/pom.xml b/modules/plugins/aliases/pom.xml
index 4567647..ef3090a 100644
--- a/modules/plugins/aliases/pom.xml
+++ b/modules/plugins/aliases/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/ant-bundle/pom.xml b/modules/plugins/ant-bundle/pom.xml
index b2eb7ee..a822ab8 100644
--- a/modules/plugins/ant-bundle/pom.xml
+++ b/modules/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/apache/pom.xml b/modules/plugins/apache/pom.xml
index 0d873a0..fd08ccc 100644
--- a/modules/plugins/apache/pom.xml
+++ b/modules/plugins/apache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/augeas/pom.xml b/modules/plugins/augeas/pom.xml
index 7b07bff..d879477 100644
--- a/modules/plugins/augeas/pom.xml
+++ b/modules/plugins/augeas/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cobbler/pom.xml b/modules/plugins/cobbler/pom.xml
index 2f7afc9..13d3c3f 100644
--- a/modules/plugins/cobbler/pom.xml
+++ b/modules/plugins/cobbler/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cron/pom.xml b/modules/plugins/cron/pom.xml
index 1764232..03beb20 100644
--- a/modules/plugins/cron/pom.xml
+++ b/modules/plugins/cron/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/database/pom.xml b/modules/plugins/database/pom.xml
index be21346..d464b41 100644
--- a/modules/plugins/database/pom.xml
+++ b/modules/plugins/database/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/filetemplate-bundle/pom.xml b/modules/plugins/filetemplate-bundle/pom.xml
index 8544158..d9df461 100644
--- a/modules/plugins/filetemplate-bundle/pom.xml
+++ b/modules/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/grub/pom.xml b/modules/plugins/grub/pom.xml
index 7e7ff13..ed5cfb4 100644
--- a/modules/plugins/grub/pom.xml
+++ b/modules/plugins/grub/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hibernate/pom.xml b/modules/plugins/hibernate/pom.xml
index b3b0de7..baffb10 100644
--- a/modules/plugins/hibernate/pom.xml
+++ b/modules/plugins/hibernate/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<!-- Bypass the jopr-plugins-parent which can not have children. It must build after the plugins in order to execute integration tests on them. -->
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/hosts/pom.xml b/modules/plugins/hosts/pom.xml
index 16524ff..f63d05e 100644
--- a/modules/plugins/hosts/pom.xml
+++ b/modules/plugins/hosts/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hudson/pom.xml b/modules/plugins/hudson/pom.xml
index 4b6b349..b8fe900 100644
--- a/modules/plugins/hudson/pom.xml
+++ b/modules/plugins/hudson/pom.xml
@@ -6,7 +6,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/iis/pom.xml b/modules/plugins/iis/pom.xml
index 8e9e712..97835f0 100644
--- a/modules/plugins/iis/pom.xml
+++ b/modules/plugins/iis/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/jboss-as-5/pom.xml b/modules/plugins/jboss-as-5/pom.xml
index 6754dcd..9f2522f 100644
--- a/modules/plugins/jboss-as-5/pom.xml
+++ b/modules/plugins/jboss-as-5/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-as/pom.xml b/modules/plugins/jboss-as/pom.xml
index 4d20b23..2abe0de 100644
--- a/modules/plugins/jboss-as/pom.xml
+++ b/modules/plugins/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache-v3/pom.xml b/modules/plugins/jboss-cache-v3/pom.xml
index 1e3cc97..8656715 100644
--- a/modules/plugins/jboss-cache-v3/pom.xml
+++ b/modules/plugins/jboss-cache-v3/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache/pom.xml b/modules/plugins/jboss-cache/pom.xml
index f88f00d..b0eef7a 100644
--- a/modules/plugins/jboss-cache/pom.xml
+++ b/modules/plugins/jboss-cache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jmx/pom.xml b/modules/plugins/jmx/pom.xml
index f8c6cee..e3bc18a 100644
--- a/modules/plugins/jmx/pom.xml
+++ b/modules/plugins/jmx/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/mysql/pom.xml b/modules/plugins/mysql/pom.xml
index f4f7e35..38684e0 100644
--- a/modules/plugins/mysql/pom.xml
+++ b/modules/plugins/mysql/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/netservices/pom.xml b/modules/plugins/netservices/pom.xml
index aff86c9..8147c2d 100644
--- a/modules/plugins/netservices/pom.xml
+++ b/modules/plugins/netservices/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/oracle/pom.xml b/modules/plugins/oracle/pom.xml
index d60a5fd..77ef2d4 100644
--- a/modules/plugins/oracle/pom.xml
+++ b/modules/plugins/oracle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/perftest/pom.xml b/modules/plugins/perftest/pom.xml
index 505c001..de9bc6d 100644
--- a/modules/plugins/perftest/pom.xml
+++ b/modules/plugins/perftest/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/platform/pom.xml b/modules/plugins/platform/pom.xml
index 2204d6f..654d23e 100644
--- a/modules/plugins/platform/pom.xml
+++ b/modules/plugins/platform/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index fc15af8..70a80a1 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/postfix/pom.xml b/modules/plugins/postfix/pom.xml
index cbe2b75..0db1680 100644
--- a/modules/plugins/postfix/pom.xml
+++ b/modules/plugins/postfix/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/postgres/pom.xml b/modules/plugins/postgres/pom.xml
index 1b4321c..6a1bdac 100644
--- a/modules/plugins/postgres/pom.xml
+++ b/modules/plugins/postgres/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-agent/pom.xml b/modules/plugins/rhq-agent/pom.xml
index 648e108..e43228b 100644
--- a/modules/plugins/rhq-agent/pom.xml
+++ b/modules/plugins/rhq-agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-server/pom.xml b/modules/plugins/rhq-server/pom.xml
index 421827f..11521dc 100644
--- a/modules/plugins/rhq-server/pom.xml
+++ b/modules/plugins/rhq-server/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/samba/pom.xml b/modules/plugins/samba/pom.xml
index a6df78c..ec50f41 100644
--- a/modules/plugins/samba/pom.xml
+++ b/modules/plugins/samba/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/script/pom.xml b/modules/plugins/script/pom.xml
index 4201a72..c874e1b 100644
--- a/modules/plugins/script/pom.xml
+++ b/modules/plugins/script/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/snmptrapd/pom.xml b/modules/plugins/snmptrapd/pom.xml
index c86b9b2..ac7a7a9 100644
--- a/modules/plugins/snmptrapd/pom.xml
+++ b/modules/plugins/snmptrapd/pom.xml
@@ -2,7 +2,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/plugins/sshd/pom.xml b/modules/plugins/sshd/pom.xml
index f28b447..931f8ba 100644
--- a/modules/plugins/sshd/pom.xml
+++ b/modules/plugins/sshd/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/sudoers/pom.xml b/modules/plugins/sudoers/pom.xml
index 25c56ab..76157ee 100644
--- a/modules/plugins/sudoers/pom.xml
+++ b/modules/plugins/sudoers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/tomcat/pom.xml b/modules/plugins/tomcat/pom.xml
index abd7251..5de4a62 100644
--- a/modules/plugins/tomcat/pom.xml
+++ b/modules/plugins/tomcat/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/twitter/pom.xml b/modules/plugins/twitter/pom.xml
index e385f66..9c9cc4b 100644
--- a/modules/plugins/twitter/pom.xml
+++ b/modules/plugins/twitter/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/validate-all-plugins/pom.xml b/modules/plugins/validate-all-plugins/pom.xml
index 539a63e..972f4b1 100644
--- a/modules/plugins/validate-all-plugins/pom.xml
+++ b/modules/plugins/validate-all-plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/pom.xml b/modules/pom.xml
index a1285fd..ac0e4ce 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/test-utils/pom.xml b/modules/test-utils/pom.xml
index 0cf13f0..2c364cf 100644
--- a/modules/test-utils/pom.xml
+++ b/modules/test-utils/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>rhq-modules-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
</parent>
<artifactId>test-utils</artifactId>
<name>RHQ Test Utils</name>
diff --git a/pom.xml b/pom.xml
index ea21cc6..1b80668 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>3.0.1.GA</version>
+ <version>3.0.1.JON242.GA</version>
<packaging>pom</packaging>
<name>RHQ</name>
12 years, 4 months
[rhq] Branch 'release_jon2.4.2.GA' - modules/enterprise
by Jay Shaughnessy
modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallatonTest.java | 150 ----------
1 file changed, 150 deletions(-)
New commits:
commit 79a2593abc51996f3ba2559d6a735db54837f063
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Dec 19 15:16:17 2011 -0500
Tried to repair this but the later versions are not compatible
with this release. Removing these broken unit tests.
diff --git a/modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallatonTest.java b/modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallatonTest.java
deleted file mode 100644
index 3bff054..0000000
--- a/modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallatonTest.java
+++ /dev/null
@@ -1,150 +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, version 2, as
- * published by the Free Software Foundation, and/or the GNU Lesser
- * General Public License, version 2.1, also as published by the Free
- * Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License and the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * and the GNU Lesser General Public License along with this program;
- * if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.rhq.enterprise.installer;
-
-import org.rhq.core.db.reset.DBReset;
-import org.rhq.core.db.setup.DBSetup;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import java.io.File;
-import java.net.URL;
-import java.util.Properties;
-
-/**
- * The tests in this class exercise the dbsetup/dbupgrade code that is run in the installer. The tests currently only
- * run against postgresql. Support needs to be added for oracle. The tests do not do any post-install/upgrade
- * verification at the time of this writing. They just simply exercise the dbsetup/dbupgrade scripts to ensure that
- * they do not contain any errors.
- *
- * @author John Sanda
- */
-public class DBInstallationTest {
-
- private final String LOG_DIRECTORY = System.getProperty("java.io.tmpdir", "rhq/installer-test");
- private final String DB_NAME = System.getProperty("rhq.db.installation.test.db-name", "rhq_installer_test_db");
- private final String USERNAME = System.getProperty("rhq.test.ds.user-name", "rhqadmin");
- private final String PASSWORD = System.getProperty("rhq.test.ds.password", "rhqadmin");
- private final String SERVER = System.getProperty("rhq.test.ds.server-name", "127.0.0.1");
- private final String DB_URL = System.getProperty("rhq.db.installation.test.connection-url",
- "jdbc:postgresql://" + SERVER + ":5432/" + DB_NAME);
- private final String ADMIN_USERNAME = System.getProperty("rhq.db.admin.username", "postgres");
- private final String ADMIN_PASSWORD = System.getProperty("rhq.db.admin.password", "postgres");
- private static final String DB_TYPE_MAPPING = System.getProperty("rhq.test.ds.type-mapping", "PostgreSQL");
-
- private ServerInformation installer;
-
- @BeforeMethod
- public void prepareForInstallation() throws Exception {
- initLogDirectory();
- recreateTestDatabase();
-
- installer = new ServerInformation();
- installer.setLogDirectory(new File(LOG_DIRECTORY));
- }
-
- @Test
- public void overwriteJON230Schema() throws Exception {
- installSchemaAndData("2.3.0");
- installer.createNewDatabaseSchema(getInstallProperties());
- }
-
- @Test
- public void upgradeJON230Schema() throws Exception {
- installSchemaAndData("2.3.0");
- installer.upgradeExistingDatabaseSchema(getInstallProperties());
- }
-
- @Test
- public void overwriteJON231Schema() throws Exception {
- installSchemaAndData("2.3.1");
- installer.createNewDatabaseSchema(getInstallProperties());
- }
-
- @Test
- public void upgradeJON231Schema() throws Exception {
- installSchemaAndData("2.3.1");
- installer.upgradeExistingDatabaseSchema(getInstallProperties());
- }
-
- @Test
- public void overwriteJON240Schema() throws Exception {
- installSchemaAndData("2.4.0");
- installer.createNewDatabaseSchema(getInstallProperties());
- }
-
- @Test
- public void upgradeJON240Schema() throws Exception {
- installSchemaAndData("2.4.0");
- installer.upgradeExistingDatabaseSchema(getInstallProperties());
- }
-
- private void initLogDirectory() {
- File logDir = new File(LOG_DIRECTORY);
- if (logDir.exists()) {
- logDir.delete();
- }
- logDir.mkdirs();
- }
-
- private void recreateTestDatabase() throws Exception {
- DBReset dbReset = new DBReset();
- dbReset.performDBReset(DB_TYPE_MAPPING, DB_URL, DB_NAME, USERNAME, ADMIN_USERNAME, ADMIN_PASSWORD);
- }
-
- private void installSchemaAndData(String jonVersion) throws Exception {
- DBSetup dbsetup = new DBSetup(DB_URL, USERNAME, PASSWORD);
- dbsetup.setup(getSchemaFile(jonVersion).getAbsolutePath());
- dbsetup.setup(getDataFile(jonVersion).getAbsolutePath());
- }
-
- private File getSchemaFile(String version) throws Exception {
- URL url = getClass().getResource("db-schema-combined-" + version + ".xml");
-
- if (url == null) {
- throw new RuntimeException("Failed to find schema file for version " + version);
- }
-
- return new File(url.toURI().getPath());
- }
-
- private File getDataFile(String version) throws Exception {
- URL url = getClass().getResource("db-data-combined-" + version + ".xml");
-
- if (url == null) {
- throw new RuntimeException("Failed to find data file for version " + version);
- }
-
- return new File(url.toURI().getPath());
- }
-
- private Properties getInstallProperties() {
- Properties dbProperties = new Properties();
- dbProperties.put(ServerProperties.PROP_DATABASE_CONNECTION_URL, DB_URL);
- dbProperties.put(ServerProperties.PROP_DATABASE_USERNAME, USERNAME);
- dbProperties.put(ServerProperties.PROP_DATABASE_PASSWORD, PASSWORD);
- dbProperties.put(ServerProperties.PROP_EMAIL_FROM_ADDRESS, "rhqadmin(a)localhost.com");
- return dbProperties;
- }
-}
12 years, 4 months
[rhq] Branch 'release_jon2.4.2.GA' - modules/enterprise
by Jay Shaughnessy
modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallatonTest.java | 91 +++-------
1 file changed, 36 insertions(+), 55 deletions(-)
New commits:
commit 7812b862b15013d8c4720d4290681f3383a6811b
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Dec 19 14:26:25 2011 -0500
The old version of this file requires on a static name and location for
the db to be installed/upgraded in the tests. This version uses the
defined test db.
diff --git a/modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallatonTest.java b/modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallatonTest.java
index 12f4ac6..3bff054 100644
--- a/modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallatonTest.java
+++ b/modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallatonTest.java
@@ -23,16 +23,13 @@
package org.rhq.enterprise.installer;
-import org.rhq.core.db.DbUtil;
+import org.rhq.core.db.reset.DBReset;
import org.rhq.core.db.setup.DBSetup;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.io.File;
-import java.net.URI;
import java.net.URL;
-import java.sql.Connection;
-import java.sql.Statement;
import java.util.Properties;
/**
@@ -43,13 +40,20 @@ import java.util.Properties;
*
* @author John Sanda
*/
-public class DBInstallatonTest {
+public class DBInstallationTest {
- final String TEST_DB = "installer_test_db";
- final String USERNAME = "rhqadmin";
- final String PASSWORD = "rhqadmin";
+ private final String LOG_DIRECTORY = System.getProperty("java.io.tmpdir", "rhq/installer-test");
+ private final String DB_NAME = System.getProperty("rhq.db.installation.test.db-name", "rhq_installer_test_db");
+ private final String USERNAME = System.getProperty("rhq.test.ds.user-name", "rhqadmin");
+ private final String PASSWORD = System.getProperty("rhq.test.ds.password", "rhqadmin");
+ private final String SERVER = System.getProperty("rhq.test.ds.server-name", "127.0.0.1");
+ private final String DB_URL = System.getProperty("rhq.db.installation.test.connection-url",
+ "jdbc:postgresql://" + SERVER + ":5432/" + DB_NAME);
+ private final String ADMIN_USERNAME = System.getProperty("rhq.db.admin.username", "postgres");
+ private final String ADMIN_PASSWORD = System.getProperty("rhq.db.admin.password", "postgres");
+ private static final String DB_TYPE_MAPPING = System.getProperty("rhq.test.ds.type-mapping", "PostgreSQL");
- ServerInformation installer = new ServerInformation();
+ private ServerInformation installer;
@BeforeMethod
public void prepareForInstallation() throws Exception {
@@ -57,7 +61,7 @@ public class DBInstallatonTest {
recreateTestDatabase();
installer = new ServerInformation();
- installer.setLogDirectory(getLogDirectory());
+ installer.setLogDirectory(new File(LOG_DIRECTORY));
}
@Test
@@ -84,50 +88,38 @@ public class DBInstallatonTest {
installer.upgradeExistingDatabaseSchema(getInstallProperties());
}
- void initLogDirectory() {
- File logDir = getLogDirectory();
+ @Test
+ public void overwriteJON240Schema() throws Exception {
+ installSchemaAndData("2.4.0");
+ installer.createNewDatabaseSchema(getInstallProperties());
+ }
+
+ @Test
+ public void upgradeJON240Schema() throws Exception {
+ installSchemaAndData("2.4.0");
+ installer.upgradeExistingDatabaseSchema(getInstallProperties());
+ }
+
+ private void initLogDirectory() {
+ File logDir = new File(LOG_DIRECTORY);
if (logDir.exists()) {
logDir.delete();
}
logDir.mkdirs();
}
- void recreateTestDatabase() throws Exception {
- Connection connection = null;
- Statement dropDB = null;
- Statement createDB = null;
-
- try {
- String dbUrl = "jdbc:postgresql://127.0.0.1:5432/postgres";
-
- connection = DbUtil.getConnection(dbUrl, "postgres", "postgres");
- dropDB = connection.createStatement();
- createDB = connection.createStatement();
-
- dropDB.execute("drop database if exists " + TEST_DB);
- createDB.execute("create database " + TEST_DB + " with owner " + USERNAME);
- } finally {
- if (dropDB != null) {
- dropDB.close();
- }
- if (createDB != null) {
- createDB.close();
- }
- if (connection != null) {
- connection.close();
- }
- }
+ private void recreateTestDatabase() throws Exception {
+ DBReset dbReset = new DBReset();
+ dbReset.performDBReset(DB_TYPE_MAPPING, DB_URL, DB_NAME, USERNAME, ADMIN_USERNAME, ADMIN_PASSWORD);
}
- void installSchemaAndData(String jonVersion) throws Exception {
- String testDbUrl = getTestDbUrl();
-
- DBSetup dbsetup = new DBSetup(testDbUrl, USERNAME, PASSWORD);
+ private void installSchemaAndData(String jonVersion) throws Exception {
+ DBSetup dbsetup = new DBSetup(DB_URL, USERNAME, PASSWORD);
dbsetup.setup(getSchemaFile(jonVersion).getAbsolutePath());
dbsetup.setup(getDataFile(jonVersion).getAbsolutePath());
}
- File getSchemaFile(String version) throws Exception {
+ private File getSchemaFile(String version) throws Exception {
URL url = getClass().getResource("db-schema-combined-" + version + ".xml");
if (url == null) {
@@ -137,7 +129,7 @@ public class DBInstallatonTest {
return new File(url.toURI().getPath());
}
- File getDataFile(String version) throws Exception {
+ private File getDataFile(String version) throws Exception {
URL url = getClass().getResource("db-data-combined-" + version + ".xml");
if (url == null) {
@@ -147,23 +139,12 @@ public class DBInstallatonTest {
return new File(url.toURI().getPath());
}
- File getLogDirectory() {
- return new File(System.getProperty("java.io.tmpdir", "rhq/installer-test"));
- }
-
private Properties getInstallProperties() {
Properties dbProperties = new Properties();
- dbProperties.put(ServerProperties.PROP_DATABASE_CONNECTION_URL, getTestDbUrl());
+ dbProperties.put(ServerProperties.PROP_DATABASE_CONNECTION_URL, DB_URL);
dbProperties.put(ServerProperties.PROP_DATABASE_USERNAME, USERNAME);
dbProperties.put(ServerProperties.PROP_DATABASE_PASSWORD, PASSWORD);
dbProperties.put(ServerProperties.PROP_EMAIL_FROM_ADDRESS, "rhqadmin(a)localhost.com");
return dbProperties;
}
-
- private String getTestDbUrl() {
- return "jdbc:postgresql://127.0.0.1:5432/" + TEST_DB;
- }
-
-
-
}
12 years, 4 months
[rhq] Branch 'lkrejci/dissalow-alert-scripts-from-accessing-local-slsbs' - 31 commits - etc/cli-scripts etc/eclipse-tools modules/common modules/core modules/enterprise
by lkrejci
etc/cli-scripts/create_files.js | 186 ++++
etc/eclipse-tools/maven/RHQ | 11
modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetReaderImpl.java | 37
modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetWriter.java | 28
modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetWriterImpl.java | 23
modules/common/drift/src/main/java/org/rhq/common/drift/FileEntry.java | 45 +
modules/common/drift/src/test/java/org/rhq/common/drift/ChangeSetReaderImplTest.java | 43 -
modules/common/drift/src/test/java/org/rhq/common/drift/ChangeSetWriterImplTest.java | 41 -
modules/core/dbutils/src/main/java/org/rhq/core/db/OracleDatabaseType.java | 23
modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml | 5
modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainerConfiguration.java | 8
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ChangeSetManager.java | 8
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ChangeSetManagerImpl.java | 47 -
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftClient.java | 3
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetectionSchedule.java | 1
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java | 381 ++++++----
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftFilesSender.java | 107 ++
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java | 94 --
modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java | 13
modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/ChangeSetManagerImplTest.java | 4
modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftDetectorTest.java | 284 ++++---
modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java | 144 ++-
modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftManagerTest.java | 53 -
modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftTest.java | 6
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java | 66 -
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionDataSource.java | 9
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDetailsView.java | 57 -
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/util/DiffUtility.java | 112 ++
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeDatasource.java | 38
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties | 24
modules/enterprise/gui/installer-war/pom.xml | 4
modules/enterprise/gui/installer-war/src/main/webapp/start.jsp | 17
modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallationTest.java | 19
modules/enterprise/pom.xml | 1
modules/enterprise/server/itests/pom.xml | 6
modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java | 127 ++-
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerBean.java | 111 +-
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerLocal.java | 24
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerRemote.java | 29
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftTemplateManagerBean.java | 40 -
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java | 9
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/drift/DriftManagerBeanTest.java | 4
42 files changed, 1497 insertions(+), 795 deletions(-)
New commits:
commit 846c73c606a445dbe9f4627d28eafc154421eec6
Merge: f2803b9 572db8c
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Dec 19 19:57:58 2011 +0100
Merge branch 'master' into lkrejci/dissalow-alert-scripts-from-accessing-local-slsbs
commit 572db8ca18f25bea345b03243bf9b9bb8d9bdf8a
Author: John Sanda <jsanda(a)redhat.com>
Date: Mon Dec 19 10:34:58 2011 -0500
Adding/updating javadocs
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerLocal.java
index ac707cc..5a79413 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerLocal.java
@@ -140,8 +140,28 @@ public interface DriftManagerLocal extends DriftManagerRemote {
void updateDriftDefinition(Subject subject, DriftDefinition driftDefinition);
/**
- * Update the provided driftDef (identified by name) on the specified EntityContext. If it exists it will be replaced. If not it will
- * be added. Agents, if available, will be notified of the change.
+ * <p>
+ * Saves or updates the provided drift definition. If the definition, identified by name, already exists, an update
+ * is performed; otherwise, a new drift definition is saved. Agents if available will be notified of the change.
+ * If agents are unreachable, the definition will still be saved/updated. Changes will then propagate to agents
+ * the next time they do an inventory sync.
+ * </p>
+ * <p>
+ * Several validation checks are performed before the definition is persisted. If it is a new definition, the
+ * following checks are performed:
+ * <ul>
+ * <li>Verify that the resource supports drift management</li>
+ * <li>Verify that the template (if specified) already exists in the database</li>
+ * <li>Verify that the template (if specified) belongs to the correct resource type</li>
+ * </ul>
+ * For new and existing definitions these additional checks are performed:
+ * <ul>
+ * <li>Verify that the definition name does not contain illegal characters</li>
+ * <li>Verify that the base directory does not contain illegal characters</li>
+ * <li>Verify that filters do not contain illegal characters</li>
+ * </ul>
+ * </p>
+ *
* @param subject
* @param entityContext
* @param driftDef
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerRemote.java
index 1d3dc82..a39108e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerRemote.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerRemote.java
@@ -119,5 +119,32 @@ public interface DriftManagerRemote {
void pinSnapshot(Subject subject, int driftDefId, int snapshotVersion);
- void updateDriftDefinition(Subject subject, EntityContext entityContext, DriftDefinition driftConfig);
+ /**
+ * <p>
+ * Saves or updates the provided drift definition. If the definition, identified by name, already exists, an update
+ * is performed; otherwise, a new drift definition is saved. Agents if available will be notified of the change.
+ * If agents are unreachable, the definition will still be saved/updated. Changes will then propagate to agents
+ * the next time they do an inventory sync.
+ * </p>
+ * <p>
+ * Several validation checks are performed before the definition is persisted. If it is a new definition, the
+ * following checks are performed:
+ * <ul>
+ * <li>Verify that the resource supports drift management</li>
+ * <li>Verify that the template (if specified) already exists in the database</li>
+ * <li>Verify that the template (if specified) belongs to the correct resource type</li>
+ * </ul>
+ * For new and existing definitions these additional checks are performed:
+ * <ul>
+ * <li>Verify that the definition name does not contain illegal characters</li>
+ * <li>Verify that the base directory does not contain illegal characters</li>
+ * <li>Verify that filters do not contain illegal characters</li>
+ * </ul>
+ * </p>
+ *
+ * @param subject
+ * @param entityContext
+ * @param driftDef
+ */
+ void updateDriftDefinition(Subject subject, EntityContext entityContext, DriftDefinition driftDef);
}
commit 4a37ccc0f13f860f4e4831eac70431ad6beaa8a7
Author: John Sanda <jsanda(a)redhat.com>
Date: Mon Dec 19 09:34:47 2011 -0500
Commenting out tests that I added for BZ 768099
I ran into an issue where TestNG executes method in an unexpected order
that causes tests to fail.
http://groups.google.com/group/testng-users/browse_thread/thread/da279067...
provides some more background on the issue.
diff --git a/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java b/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java
index ac55445..36ff31f 100644
--- a/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java
+++ b/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java
@@ -26,16 +26,12 @@ import org.rhq.core.domain.criteria.JPADriftChangeSetCriteria;
import org.rhq.core.domain.drift.*;
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.util.PageList;
import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility;
import org.rhq.test.AssertUtils;
import org.rhq.test.TransactionCallback;
import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-import javax.ejb.EJBException;
import javax.persistence.EntityManager;
import java.util.ArrayList;
import java.util.List;
@@ -47,7 +43,6 @@ import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
import static org.rhq.core.domain.drift.DriftConfigurationDefinition.BaseDirValueContext.fileSystem;
import static org.rhq.core.domain.drift.DriftConfigurationDefinition.DriftHandlingMode.normal;
import static org.rhq.core.domain.drift.DriftDefinitionComparator.CompareMode.BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS;
-import static org.rhq.core.domain.resource.ResourceCategory.SERVER;
import static org.rhq.enterprise.server.util.LookupUtil.getDriftManager;
import static org.rhq.enterprise.server.util.LookupUtil.getDriftTemplateManager;
@@ -104,51 +99,60 @@ public class ManageDriftDefinitionsTest extends DriftServerTest {
assertEquals("The template association was not set on the definition", template, newDef.getTemplate());
}
- public void createEntitiesThatDoNotSupportDrift() {
- // first create the resource type that does not support drift
- driftNotSupportedType = new ResourceTypeBuilder()
- .createResourceType()
- .withId(0)
- .withName(DRIFT_NOT_SUPPORTED_TYPE)
- .withCategory(SERVER)
- .withPlugin(DRIFT_NOT_SUPPORTED_TYPE.toLowerCase())
- .build();
-
- // create a resource of the type that does not support drift
- driftNotSupportedResource = new ResourceBuilder()
- .createResource()
- .withId(0)
- .withName(DRIFT_NOT_SUPPORTED_RESOURCE)
- .withResourceKey(DRIFT_NOT_SUPPORTED_RESOURCE)
- .withRandomUuid()
- .withResourceType(driftNotSupportedType)
- .build();
-
- executeInTransaction(new TransactionCallback() {
- @Override
- public void execute() throws Exception {
- EntityManager em = getEntityManager();
- em.persist(driftNotSupportedType);
- em.persist(driftNotSupportedResource);
- }
- });
- }
-
- @Test(dependsOnMethods = "createEntitiesThatDoNotSupportDrift",
- expectedExceptions = EJBException.class,
- expectedExceptionsMessageRegExp = ".*Cannot create drift definition.*type.*does not support drift management")
- @InitDB(false)
- public void doNotAllowDefinitionToBeCreatedForTypeThatDoesNotSupportDrift() {
- DriftDefinition driftDef = new DriftDefinition(new Configuration());
- driftDef.setName("test_typeDoesNotSupportDrift");
- driftDef.setEnabled(true);
- driftDef.setInterval(1800L);
- driftDef.setDriftHandlingMode(normal);
- driftDef.setBasedir(new DriftDefinition.BaseDirectory(fileSystem, "/foo/bar/test"));
-
- driftMgr.updateDriftDefinition(getOverlord(), EntityContext.forResource(driftNotSupportedResource.getId()),
- driftDef);
- }
+ // The following two tests are commented out because when they are enabled
+ // and all tests in the itests module are run, the @AfterClass method for
+ // DriftTemplateManagerBeanTest does not run immediately after all of its
+ // test methods have finished running. Instead, some of the tests in
+ // ManageDriftDefinitionsTest start running. This leads to some database
+ // constraint violations because of how agents are created in the parent
+ // class, DriftServerTest. See http://groups.google.com/group/testng-users/browse_thread/thread/da279067...
+ // more info on the order in which TestNG executes tests.
+
+// public void createEntitiesThatDoNotSupportDrift() {
+// // first create the resource type that does not support drift
+// driftNotSupportedType = new ResourceTypeBuilder()
+// .createResourceType()
+// .withId(0)
+// .withName(DRIFT_NOT_SUPPORTED_TYPE)
+// .withCategory(SERVER)
+// .withPlugin(DRIFT_NOT_SUPPORTED_TYPE.toLowerCase())
+// .build();
+//
+// // create a resource of the type that does not support drift
+// driftNotSupportedResource = new ResourceBuilder()
+// .createResource()
+// .withId(0)
+// .withName(DRIFT_NOT_SUPPORTED_RESOURCE)
+// .withResourceKey(DRIFT_NOT_SUPPORTED_RESOURCE)
+// .withRandomUuid()
+// .withResourceType(driftNotSupportedType)
+// .build();
+//
+// executeInTransaction(new TransactionCallback() {
+// @Override
+// public void execute() throws Exception {
+// EntityManager em = getEntityManager();
+// em.persist(driftNotSupportedType);
+// em.persist(driftNotSupportedResource);
+// }
+// });
+// }
+//
+// @Test(dependsOnMethods = "createEntitiesThatDoNotSupportDrift",
+// expectedExceptions = EJBException.class,
+// expectedExceptionsMessageRegExp = ".*Cannot create drift definition.*type.*does not support drift management")
+// @InitDB(false)
+// public void doNotAllowDefinitionToBeCreatedForTypeThatDoesNotSupportDrift() {
+// DriftDefinition driftDef = new DriftDefinition(new Configuration());
+// driftDef.setName("test_typeDoesNotSupportDrift");
+// driftDef.setEnabled(true);
+// driftDef.setInterval(1800L);
+// driftDef.setDriftHandlingMode(normal);
+// driftDef.setBasedir(new DriftDefinition.BaseDirectory(fileSystem, "/foo/bar/test"));
+//
+// driftMgr.updateDriftDefinition(getOverlord(), EntityContext.forResource(driftNotSupportedResource.getId()),
+// driftDef);
+// }
@SuppressWarnings("unchecked")
public void createDefinitionFromPinnedTemplate() throws Exception {
commit 615c99b2a0d856b316b558a4e6fd7989b4004a15
Author: John Sanda <jsanda(a)redhat.com>
Date: Mon Dec 19 09:20:56 2011 -0500
[BZ 768099] Add validation checks when creating a drift definition
The following validation checks have been added:
* verify that the resource supports drift management
* verify that the template attached to the def exists in the db
* verify that that the template is from the correct resource type
diff --git a/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java b/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java
index 6e93bb3..ac55445 100644
--- a/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java
+++ b/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java
@@ -19,56 +19,64 @@
package org.rhq.enterprise.server.drift;
+import org.rhq.core.domain.common.EntityContext;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.criteria.DriftDefinitionCriteria;
+import org.rhq.core.domain.criteria.JPADriftChangeSetCriteria;
+import org.rhq.core.domain.drift.*;
+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.util.PageList;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility;
+import org.rhq.test.AssertUtils;
+import org.rhq.test.TransactionCallback;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.ejb.EJBException;
+import javax.persistence.EntityManager;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
import static java.util.Arrays.asList;
import static org.rhq.core.domain.drift.DriftCategory.FILE_ADDED;
import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
import static org.rhq.core.domain.drift.DriftConfigurationDefinition.BaseDirValueContext.fileSystem;
import static org.rhq.core.domain.drift.DriftConfigurationDefinition.DriftHandlingMode.normal;
import static org.rhq.core.domain.drift.DriftDefinitionComparator.CompareMode.BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS;
+import static org.rhq.core.domain.resource.ResourceCategory.SERVER;
import static org.rhq.enterprise.server.util.LookupUtil.getDriftManager;
import static org.rhq.enterprise.server.util.LookupUtil.getDriftTemplateManager;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import javax.persistence.EntityManager;
-
-import org.testng.annotations.BeforeClass;
+public class ManageDriftDefinitionsTest extends DriftServerTest {
-import org.rhq.core.domain.common.EntityContext;
-import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.criteria.DriftDefinitionCriteria;
-import org.rhq.core.domain.criteria.JPADriftChangeSetCriteria;
-import org.rhq.core.domain.drift.Drift;
-import org.rhq.core.domain.drift.DriftChangeSet;
-import org.rhq.core.domain.drift.DriftComplianceStatus;
-import org.rhq.core.domain.drift.DriftConfigurationDefinition;
-import org.rhq.core.domain.drift.DriftDefinition;
-import org.rhq.core.domain.drift.DriftDefinitionComparator;
-import org.rhq.core.domain.drift.DriftDefinitionTemplate;
-import org.rhq.core.domain.drift.DriftSnapshot;
-import org.rhq.core.domain.drift.JPADrift;
-import org.rhq.core.domain.drift.JPADriftChangeSet;
-import org.rhq.core.domain.drift.JPADriftFile;
-import org.rhq.core.domain.drift.JPADriftSet;
-import org.rhq.core.domain.util.PageList;
-import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility;
-import org.rhq.test.AssertUtils;
-import org.rhq.test.TransactionCallback;
+ private final String DRIFT_NOT_SUPPORTED_TYPE = getClass().getSimpleName() + "DRIFT_NOT_SUPPORTED_RESOURCE_TYPE";
-public class ManageDriftDefinitionsTest extends DriftServerTest {
+ private final String DRIFT_NOT_SUPPORTED_RESOURCE = getClass().getSimpleName() + "DRIFT_NOT_SUPPORTED_RESOURCE";
private DriftManagerLocal driftMgr;
private DriftTemplateManagerLocal templateMgr;
+ private ResourceType driftNotSupportedType;
+
+ private Resource driftNotSupportedResource;
+
@BeforeClass
public void initClass() throws Exception {
driftMgr = getDriftManager();
templateMgr = getDriftTemplateManager();
}
+ @Override
+ protected void purgeDB(EntityManager em) {
+ deleteEntity(Resource.class, DRIFT_NOT_SUPPORTED_RESOURCE, em);
+ deleteEntity(ResourceType.class, DRIFT_NOT_SUPPORTED_TYPE, em);
+ }
+
public void createDefinitionFromUnpinnedTemplate() {
// first create a template
final DriftDefinition templateDef = new DriftDefinition(new Configuration());
@@ -96,6 +104,52 @@ public class ManageDriftDefinitionsTest extends DriftServerTest {
assertEquals("The template association was not set on the definition", template, newDef.getTemplate());
}
+ public void createEntitiesThatDoNotSupportDrift() {
+ // first create the resource type that does not support drift
+ driftNotSupportedType = new ResourceTypeBuilder()
+ .createResourceType()
+ .withId(0)
+ .withName(DRIFT_NOT_SUPPORTED_TYPE)
+ .withCategory(SERVER)
+ .withPlugin(DRIFT_NOT_SUPPORTED_TYPE.toLowerCase())
+ .build();
+
+ // create a resource of the type that does not support drift
+ driftNotSupportedResource = new ResourceBuilder()
+ .createResource()
+ .withId(0)
+ .withName(DRIFT_NOT_SUPPORTED_RESOURCE)
+ .withResourceKey(DRIFT_NOT_SUPPORTED_RESOURCE)
+ .withRandomUuid()
+ .withResourceType(driftNotSupportedType)
+ .build();
+
+ executeInTransaction(new TransactionCallback() {
+ @Override
+ public void execute() throws Exception {
+ EntityManager em = getEntityManager();
+ em.persist(driftNotSupportedType);
+ em.persist(driftNotSupportedResource);
+ }
+ });
+ }
+
+ @Test(dependsOnMethods = "createEntitiesThatDoNotSupportDrift",
+ expectedExceptions = EJBException.class,
+ expectedExceptionsMessageRegExp = ".*Cannot create drift definition.*type.*does not support drift management")
+ @InitDB(false)
+ public void doNotAllowDefinitionToBeCreatedForTypeThatDoesNotSupportDrift() {
+ DriftDefinition driftDef = new DriftDefinition(new Configuration());
+ driftDef.setName("test_typeDoesNotSupportDrift");
+ driftDef.setEnabled(true);
+ driftDef.setInterval(1800L);
+ driftDef.setDriftHandlingMode(normal);
+ driftDef.setBasedir(new DriftDefinition.BaseDirectory(fileSystem, "/foo/bar/test"));
+
+ driftMgr.updateDriftDefinition(getOverlord(), EntityContext.forResource(driftNotSupportedResource.getId()),
+ driftDef);
+ }
+
@SuppressWarnings("unchecked")
public void createDefinitionFromPinnedTemplate() throws Exception {
// We first need to create a pinned template. Users can only create a pinned
@@ -209,8 +263,19 @@ public class ManageDriftDefinitionsTest extends DriftServerTest {
}
public void unpinDefinition() {
+ // First create the template
+ final DriftDefinition templateDef = new DriftDefinition(new Configuration());
+ templateDef.setName("test_unpin_def_template");
+ templateDef.setEnabled(true);
+ templateDef.setDriftHandlingMode(normal);
+ templateDef.setInterval(2400L);
+ templateDef.setBasedir(new DriftDefinition.BaseDirectory(fileSystem, "/foo/bar/test"));
+
+ final DriftDefinitionTemplate template = templateMgr.createTemplate(getOverlord(), resourceType.getId(), true,
+ templateDef);
+
// First create the definition
- DriftDefinition definition = new DriftDefinition(new Configuration());
+ DriftDefinition definition = template.createDefinition();
definition.setName("test_unpin");
definition.setEnabled(true);
definition.setBasedir(new DriftDefinition.BaseDirectory(fileSystem, "/foo/bar/test"));
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerBean.java
index 12c7233..3da8bd2 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerBean.java
@@ -18,73 +18,25 @@
*/
package org.rhq.enterprise.server.drift;
-import static java.util.Arrays.asList;
-import static javax.ejb.TransactionAttributeType.NOT_SUPPORTED;
-import static javax.ejb.TransactionAttributeType.REQUIRES_NEW;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
-import static org.rhq.core.domain.drift.DriftComplianceStatus.IN_COMPLIANCE;
-import static org.rhq.core.domain.drift.DriftComplianceStatus.OUT_OF_COMPLIANCE_DRIFT;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.ejb.EJB;
-import javax.ejb.Stateless;
-import javax.ejb.TransactionAttribute;
-import javax.jms.Connection;
-import javax.jms.ConnectionFactory;
-import javax.jms.MessageProducer;
-import javax.jms.ObjectMessage;
-import javax.jms.Queue;
-import javax.jms.Session;
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-
import difflib.DiffUtils;
import difflib.Patch;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Hibernate;
-
import org.jboss.remoting.CannotConnectException;
-
import org.rhq.core.clientapi.agent.drift.DriftAgentService;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.common.EntityContext;
-import org.rhq.core.domain.criteria.DriftChangeSetCriteria;
-import org.rhq.core.domain.criteria.DriftCriteria;
-import org.rhq.core.domain.criteria.DriftDefinitionCriteria;
-import org.rhq.core.domain.criteria.GenericDriftChangeSetCriteria;
-import org.rhq.core.domain.criteria.GenericDriftCriteria;
-import org.rhq.core.domain.drift.Drift;
-import org.rhq.core.domain.drift.DriftCategory;
-import org.rhq.core.domain.drift.DriftChangeSet;
-import org.rhq.core.domain.drift.DriftChangeSetCategory;
-import org.rhq.core.domain.drift.DriftComplianceStatus;
-import org.rhq.core.domain.drift.DriftComposite;
-import org.rhq.core.domain.drift.DriftConfigurationDefinition;
+import org.rhq.core.domain.criteria.*;
+import org.rhq.core.domain.drift.*;
import org.rhq.core.domain.drift.DriftConfigurationDefinition.DriftHandlingMode;
-import org.rhq.core.domain.drift.DriftDefinition;
import org.rhq.core.domain.drift.DriftDefinition.BaseDirectory;
-import org.rhq.core.domain.drift.DriftDefinitionComparator;
import org.rhq.core.domain.drift.DriftDefinitionComparator.CompareMode;
-import org.rhq.core.domain.drift.DriftDefinitionComposite;
-import org.rhq.core.domain.drift.DriftDefinitionTemplate;
-import org.rhq.core.domain.drift.DriftDetails;
-import org.rhq.core.domain.drift.DriftFile;
-import org.rhq.core.domain.drift.DriftSnapshot;
-import org.rhq.core.domain.drift.DriftSnapshotRequest;
-import org.rhq.core.domain.drift.FileDiffReport;
-import org.rhq.core.domain.drift.Filter;
import org.rhq.core.domain.drift.dto.DriftChangeSetDTO;
import org.rhq.core.domain.drift.dto.DriftDTO;
import org.rhq.core.domain.drift.dto.DriftFileDTO;
import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.PageOrdering;
@@ -103,6 +55,28 @@ import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
import org.rhq.enterprise.server.util.CriteriaQueryRunner;
import org.rhq.enterprise.server.util.LookupUtil;
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+import javax.ejb.TransactionAttribute;
+import javax.jms.*;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import java.io.File;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+import static javax.ejb.TransactionAttributeType.NOT_SUPPORTED;
+import static javax.ejb.TransactionAttributeType.REQUIRES_NEW;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
+import static org.rhq.core.domain.drift.DriftComplianceStatus.IN_COMPLIANCE;
+import static org.rhq.core.domain.drift.DriftComplianceStatus.OUT_OF_COMPLIANCE_DRIFT;
+
+import java.lang.IllegalStateException;
+
/**
* The SLSB supporting Drift management to clients.
*
@@ -716,7 +690,6 @@ public class DriftManagerBean implements DriftManagerLocal, DriftManagerRemote {
@Override
public void updateDriftDefinition(Subject subject, EntityContext entityContext, DriftDefinition driftDef) {
-
// before we do anything, validate certain field values to prevent downstream errors
validateDriftDefinition(driftDef);
@@ -728,6 +701,11 @@ public class DriftManagerBean implements DriftManagerLocal, DriftManagerRemote {
throw new IllegalArgumentException("Entity not found [" + entityContext + "]");
}
+ if (!isDriftMgmtSupported(resource)) {
+ throw new IllegalArgumentException("Cannot create drift definition. The resource type " +
+ resource.getResourceType() + " does not support drift management");
+ }
+
// Update or add the driftDef as necessary
DriftDefinitionComparator comparator = new DriftDefinitionComparator(
CompareMode.ONLY_DIRECTORY_SPECIFICATIONS);
@@ -752,6 +730,7 @@ public class DriftManagerBean implements DriftManagerLocal, DriftManagerRemote {
}
if (!isUpdated) {
+ validateTemplateForNewDef(driftDef, resource);
resource.addDriftDefinition(driftDef);
// We call persist here because if this definition is created
// from a pinned template, then we need to generate the initial
@@ -826,6 +805,32 @@ public class DriftManagerBean implements DriftManagerLocal, DriftManagerRemote {
}
}
+ private boolean isDriftMgmtSupported(Resource resource) {
+ ResourceType type = resource.getResourceType();
+ return type.getDriftDefinitionTemplates() != null && !type.getDriftDefinitionTemplates().isEmpty();
+ }
+
+ private void validateTemplateForNewDef(DriftDefinition driftDef, Resource resource) {
+ if (driftDef.getTemplate() == null) {
+ return;
+ }
+
+ DriftDefinitionTemplate template = entityManager.find(DriftDefinitionTemplate.class,
+ driftDef.getTemplate().getId());
+
+ if (template == null) {
+ throw new IllegalArgumentException("Cannot create drift definition with template " +
+ DriftDefinitionTemplate.class.getSimpleName() + "[" + driftDef.getTemplate().getName() +
+ "] that has not been saved");
+ }
+
+ if (!template.getResourceType().equals(resource.getResourceType())) {
+ throw new IllegalArgumentException("Cannot create drift definition with template " +
+ DriftDefinitionTemplate.class.getSimpleName() + "[" + driftDef.getTemplate().getName() +
+ "] that is from a different resource type, " + template.getResourceType());
+ }
+ }
+
@Override
public boolean isBinaryFile(Subject subject, Drift<?, ?> drift) {
return DriftUtil.isBinaryFile(drift);
commit 95df570457b745fc77231ea8ffa86ac82b6063e4
Author: Fusayuki Minamoto <fminamot(a)redhat.com>
Date: Mon Dec 19 10:19:02 2011 +0100
Translate remaining properties
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 67d4a7f..41a33be 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
@@ -425,7 +425,7 @@ view_adminRoles_permissions_permDesc_manageBundles = (誰でも閲覧可能な)
view_adminRoles_permissions_permDesc_manageInventory = すべてのリソースについて、以下に示すように、すべてのリソース権限を持ちます。つまり、グループの作成、更新、削除、そして自動検出された、または手動で検出されたリソースのインポートができます
view_adminRoles_permissions_permDesc_manageRepositories = (自分自身のリポジトリを作成可能な)ユーザーのリポジトリの作成、更新、削除が可能です。
view_adminRoles_permissions_permDesc_manageSecurity = (誰でも閲覧可能な)ユーザーとロールの作成、更新、削除
-## view_adminRoles_permissions_permDesc_manageSettings = RHQサーバー構成の修正と任意のサーバー関連の機能の実行ができます
+view_adminRoles_permissions_permDesc_manageSettings = {0}サーバーの修正と任意のサーバー関連の機能の実行ができます
view_adminRoles_permissions_permReadDesc_configure = リソース構成とリソース構成リビジョン履歴の閲覧
view_adminRoles_permissions_permReadDesc_control = 利用可能オペレーションとオペレーション実行履歴の(暗黙的な)閲覧
view_adminRoles_permissions_permReadDesc_createChildResources = (暗黙的な)子リソースの作成履歴の閲覧
@@ -496,30 +496,30 @@ view_admin_configuration = 構成
view_admin_content = コンテント
view_admin_downloads_agentDownload = エージェントのダウンロード
view_admin_downloads_agent_buildNumber = エージェントビルド
-## view_admin_downloads_agent_help = <p> これはRHQ Agentの更新バイナリJARファイルです。このJARファイルの目的はユーザーがエージェントがまだ存在しないマシン上に新しいエージェントをインストールできるようにすることと、すでにインストール済みのエージェントを更新できるようにするためです。詳細は、このエージェントダウンロードJARで次のように--helpコマンドラインオプションをつけて実行してください。<br/> <b>java -jar <agent-download.jar> --help</b> </p> <h3>エージェントのインストール</h3> <p> <b>java -jar <agent-download.jar> --install[=<新しいエージェントディレクトリ>]</b><br/> このコマンドは新しいエージェントをインストールします。もし新しいディレクトリを指定しなければ、デフォルトは"."となります。</p> <h3>エージェントの更新</h3> <p> <b>java -jar <agent-download.jar> --update[=<古いエージェントディレクトリ>]</b><br/> これはすでにインストールされた既存のエージェントを更新します。もし古い、既存のエージェントがインストールされたディレクトリを指定しなかったなら、"rhq-agent"が仮定されます。</p>
+view_admin_downloads_agent_help = <p> これは {0} Agentの更新バイナリJARファイルです。このJARファイルの目的はユーザーがエージェントがまだ存在しないマシン上に新しいエージェントをインストールできるようにすることと、すでにインストール済みのエージェントを更新できるようにするためです。詳細は、このエージェントダウンロードJARで次のように--helpコマンドラインオプションをつけて実行してください。<br/> <b>java -jar <agent-download.jar> --help</b> </p> <h3>エージェントのインストール</h3> <p> <b>java -jar <agent-download.jar> --install[=<新しいエージェントディレクトリ>]</b><br/> このコマンドは新しいエージェントをインストールします。もし新しいディレクトリを指定しなければ、デフォルトは"."となります。</p> <h3>エージェントの更新</h3> <p> <b>java -jar <agent-download.jar> --update[=<古いエージェントディレクトリ>]</b><br/> これはすでにインストールされた既存のエージェントを更新します。もし古い、既存のエージェントがインストールされたディレクトリを指定しなかったなら、"rhq-agent"が仮定されます。</p>
view_admin_downloads_agent_link_label = リンク
view_admin_downloads_agent_link_value = エージェント {0} ({1}) のダウンロード
view_admin_downloads_agent_loadError = エージェントバージョン情報が取得できません
view_admin_downloads_agent_md5 = エージェント MD5
view_admin_downloads_agent_version = エージェントバージョン
view_admin_downloads_bundleDownload = バンドルデプロイヤのダウンロード
-## view_admin_downloads_bundle_help = <p> これはバンドルデプロイヤツールで、開発者とRHQバンドルによって使われます。このスタンドアロンツールを使うとバンドルやコンソールからのレシピをテストできるようにします。</p>
+view_admin_downloads_bundle_help = <p> これはバンドルデプロイヤツールで、{0}バンドルの開発者とパッケージ開発者によって使われます。このスタンドアロンツールを使うとバンドルやコンソールからのレシピをテストできるようにします。</p>
view_admin_downloads_bundle_link_label = リンク
view_admin_downloads_bundle_link_value = バンドルデプロイヤー {0} をダウンロード
view_admin_downloads_bundle_loadError = バンドルデプロイヤー情報が取得できません
view_admin_downloads_cliDownload = コマンドラインクライアントのダウンロード
view_admin_downloads_cli_buildNumber = CLIビルド
-## view_admin_downloads_cli_help = <p> これはコマンドラインツールで、CLIとして知られているものです。コンソールから実行するスタンドアロンツールで、RHQサーバーに対してコマンドラインインタフェースを提供します。自動化されたタスクを実行するためにCLIやrunスクリプトを介してコマンドを呼び出すことが可能です。CLIのインストール方法と使い方についての詳細情報はドキュメントをご覧ください。</p>
+view_admin_downloads_cli_help = <p> これはコマンドラインツールで、CLIとして知られているものです。コンソールから実行するスタンドアロンツールで、{0}サーバーに対してコマンドラインインタフェースを提供します。自動化されたタスクを実行するためにCLIやrunスクリプトを介してコマンドを呼び出すことが可能です。CLIのインストール方法と使い方についての詳細情報はドキュメントをご覧ください。</p>
view_admin_downloads_cli_link_label = リンク
view_admin_downloads_cli_link_value = CLI {0} ({1}) をダウンロード
view_admin_downloads_cli_loadError = CLIバージョン情報が取得できません
view_admin_downloads_cli_md5 = CLI MD5
view_admin_downloads_cli_version = CLIバージョン
view_admin_downloads_connectorsDownload = コネクタのダウンロード
-## view_admin_downloads_connectors_help = コネクターは製品がRHQによって管理可能であるために必要となるソフトウェアです。RHQエージェントが通信できるように、管理製品にコネクターをインストールします。詳細はドキュメントをご覧ください。
+view_admin_downloads_connectors_help = コネクターは製品が{0}によって管理可能であるために必要となるソフトウェアです。RHQエージェントが通信できるように、管理製品にコネクターをインストールします。詳細はドキュメントをご覧ください。
view_admin_downloads_connectors_loadError = コネクター情報を取得できません
view_admin_downloads_connectors_none = ダウンロードのためのコネクターが見つかりません
-## view_admin_landing = このセクションにおいて、RHQグローバル設定が管理されます。これはセキュリティ構成、プラグイン設定、RHQサーバーとエージェントの管理を含みます。
+view_admin_landing = このセクションにおいて、{0}グローバル設定が管理されます。これはセキュリティ構成、プラグイン設定、RHQサーバーとエージェントの管理を含みます。
view_admin_measTemplates_updateExisting_title = 既存スケジュールの更新
view_admin_measTemplates_updateExisting_tooltip = このボックスをチェックすると、このタイプのすべてのリソースを対象に選択したメトリックスの収集スケジュールを更新します。もしこれがチェックされていなければ、テンプレートスケジュールが将来的にインベントリに追加されるこのタイプの新規リソースに適用されるだけです。
view_admin_plugins_agent = エージェント
@@ -1171,7 +1171,7 @@ view_dashboardManager_saved = ダッシュボード {0} をサーバーへ保存
view_dashboardManager_success = ダッシュボードを保存しました
view_dashboard_favorites_error1 = 好みのリソースをロードするのに失敗しました
view_dashboardsManager_error1 = 新しいダッシュボードを追加するのに失敗しました
-## view_dashboardsManager_message_title_details = <h1>RHQへようこそ</h1>\n<p>RHQプロジェクトは抽象化されたプラグインベースのシステム管理スイートで、複数のプロダクトやプラットフォームに対してコア機能を横断的に適用できる拡張可能で、統合化されたシステム管理を提供します。このプロジェクトはレイヤ化されたモジュールによって設計されていて、デプロイのための柔軟なアーキテクチャを提供します。それは企業全体に対する監査と履歴の管理を提供するコアとなるユーザーインタフェースを導入します。サーバー/エージェントアーキテクチャはリモートでの管理と特定プロダクトのサポートを実現するプラグインを提供します。 </p>\n <p>このデフォルトのダッシュボードは上の「編集モード」ボタンをすることで編集可能です。</p>
+view_dashboardsManager_message_title_details = <h1>{0}へようこそ</h1>\n<p>RHQプロジェクトは抽象化されたプラグインベースのシステム管理スイートで、複数のプロダクトやプラットフォームに対してコア機能を横断的に適用できる拡張可能で、統合化されたシステム管理を提供します。このプロジェクトはレイヤ化されたモジュールによって設計されていて、デプロイのための柔軟なアーキテクチャを提供します。それは企業全体に対する監査と履歴の管理を提供するコアとなるユーザーインタフェースを導入します。サーバー/エージェントアーキテクチャはリモートでの管理と特定プロダクトのサポートを実現するプラグインを提供します。 </p>\n <p>このデフォルトのダッシュボードは上の「編集モード」ボタンをすることで編集可能です。</p>
view_dashboards_confirm1 = 削除してもよろしいですか
view_dashboards_portlets_refresh_fail1 = 自動リフレッシュするポートレットのリフレッシュ間隔の更新に失敗しました
view_dashboards_portlets_refresh_fail2 = 自動リフレッシュするポートレットのリロードの無効化に失敗しました
@@ -1341,10 +1341,10 @@ view_groupConfigEdit_tooltip_1 = メンバー値の違い - 編集するため
view_groupConfigEdit_unset = 設定解除
view_groupConfigEdit_valsDiff = メンバー値の違い
view_groupConfigEdit_valsDiffForProp = プロパティ [{0}] のためのメンバー値
-## view_groupCreateWizard_createFailure = リソースグループの作成に失敗しました
+view_groupCreateWizard_createFailure = リソースグループ [{0}] の作成に失敗しました : {1}
view_groupCreateWizard_createStepName = グループ設定
view_groupCreateWizard_createStep_recursive = 再帰
-## view_groupCreateWizard_createSuccessful_concise = 新規のリソースグループを作成しました。
+view_groupCreateWizard_createSuccessful_concise = [{0}] という名前の新規のリソースグループを作成しました。
view_groupCreateWizard_createSuccessful_full = [{2}] メンバーリソースを含む 名前 [{1}] の新規 [{0}] リソースグループを作成しました。
view_groupCreateWizard_membersStepName = メンバーの選択
view_groupCreateWizard_title = グループ作成
@@ -1505,7 +1505,7 @@ view_login_prompt = ログインしてください
view_login_registerLater = (キャンセル - 登録を後で完成させてください)
view_login_registerLdapSuccess = 新しいLDAPユーザーの登録に成功しました
view_login_registerUser = ユーザの登録
-## view_login_welcomeMsg = RHQへようこそ! <br/><br/> 登録を完成させるために次のフィールドを入力/更新してください。<br/> "OK"をクリックしたら、ログインします。<br/><br/>
+view_login_welcomeMsg = {0}へようこそ! <br/><br/> 登録を完成させるために次のフィールドを入力/更新してください。<br/> "OK"をクリックしたら、ログインします。<br/><br/>
view_measureRange_last = 時間の範囲 - 直前
view_measureRange_simple = シンプル...
view_measureRange_start = 時間の範囲 - 開始
@@ -1545,7 +1545,7 @@ view_operationScheduleDetails_enterParametersBelow = 以下にパラメーター
view_operationScheduleDetails_fieldDefault_description = 説明を見るとためオペレーションを選択してください
view_operationScheduleDetails_fieldDefault_parameters = パラメーターを見るためにオペレーションを選択してください
view_operationScheduleDetails_fieldHelp_description = このスケジュールされたオペレーションのための任意の説明 (例、夜間保守のためのアプリサーバー再起動)
-## view_operationScheduleDetails_fieldHelp_timeout = 時間間隔 - もし指定されていて、その間隔がスケジュールされたオペレーション実行が完了する前に経過してしまったならば、RHQサーバーはそのオペレーションをタイムアウトにし、それを失敗させることを検討します。注意:通常はすでに開始させられた根本の管理リソースオペレーションをアボートすることは不可能です。
+view_operationScheduleDetails_fieldHelp_timeout = 時間間隔 - もし指定されていて、その間隔がスケジュールされたオペレーション実行が完了する前に経過してしまったならば、{0} サーバーはそのオペレーションをタイムアウトにし、それを失敗させることを検討します。注意:通常はすでに開始させられた根本の管理リソースオペレーションをアボートすることは不可能です。
view_operationScheduleDetails_field_description = 説明
view_operationScheduleDetails_field_parameters = パラメーター
view_operationScheduleDetails_field_timeout = タイムアウト
@@ -1919,7 +1919,7 @@ widget_resourceFactoryWizard_infoStepName = リソース情報
widget_resourceFactoryWizard_infoStep_loadFail = アーキテクチャーを利用可能にするのに失敗しました
widget_resourceFactoryWizard_namePrompt = 新規リソース名
widget_resourceFactoryWizard_templatePrompt = コネクション設定テンプレート
-## widget_resourceFactoryWizard_timeoutHelp = タイムアウト間隔。もし指定されたならば(RHQエージェント上での)子のリソース作成のためのデフォルトタイムアウトを上書きします。大きなアプリケーションのデプロイのような長時間かかる作成アクションに特に有用です。通常、前回の試みのときにタイムアウトの失敗だった場合に使われます。
+widget_resourceFactoryWizard_timeoutHelp = タイムアウト間隔。もし指定されたならば({0}エージェント上での)子のリソース作成のためのデフォルトタイムアウトを上書きします。大きなアプリケーションのデプロイのような長時間かかる作成アクションに特に有用です。通常、前回の試みのときにタイムアウトの失敗だった場合に使われます。
widget_resourceFactoryWizard_uploadFailure = ファイルアップロードの失敗
widget_resourceFactoryWizard_uploadFileStepName = リソースコンテントファイルのアップロード
widget_resourceFactoryWizard_uploadInProgress = アップロードは処理中です... 大きなファイルを配布するには数分かかることもあります。
commit 227c63ec1caf645f19173e1e39b588b5b112ca4a
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Dec 16 17:34:31 2011 -0500
eclipse tool to build for both FF and chrome
diff --git a/etc/eclipse-tools/maven/RHQ Maven Build - Dev Profile Web UI Only (GWT) (FF,Chrome).launch b/etc/eclipse-tools/maven/RHQ Maven Build - Dev Profile Web UI Only (GWT) (FF,Chrome).launch
new file mode 100644
index 0000000..9fcb8fb
--- /dev/null
+++ b/etc/eclipse-tools/maven/RHQ Maven Build - Dev Profile Web UI Only (GWT) (FF,Chrome).launch
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
+<stringAttribute key="bad_container_name" value="\rhq\etc\eclipse-tools\maven"/>
+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${env_var:M2_HOME}/bin/${MAVEN_EXE}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-o -Dgwt.userAgent=gecko1_8,safari -Dmaven.test.skip=true -Pdev gwt:clean install"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/rhq/modules/enterprise/gui/coregui}"/>
+</launchConfiguration>
commit 14256b6e778bbb02703dd82e1804f69d2b639f64
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri Dec 16 16:18:03 2011 -0500
[Bug 535538 - (RHQ-2222) Installer: db "Test Connection" button clears password field]
An attempt to improve the situation by alerting the user, and not processing
"Test Connection" or "Install Server!" buttons, if the password field
is empty.
- Note, the message displayed is in English since I'm not proficient enough
to figure out how to get javascript to interact with the resource bundle.
diff --git a/modules/enterprise/gui/installer-war/src/main/webapp/start.jsp b/modules/enterprise/gui/installer-war/src/main/webapp/start.jsp
index c9aee8f..ad0219e 100644
--- a/modules/enterprise/gui/installer-war/src/main/webapp/start.jsp
+++ b/modules/enterprise/gui/installer-war/src/main/webapp/start.jsp
@@ -4,6 +4,7 @@
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
<f:view>
<f:loadBundle var="bundle" basename="InstallerMessages" />
@@ -19,6 +20,13 @@
var thisDiv = document.getElementById( _levelId );
thisDiv.style.display = "block";
}
+ function checkForPassword() {
+ if ( document.getElementById('propForm:databasepassword').value == '' ) {
+ alert("Please enter database password.");
+ return false;
+ }
+ return true;
+ }
</script>
</head>
@@ -144,6 +152,7 @@
<h:outputText value="#{bundle.testDatabaseNote}" style="font-size: 100%"/>
<h:panelGrid columns="2">
<h:commandButton id="testDatabaseButton"
+ onclick="if (!checkForPassword()) return false"
action="#{configurationBean.testConnection}"
value="#{bundle.testDatabaseButton}"/>
<h:panelGroup rendered="#{configurationBean.lastTest != null && configurationBean.lastTest != 'OK'}">
@@ -326,7 +335,11 @@
</tr></table>
--%>
<table border="1"><tr>
- <td><h:commandButton id="save" action="#{configurationBean.save}" value="#{bundle.save}" /></td>
+ <td><h:commandButton id="save"
+ onclick="if (!checkForPassword()) return false"
+ action="#{configurationBean.save}"
+ value="#{bundle.save}" />
+ </td>
</tr></table>
</p>
</h:form>
@@ -335,4 +348,4 @@
</html>
-</f:view>
\ No newline at end of file
+</f:view>
commit 8937a7db8b70b606ef0847dbb2b100ddcf2d89ee
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Fri Dec 16 09:18:45 2011 -0500
[BZ 760139] additionally modifying MeasurmentManager to always return non-null values even for erroneous runtime conditions.
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 c019cde..be408b5 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
@@ -421,17 +421,20 @@ public class MeasurementManager extends AgentService implements MeasurementAgent
// corresponding metric defs - one for the raw value and one for the derived per-minute value. There's no
// way to tell which value the caller wants. For now, it assumes the caller wants the raw value.
// (ips, 09/05/08)
+ // spinder 12/16/11. BZ 760139. Modified to return empty sets instead of 'null' even for erroneous conditions.
+ // Server side logging or erroneous runtime conditions still occurs, but callers to getRealTimeMeasurementValues
+ // won't have to additionally check for null values now. This is a safe and better pattern.
public Set<MeasurementData> getRealTimeMeasurementValue(int resourceId, List<MeasurementDataRequest> requests) {
if (requests.size() == 0) {
// There's no need to even call getValues() on the ResourceComponent if the list of metric names is empty.
return Collections.emptySet();
}
MeasurementFacet measurementFacet;
- ResourceContainer resourceContainer = PluginContainer.getInstance().getInventoryManager().getResourceContainer(
- resourceId);
+ ResourceContainer resourceContainer = PluginContainer.getInstance().getInventoryManager()
+ .getResourceContainer(resourceId);
if (resourceContainer == null) {
LOG.warn("Can not get resource container for resource with id " + resourceId);
- return null;
+ return Collections.emptySet();
}
Resource resource = resourceContainer.getResource();
ResourceType resourceType = resource.getResourceType();
@@ -443,7 +446,7 @@ public class MeasurementManager extends AgentService implements MeasurementAgent
FACET_METHOD_TIMEOUT, true, true);
} catch (Exception e) {
LOG.warn("Cannot get measurement facet for Resource [" + resourceId + "]. Cause: " + e);
- return null;
+ return Collections.emptySet();
}
MeasurementReport report = new MeasurementReport();
@@ -457,7 +460,7 @@ public class MeasurementManager extends AgentService implements MeasurementAgent
measurementFacet.getValues(report, allMeasurements);
} catch (Throwable t) {
LOG.error("Could not get measurement values", t);
- return null;
+ return Collections.emptySet();
}
Set<MeasurementData> values = new HashSet<MeasurementData>();
commit b07f2c488f9487b8e142955048e7b140bcb72172
Author: John Sanda <jsanda(a)redhat.com>
Date: Thu Dec 15 17:31:50 2011 -0500
A CLI script for generating random files
I put this together while doing perf testing for drift. This script
needs some updating and docs, but it is generally useful.
diff --git a/etc/cli-scripts/create_files.js b/etc/cli-scripts/create_files.js
new file mode 100644
index 0000000..b0a2bab
--- /dev/null
+++ b/etc/cli-scripts/create_files.js
@@ -0,0 +1,186 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+importPackage(java.io);
+
+/**
+ * The first argument is a string that specifies the base directory in which
+ * file sets will be generated.
+ *
+ * {
+ * basedir: '/drift/files',
+ * fileSets: [
+ * {numFiles: 500, size: 10, extension: 'jar', dir:}
+ * {numFiles: 750, size: 8, extension: 'jar', dir:}
+ * ]
+ * }
+ *
+ * @param basedir
+ * @param fileSpecs
+ */
+
+/**
+ *
+ * @param opts
+ * basedir:
+ * fileSets:
+ * dir
+ * dirLayout
+ * numDirectories
+ * numFiles
+ * size
+ * extension
+ */
+function createFiles(opts) {
+ var basedir = File(opts.basedir);
+ basedir.mkdirs();
+
+ for (var i = 0; i < opts.fileSets.length; ++i) {
+ var fileSetOpts = bindFileSetOpts(opts.fileSets[i], i);
+ var dir = File(basedir, fileSetOpts.dir);
+ dir.mkdir();
+
+ var getSize;
+
+ if (fileSetOpts.size.constructor == Array) {
+ var nextSize = 0;
+ getSize = function() {
+ return fileSetOpts.size[(nextSize++ % fileSetOpts.size.length)]
+ }
+ } else {
+ getSize = function() { return fileSetOpts.size; }
+ }
+
+ for (var j = 0; j < fileSetOpts.numFiles; ++j) {
+ createFile({
+ dir: dir.path,
+ name: j + '.' + fileSetOpts.extension,
+ size: getSize()
+ });
+ }
+ }
+}
+
+function bindFileSetOpts(options, index) {
+ var defaultOpts = {
+ dir: index,
+ dirLayout: 'single',
+ numDirectories: 1,
+ numFiles: 100,
+ size: 4,
+ extension: 'gen'
+ };
+
+ for (var optName in defaultOpts) {
+ if (typeof options[optName] === 'undefined') {
+ options[optName] = defaultOpts[optName];
+ }
+ }
+
+ return options;
+}
+
+function fileSets(num, createFileSet) {
+ var array = [];
+ for (var i = 0; i < num; ++i) {
+ array.push(createFileSet());
+ }
+ return array;
+}
+
+/**
+ * Takes a map of options that provide specifications for creating the file and
+ * writes a file to disk according to those specifications. Unless stated
+ * otherwise, each option should be specified as a string.
+ *
+ * @param opts A map of options that specify how the file is to be generated.
+ * dir: The directory in which the file should be created. (required)
+ * name: The file name (required)
+ * size: The file size which can be specified in bytes, kilobytes, megabytes
+ * or gigabytes, e.g., 10B, 10KB, 10MB, 10GB (required)
+ */
+function createFile(opts) {
+ var file = File(opts.dir, opts.name);
+ var random = java.util.Random();
+ var sizeObj = parseFileSize(opts.size);
+ var calcSize = fileSizeConverter(sizeObj.units);
+ var numBytes = calcSize(sizeObj.number);
+
+ withWriter(file, function(writer) {
+ for (var i = 0; i < numBytes; i++) {
+ writer.write(random.nextInt(128));
+ }
+ });
+}
+
+/**
+ * Parses the file size option into an object. The size argument is validated
+ * to ensure it has the proper format. An exception is thrown if the syntax is
+ * invalid.
+ *
+ * @param size The file size specified as a string. The format is an integer
+ * followed by the units where recognized units are bytes (B), kilobytes (KB),
+ * megabytes (MB), and gigabytes(GB). Here are some examples of legal values,
+ *
+ * 12B // 12 bytes
+ * 12KB // 12 kilobytes
+ * 12MB // 12 megabytes
+ * 12GB // 12 gigabytes
+ *
+ * @return An object that contains two properties - number and units. number is
+ * the integer portion of the size argument and units is the one or two character
+ * units abbreviation.
+ */
+function parseFileSize(size) {
+ var pattern = /^\d+(B|KB|MB|GB)$/;
+
+ if (!pattern.test(size)) {
+ throw 'Illegal Syntax: ' + size + ' - file size must be an integer followed by units ' +
+ 'which is one of B, KB, MB, GB';
+ }
+
+ var unitsIndex = size.search(/(B|KB|MB|GB)/);
+ return {number: size.substring(0, unitsIndex), units: size.substring(unitsIndex)};
+}
+
+function fileSizeConverter(units) {
+ var converters = {
+ 'B': function(size) { return size; },
+ 'KB': function(size) { return size * 1024; },
+ 'MB': function(size) { return size * 1024 * 1024; },
+ 'GB': function(size) { return size * 1024 * 1024 * 1024; }
+ }
+ return converters[units];
+}
+
+function withWriter(file, fn) {
+ var writer = BufferedWriter(FileWriter(file));
+ try {
+ fn(writer);
+ } finally {
+ writer.close();
+ }
+}
+
+if (typeof create != 'undefined') {
+ println('creating files...');
+ var defs = eval('(' + create + ');');
+ createFiles(defs);
+ println('finished');
+}
commit c0987558d5ccbb366bf78e26c27400d02d53405c
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Dec 15 16:27:55 2011 -0500
Fix compilation isue after merge.
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
index c3aa13c..0d878a5 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
@@ -70,7 +70,7 @@ public class DriftFilesSenderTest extends DriftTest {
Headers headers = createHeaders(driftDefName, COVERAGE);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), headers);
- writer.write(addedFileEntry("server.conf", serverConfHash));
+ writer.write(addedFileEntry("server.conf", serverConfHash, serverConf.lastModified(), serverConf.length()));
writer.close();
sender.setDriftFiles(driftFiles(serverConfHash));
@@ -198,7 +198,8 @@ public class DriftFilesSenderTest extends DriftTest {
Headers headers = createHeaders(driftDefName, COVERAGE);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), headers);
- writer.write(addedFileEntry("conf/server.conf", serverConfHash));
+ writer
+ .write(addedFileEntry("conf/server.conf", serverConfHash, serverConf.lastModified(), serverConf.length()));
writer.close();
serverConf.delete();
commit cf001e9bc410896e57b7767164711fd8f819ccd8
Author: John Sanda <jsanda(a)redhat.com>
Date: Thu Dec 15 16:00:57 2011 -0500
DBInstallationTest needs to use its own dedicated database
DBInstallationTest runs through several database upgrades and it has
been using the same database as other tests on a jenkins build. This bug
probably goes back to the initial implementation. It wasn't a problem
previously because most if not all tests run before DBInstallationTest.
To avoid causing interference with other tests, it should use its own
dedicated database. This commit includes a fix for postgresql but not
for oracle. Oracle will have to be addressed separately.
diff --git a/modules/enterprise/gui/installer-war/pom.xml b/modules/enterprise/gui/installer-war/pom.xml
index 7f79832..bd1474a 100644
--- a/modules/enterprise/gui/installer-war/pom.xml
+++ b/modules/enterprise/gui/installer-war/pom.xml
@@ -35,6 +35,8 @@
<product.help.guide.agent>Running+the+RHQ+Agent</product.help.guide.agent>
<product.help.FAQ>FAQ</product.help.FAQ>
<product.help.config.props>http://support.rhq-project.org/display/JOPR2/Startup+Properties#Configuri...</product.help.config.props>
+
+ <rhq.db.installation.test.db-name>rhq_installer_test_db</rhq.db.installation.test.db-name>
</properties>
<dependencies>
@@ -149,6 +151,8 @@
<rhq.db.admin.password>${rhq.db.admin.password}</rhq.db.admin.password>
<rhq.test.ds.user-name>${rhq.test.ds.user-name}</rhq.test.ds.user-name>
<rhq.test.ds.password>${rhq.test.ds.password}</rhq.test.ds.password>
+ <rhq.db.installation.test.db-name>${rhq.db.installation.test.db-name}</rhq.db.installation.test.db-name>
+ <rhq.db.installation.test.connection-url>jdbc:postgresql://${rhq.test.ds.server-name}:5432/${rhq.db.installation.test.db-name}</rhq.db.installation.test.connection-url>
</systemPropertyVariables>
</configuration>
</plugin>
diff --git a/modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallationTest.java b/modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallationTest.java
index 6633cb7..3bff054 100644
--- a/modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallationTest.java
+++ b/modules/enterprise/gui/installer-war/src/test/java/org/rhq/enterprise/installer/DBInstallationTest.java
@@ -23,17 +23,14 @@
package org.rhq.enterprise.installer;
-import java.io.File;
-import java.net.URL;
-import java.util.Properties;
-
+import org.rhq.core.db.reset.DBReset;
+import org.rhq.core.db.setup.DBSetup;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import org.rhq.core.db.reset.DBReset;
-import org.rhq.core.db.setup.DBSetup;
-import org.rhq.enterprise.installer.ServerInformation;
-import org.rhq.enterprise.installer.ServerProperties;
+import java.io.File;
+import java.net.URL;
+import java.util.Properties;
/**
* The tests in this class exercise the dbsetup/dbupgrade code that is run in the installer. The tests currently only
@@ -46,12 +43,12 @@ import org.rhq.enterprise.installer.ServerProperties;
public class DBInstallationTest {
private final String LOG_DIRECTORY = System.getProperty("java.io.tmpdir", "rhq/installer-test");
- private final String DB_NAME = System.getProperty("rhq.test.ds.db-name", "rhq_installer_test_db");
+ private final String DB_NAME = System.getProperty("rhq.db.installation.test.db-name", "rhq_installer_test_db");
private final String USERNAME = System.getProperty("rhq.test.ds.user-name", "rhqadmin");
private final String PASSWORD = System.getProperty("rhq.test.ds.password", "rhqadmin");
private final String SERVER = System.getProperty("rhq.test.ds.server-name", "127.0.0.1");
- private final String DB_URL = System.getProperty("rhq.test.ds.connection-url", "jdbc:postgresql://" + SERVER
- + ":5432/" + DB_NAME);
+ private final String DB_URL = System.getProperty("rhq.db.installation.test.connection-url",
+ "jdbc:postgresql://" + SERVER + ":5432/" + DB_NAME);
private final String ADMIN_USERNAME = System.getProperty("rhq.db.admin.username", "postgres");
private final String ADMIN_PASSWORD = System.getProperty("rhq.db.admin.password", "postgres");
private static final String DB_TYPE_MAPPING = System.getProperty("rhq.test.ds.type-mapping", "PostgreSQL");
commit 260fbda7005ebd20b436c55eca4dd07f8c803d31
Merge: 6e70db5 638de1b
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Dec 15 13:38:47 2011 -0500
Merge branch 'jsanda/drift'
Conflicts:
modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
diff --cc modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
index d427229,b102300..c3aa13c
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
@@@ -19,29 -19,23 +19,30 @@@
package org.rhq.core.pc.drift;
- import org.rhq.common.drift.ChangeSetWriter;
- import org.rhq.common.drift.Headers;
- import org.rhq.core.domain.drift.DriftChangeSetCategory;
- import org.rhq.core.domain.drift.DriftFile;
- import org.rhq.core.domain.drift.JPADriftFile;
- import org.rhq.core.util.ZipUtil;
- import org.rhq.test.AssertUtils;
- import org.testng.annotations.BeforeMethod;
- import org.testng.annotations.Test;
+ import static org.rhq.common.drift.FileEntry.addedFileEntry;
+ import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
+ import static org.testng.Assert.assertEquals;
+ import static org.testng.Assert.assertTrue;
import java.io.File;
+import java.io.FilenameFilter;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
- import static org.rhq.common.drift.FileEntry.addedFileEntry;
- import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
- import static org.testng.Assert.assertEquals;
- import static org.testng.Assert.assertTrue;
+ import org.testng.annotations.BeforeMethod;
+ import org.testng.annotations.Test;
+
+ import org.rhq.common.drift.ChangeSetWriter;
+ import org.rhq.common.drift.Headers;
+ import org.rhq.core.domain.drift.DriftChangeSetCategory;
+ import org.rhq.core.domain.drift.DriftFile;
+ import org.rhq.core.domain.drift.JPADriftFile;
++import org.rhq.core.util.ZipUtil;
++import org.rhq.test.AssertUtils;
public class DriftFilesSenderTest extends DriftTest {
@@@ -96,8 -69,10 +97,10 @@@
Headers headers = createHeaders(driftDefName, COVERAGE);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), headers);
- writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash));
- writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash));
- writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash, server1Conf.lastModified(),
- server1Conf.length()));
- writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash, server2Conf.lastModified(),
- server2Conf.length()));
++ writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash, server1Conf.lastModified(), server1Conf
++ .length()));
++ writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash, server2Conf.lastModified(), server2Conf
++ .length()));
writer.close();
sender.setDriftFiles(driftFiles(server1ConfHash, server2ConfHash));
@@@ -129,10 -107,14 +132,14 @@@
Headers headers = createHeaders(driftDefName, COVERAGE);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), headers);
- writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash));
- writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash));
- writer.write(addedFileEntry("lib/server-1.jar", server1JarHash));
- writer.write(addedFileEntry("lib/server-2.jar", server2JarHash));
- writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash, server1Conf.lastModified(),
- server1Conf.length()));
- writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash, server2Conf.lastModified(),
- server2Conf.length()));
- writer.write(addedFileEntry("lib/server-1.jar", server1JarHash, server1Jar.lastModified(),
- server1Jar.length()));
- writer.write(addedFileEntry("lib/server-2.jar", server2JarHash, server2Jar.lastModified(),
- server2Jar.length()));
++ writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash, server1Conf.lastModified(), server1Conf
++ .length()));
++ writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash, server2Conf.lastModified(), server2Conf
++ .length()));
++ writer
++ .write(addedFileEntry("lib/server-1.jar", server1JarHash, server1Jar.lastModified(), server1Jar.length()));
++ writer
++ .write(addedFileEntry("lib/server-2.jar", server2JarHash, server2Jar.lastModified(), server2Jar.length()));
writer.close();
// Note that the order of the drift files is random. When the server sends a request
@@@ -161,77 -148,25 +168,78 @@@
Headers headers = createHeaders(driftDefName, COVERAGE);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), headers);
- writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash));
- writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash));
- writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash, server1Conf.lastModified(),
- server1Conf.length()));
- writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash, server2Conf.lastModified(),
- server2Conf.length()));
++ writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash, server1Conf.lastModified(), server1Conf
++ .length()));
++ writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash, server2Conf.lastModified(), server2Conf
++ .length()));
writer.close();
// It is possible that the server can request a file that has been deleted since it
// it was initially detected during drift detection.
server1Conf.delete();
--
sender.setDriftFiles(driftFiles(server1ConfHash, server2ConfHash));
sender.setHeaders(headers);
sender.run();
- File contentDir = mkdir(changeSetDir, "content");
+ assertContentFileExists(changeSetDir);
+ assertContentFileMatches(changeSetDir, server2ConfHash);
+ }
+
+ @Test
- public void doNotSendEmptyZipFileToServer() throws Exception {
++ public void doNotSendEmptyZipFileToServer() throws Exception {
+ String driftDefName = "empty_content_test";
+
+ File confDir = mkdir(resourceDir, "conf");
+ File serverConf = createRandomFile(confDir, "server.conf");
+
+ String serverConfHash = sha256(serverConf);
+
+ Headers headers = createHeaders(driftDefName, COVERAGE);
+
+ ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), headers);
+ writer.write(addedFileEntry("conf/server.conf", serverConfHash));
+ writer.close();
+
+ serverConf.delete();
+
+ sender.setDriftFiles(driftFiles(serverConfHash));
+ sender.setHeaders(headers);
+ sender.run();
+
+ assertEquals(driftClient.getSendChangeSetContentInvocationCount(), 0,
- "Do not call DriftClient to send content to server when there is no content to send.");
++ "Do not call DriftClient to send content to server when there is no content to send.");
+ assertContentFileExists(changeSetDir(driftDefName));
+ }
+
+ void assertContentFileExists(File changeSetDir) {
+ File[] files = getContentFiles(changeSetDir);
+ assertEquals(files.length, 1, "Expected to find a single content zip file but found " + Arrays.toString(files));
+ }
+
+ void assertContentFileMatches(File changeSetDir, String... expectedFileNames) throws Exception {
+ File contentFile = getContentFiles(changeSetDir)[0];
+ final List<String> actualFileNames = new LinkedList<String>();
+
+ ZipUtil.walkZipFile(contentFile, new ZipUtil.ZipEntryVisitor() {
+ @Override
+ public boolean visit(ZipEntry entry, ZipInputStream stream) throws Exception {
+ actualFileNames.add(entry.getName());
+ return true;
+ }
+ });
+
+ AssertUtils.assertCollectionEqualsNoOrder(Arrays.asList(expectedFileNames), actualFileNames,
- "The content file " + contentFile.getPath() + " does not contain the correct entries");
++ "The content file " + contentFile.getPath() + " does not contain the correct entries");
+ }
- assertEquals(contentDir.list().length, 1, "Expected to find one file in " + contentDir.getAbsolutePath());
- assertFileCopiedToContentDir(contentDir, server2ConfHash);
+ private File[] getContentFiles(File changeSetDir) {
+ return changeSetDir.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.startsWith("content_") && name.endsWith(".zip");
+ }
+ });
}
/**
@@@ -245,8 -180,8 +253,8 @@@
*/
void assertFileCopiedToContentDir(File contentDir, String fileHash) {
File file = new File(contentDir, fileHash);
-- assertTrue(file.exists(), "Expected to find file named " + file.getName() + " in content directory " +
-- contentDir.getPath() + ". The SHA-256 hash should be used as the file name.");
++ assertTrue(file.exists(), "Expected to find file named " + file.getName() + " in content directory "
++ + contentDir.getPath() + ". The SHA-256 hash should be used as the file name.");
}
Headers createHeaders(String configName, DriftChangeSetCategory type) {
commit 638de1b71e5eb15b137ca2deda01299a30f5482c
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Dec 15 13:18:32 2011 -0500
[Bug 768031 - Pin template failure on upgraded dbs]
Set RHQ_DRIFT_CHANGE_SET.DRIFT_DEFINITION_ID nullable in the db upgrade.
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 9e3bbd6..24c536d 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -3826,7 +3826,10 @@
<schemaSpec version="2.117">
<!-- Remove an obsolete drift table that may be hanging around -->
- <schema-dropTable table="RHQ_DRIFT_TEMPLATE_MAP" />
+ <schema-dropTable table="RHQ_DRIFT_TEMPLATE_MAP" />
+
+ <!-- Remove an unwanted null consraint -->
+ <schema-alterColumn table="RHQ_DRIFT_CHANGE_SET" column="DRIFT_DEFINITION_ID" nullable="TRUE" />
</schemaSpec>
</dbupgrade>
commit 4da6f3724d6492ae449ea76100aac8d9948f6303
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Dec 15 13:16:59 2011 -0500
Supporting check-in for [Bug 768031 - Pin template failure on upgraded dbs]
- Fix a long standing issue in dbupgrade due to Oracle throwing exceptions
when trying to set nullable to the current value. In other words, the
upgrade would fail on oracle if you tried to set nullable false on a
column that was already nullable false. (same for nullable true). This
caused issues when you can't guarantee the current state, you just know
what you need it to be. Now, catch the relevant exceptions and toss
them as needed.
diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/OracleDatabaseType.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/OracleDatabaseType.java
index b4ea5e9..9dcbb89 100644
--- a/modules/core/dbutils/src/main/java/org/rhq/core/db/OracleDatabaseType.java
+++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/OracleDatabaseType.java
@@ -25,6 +25,8 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
+import mazz.i18n.Logger;
+
/**
* Superclass of all versions of the Oracle database.
*
@@ -32,6 +34,8 @@ import java.util.List;
*
*/
public abstract class OracleDatabaseType extends DatabaseType {
+ private static final Logger LOG = DbUtilsI18NFactory.getLogger(OracleDatabaseType.class);
+
/**
* The vendor name for all Oracle databases.
*/
@@ -150,7 +154,24 @@ public abstract class OracleDatabaseType extends DatabaseType {
sql += ")";
- executeSql(conn, sql);
+ try {
+ executeSql(conn, sql);
+ } catch (SQLException e) {
+ // Oracle throws an exception if you try to set nullable to its current setting. Ignore errors
+ // generated when a nullable setting is already the way we want it to be.
+ // ORA-01442: column to be modified to NOT NULL is already NOT NULL
+ // ORA-01451: column to be modified to NULL cannot be modified to NULL
+ if (nullable != null) {
+ String msg = e.getMessage();
+ if (msg.contains("ORA-01442") || msg.contains("ORA-01451")) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Ignoring exception, column already set to nullable=" + nullable, e);
+ }
+ } else {
+ throw e;
+ }
+ }
+ }
if ((reindex != null) && reindex.booleanValue()) {
reindexTable(conn, table);
commit 6e70db5abb0b3db8b93730c27695503a461f8f40
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Dec 14 18:07:25 2011 -0500
[BZ 765593] escape HTML in unified diff output (https://bugzilla.redhat.com/show_bug.cgi?id=765593)
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java
index b3de83f..d7477af 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java
@@ -20,17 +20,13 @@ package org.rhq.enterprise.gui.coregui.client.drift;
import java.util.ArrayList;
import java.util.LinkedHashMap;
-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.widgets.Canvas;
-import com.smartgwt.client.widgets.form.DynamicForm;
-import com.smartgwt.client.widgets.form.fields.CanvasItem;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
-import com.smartgwt.client.widgets.layout.VLayout;
import org.rhq.core.domain.common.EntityContext;
import org.rhq.core.domain.criteria.DriftDefinitionCriteria;
@@ -45,12 +41,12 @@ import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.DetailsView;
import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.LinkManager;
-import org.rhq.enterprise.gui.coregui.client.PopupWindow;
import org.rhq.enterprise.gui.coregui.client.ViewPath;
import org.rhq.enterprise.gui.coregui.client.components.buttons.BackButton;
import org.rhq.enterprise.gui.coregui.client.components.carousel.BookmarkableCarousel;
import org.rhq.enterprise.gui.coregui.client.components.form.EnumSelectItem;
import org.rhq.enterprise.gui.coregui.client.drift.DriftCarouselMemberView.DriftSelectionListener;
+import org.rhq.enterprise.gui.coregui.client.drift.util.DiffUtility;
import org.rhq.enterprise.gui.coregui.client.gwt.DriftGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
@@ -266,7 +262,6 @@ public class DriftCarouselView extends BookmarkableCarousel implements DetailsVi
addCarouselAction("Compare", MSG.common_button_compare(), null, new CarouselAction() {
public void executeAction(Object actionValue) {
-
Record record1 = selectedRecords.get(0);
Record record2 = selectedRecords.get(1);
final String path = record1.getAttribute(DriftDataSource.ATTR_PATH);
@@ -280,68 +275,16 @@ public class DriftCarouselView extends BookmarkableCarousel implements DetailsVi
GWTServiceLookup.getDriftService().generateUnifiedDiffByIds(diffOldId, diffNewId,
new AsyncCallback<FileDiffReport>() {
- @Override
public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError("Failed to generate diff", caught);
+ CoreGUI.getErrorHandler().handleError("Failed to generate diff.", caught);
}
- @Override
public void onSuccess(FileDiffReport diffReport) {
- String diffContents = toHtml(diffReport.getDiff(), 1, 2);
- LocatableWindow window = createDiffViewer(diffContents, path, 1, 2);
+ String diffContents = DiffUtility.formatAsHtml(diffReport.getDiff(), 1, 2);
+ LocatableWindow window = DiffUtility.createDiffViewerWindow(diffContents, path, 1, 2);
window.show();
}
-
- private String toHtml(List<String> deltas, int oldVersion, int newVersion) {
- StringBuilder diff = new StringBuilder();
- diff.append("<font color=\"red\">").append(deltas.get(0)).append(":").append(oldVersion)
- .append("</font><br/>");
- diff.append("<font color=\"green\">").append(deltas.get(1)).append(":").append(newVersion)
- .append("</font><br/>");
-
- for (String line : deltas.subList(2, deltas.size())) {
- if (line.startsWith("@@")) {
- diff.append("<font color=\"purple\">").append(line).append("</font><br/>");
- } else if (line.startsWith("-")) {
- diff.append("<font color=\"red\">").append(line).append("</font><br/>");
- } else if (line.startsWith("+")) {
- diff.append("<font color=\"green\">").append(line).append("</font><br/>");
- } else {
- diff.append(line).append("<br/>");
- }
- }
- return diff.toString();
- }
-
- private LocatableWindow createDiffViewer(String contents, String path, int oldVersion,
- int newVersion) {
- VLayout layout = new VLayout();
- DynamicForm form = new DynamicForm();
- form.setWidth100();
- form.setHeight100();
-
- CanvasItem canvasItem = new CanvasItem();
- canvasItem.setColSpan(2);
- canvasItem.setShowTitle(false);
- canvasItem.setWidth("*");
- canvasItem.setHeight("*");
-
- Canvas canvas = new Canvas();
- canvas.setContents(contents);
- canvasItem.setCanvas(canvas);
-
- form.setItems(canvasItem);
- layout.addMember(form);
-
- PopupWindow window = new PopupWindow("diffViewer", layout);
- window.setTitle(path + ":" + oldVersion + ":" + newVersion);
- window.setIsModal(false);
-
- return window;
- }
-
});
-
}
public boolean isEnabled() {
@@ -354,6 +297,7 @@ public class DriftCarouselView extends BookmarkableCarousel implements DetailsVi
return false;
}
+
});
super.configureCarousel();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDetailsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDetailsView.java
index 0cd08a1..d359e6b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDetailsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDetailsView.java
@@ -47,6 +47,7 @@ import org.rhq.core.domain.drift.FileDiffReport;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.PopupWindow;
import org.rhq.enterprise.gui.coregui.client.components.table.TimestampCellFormatter;
+import org.rhq.enterprise.gui.coregui.client.drift.util.DiffUtility;
import org.rhq.enterprise.gui.coregui.client.gwt.DriftGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm;
@@ -286,51 +287,23 @@ public class DriftDetailsView extends LocatableVLayout {
return window;
}
- private LocatableWindow createDiffViewer(String contents, String path, int oldVersion, int newVersion) {
- VLayout layout = new VLayout();
- DynamicForm form = new DynamicForm();
- form.setWidth100();
- form.setHeight100();
-
- CanvasItem canvasItem = new CanvasItem();
- canvasItem.setColSpan(2);
- canvasItem.setShowTitle(false);
- canvasItem.setWidth("*");
- canvasItem.setHeight("*");
-
- Canvas canvas = new Canvas();
- canvas.setContents(contents);
- canvasItem.setCanvas(canvas);
-
- form.setItems(canvasItem);
- layout.addMember(form);
-
- PopupWindow window = new PopupWindow("diffViewer", layout);
- window.setTitle(path + ":" + oldVersion + ":" + newVersion);
- window.setIsModal(false);
-
- return window;
- }
-
private LinkItem createViewDiffLink(final Drift<?, ?> drift, final int oldVersion) {
LinkItem viewDiffLink = new LinkItem("viewDiff");
viewDiffLink.setLinkTitle("(view diff)");
viewDiffLink.setShowTitle(false);
viewDiffLink.addClickHandler(new ClickHandler() {
- @Override
public void onClick(ClickEvent clickEvent) {
GWTServiceLookup.getDriftService().generateUnifiedDiff(drift, new AsyncCallback<FileDiffReport>() {
- @Override
public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError("Failed to generate diff", caught);
+ CoreGUI.getErrorHandler().handleError("Failed to generate diff.", caught);
}
- @Override
public void onSuccess(FileDiffReport diffReport) {
int newVersion = drift.getChangeSet().getVersion();
- String diffContents = toHtml(diffReport.getDiff(), oldVersion, newVersion);
- LocatableWindow window = createDiffViewer(diffContents, drift.getPath(), oldVersion, newVersion);
+ String diffContents = DiffUtility.formatAsHtml(diffReport.getDiff(), oldVersion, newVersion);
+ LocatableWindow window = DiffUtility.createDiffViewerWindow(diffContents, drift.getPath(),
+ oldVersion, newVersion);
window.show();
}
});
@@ -339,24 +312,4 @@ public class DriftDetailsView extends LocatableVLayout {
return viewDiffLink;
}
- private String toHtml(List<String> deltas, int oldVersion, int newVersion) {
- StringBuilder diff = new StringBuilder();
- diff.append("<font color=\"red\">").append(deltas.get(0)).append(":").append(oldVersion).append("</font><br/>");
- diff.append("<font color=\"green\">").append(deltas.get(1)).append(":").append(newVersion).append(
- "</font><br/>");
-
- for (String line : deltas.subList(2, deltas.size())) {
- if (line.startsWith("@@")) {
- diff.append("<font color=\"purple\">").append(line).append("</font><br/>");
- } else if (line.startsWith("-")) {
- diff.append("<font color=\"red\">").append(line).append("</font><br/>");
- } else if (line.startsWith("+")) {
- diff.append("<font color=\"green\">").append(line).append("</font><br/>");
- } else {
- diff.append(line).append("<br/>");
- }
- }
- return diff.toString();
- }
-
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/util/DiffUtility.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/util/DiffUtility.java
new file mode 100644
index 0000000..dc3fbb0
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/util/DiffUtility.java
@@ -0,0 +1,112 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.drift.util;
+
+import java.util.List;
+
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.CanvasItem;
+import com.smartgwt.client.widgets.layout.VLayout;
+import org.rhq.enterprise.gui.coregui.client.PopupWindow;
+import org.rhq.enterprise.gui.coregui.client.util.StringUtility;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableWindow;
+
+/**
+ * A collection of utility methods for working with unified diffs.
+ */
+public class DiffUtility {
+
+ /**
+ * Formats the specified unified diff output as HTML.
+ *
+ * @param deltas
+ * @param oldVersion
+ * @param newVersion
+ *
+ * @return the specified unified diff output formatted as HTML
+ */
+ public static String formatAsHtml(List<String> deltas, int oldVersion, int newVersion) {
+ StringBuilder html = new StringBuilder();
+
+ String originalFilename = deltas.get(0);
+ html.append("<b>").append(StringUtility.escapeHtml(originalFilename)).
+ append(":").append(oldVersion).append("</b><br/>");
+ String revisedFilename = deltas.get(1);
+ html.append("<b>").append(StringUtility.escapeHtml(revisedFilename)).
+ append(":").append(newVersion).append("</b><br/>");
+
+ List<String> lines = deltas.subList(2, deltas.size());
+ for (String line : lines) {
+ String escapedLine = StringUtility.escapeHtml(line);
+ if (line.startsWith("@@")) {
+ html.append("<font color=\"blue\">").append(escapedLine).append("</font>");
+ } else if (line.startsWith("-")) {
+ html.append("<font color=\"red\">").append(escapedLine).append("</font>");
+ } else if (line.startsWith("+")) {
+ html.append("<font color=\"green\">").append(escapedLine).append("</font>");
+ } else {
+ html.append(escapedLine);
+ }
+ html.append("<br/>");
+ }
+
+ return html.toString();
+ }
+
+ /**
+ * Create a non-modal window containing unified diff HTML.
+ *
+ * @param contents
+ * @param path
+ * @param oldVersion
+ * @param newVersion
+ *
+ * @return a non-modal window containing unified diff HTML
+ */
+ public static LocatableWindow createDiffViewerWindow(String contents, String path, int oldVersion, int newVersion) {
+ VLayout layout = new VLayout();
+ DynamicForm form = new DynamicForm();
+ form.setWidth100();
+ form.setHeight100();
+
+ CanvasItem canvasItem = new CanvasItem();
+ canvasItem.setColSpan(2);
+ canvasItem.setShowTitle(false);
+ canvasItem.setWidth("*");
+ canvasItem.setHeight("*");
+
+ Canvas canvas = new Canvas();
+ canvas.setContents(contents);
+ canvasItem.setCanvas(canvas);
+
+ form.setItems(canvasItem);
+ layout.addMember(form);
+
+ PopupWindow window = new PopupWindow("diffViewer", layout);
+ window.setTitle(path + ":" + oldVersion + ":" + newVersion);
+ window.setIsModal(false);
+
+ return window;
+ }
+
+ private DiffUtility() {
+ }
+
+}
commit 9f18aee38ed44f992ce26e7f8141a057af716533
Author: John Sanda <jsanda(a)redhat.com>
Date: Wed Dec 14 20:59:56 2011 -0500
[BZ 767205] Only read snapshot file once when looking for content to send to server
With this commit DriftFilesSender now builds an index of the file
entries key offed of the SHA so that is can quickly find files without
having to repeatedly scan the snapshot file on disk.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftClient.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftClient.java
index 1649819..761b3df 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftClient.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftClient.java
@@ -24,7 +24,8 @@ public interface DriftClient {
* @param driftDefinitionName
* @param contentDir
*/
- void sendChangeSetContentToServer(int resourceId, String driftDefinitionName, File contentDir);
+ //void sendChangeSetContentToServer(int resourceId, String driftDefinitionName, File contentDir);
+ void sendChangeSetContentToServer(int resourceId, String driftDefName, File contentZipFile);
void repeatChangeSet(int resourceId, String driftDefName, int version);
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 4181472..59d3054 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
@@ -10,6 +10,10 @@ 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 {
@@ -47,41 +51,95 @@ public class DriftFilesSender implements Runnable {
@Override
public void run() {
+ ZipOutputStream stream = null;
try {
if (log.isInfoEnabled()) {
log.info("Preparing to send content to server for " + defToString());
}
-
+ long startTime = System.currentTimeMillis();
File changeSet = changeSetMgr.findChangeSet(resourceId, headers.getDriftDefinitionName());
- File contentDir = new File(changeSet.getParentFile(), "content");
- contentDir.mkdir();
-
- for (DriftFile driftFile : driftFiles) {
+ File changeSetDir = changeSet.getParentFile();
+
+ // Note that the content file has a specific format that the server
+ // expects. The file name is of the form content_<token>.zip where
+ // token is a unique string that the agent can use to identify the
+ // content zip file when the server sends an acknowledgement. The
+ // token is necessary because it is possible, albeit not likely,
+ // for a a particular definition to wind up with multiple content
+ // zip files and there is no guarantee that they will be acked in
+ // the order in which they were sent. The name of each file in the
+ // zip file should be the SHA for that file. The server uses that
+ // SHA to look up the DriftFile object it has already created for
+ // the content.
+ //
+ // jsanda
+
+ String timestamp = Long.toString(System.currentTimeMillis());
+ String contentFileName = "content_" + timestamp + ".zip";
+ final File zipFile = new File(changeSetDir, contentFileName);
+ stream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
+
+ if (driftFiles.size() == 1) {
+ DriftFile driftFile = driftFiles.get(0);
File file = find(driftFile);
if (file == null || !file.exists()) {
log.warn("Unable to find file for " + driftFile);
} else {
if (log.isDebugEnabled()) {
- log.debug("Copying " + file.getPath() + " to " + contentDir.getPath());
+ log.debug("Adding " + file.getPath() + " to " + contentFileName);
}
- StreamUtil.copy(new BufferedInputStream(new FileInputStream(file)), new BufferedOutputStream(
- new FileOutputStream(new File(contentDir, driftFile.getHashId()))), true);
- }
- }
-
- File[] content = contentDir.listFiles();
- if (content == null || content.length == 0) {
- if (log.isDebugEnabled()) {
- log.debug("Could not find any of the requested content for " + defToString());
+ addFileToContentZipFile(stream, driftFile, file);
}
} else {
- if (log.isDebugEnabled()) {
- log.debug("Sending " + content.length + " files to the server for " + defToString());
+ Map<String, FileEntry> fileEntries = createSnapshotIndex();
+
+ for (DriftFile driftFile : driftFiles) {
+ FileEntry entry = fileEntries.get(driftFile.getHashId());
+ if (entry == null) {
+ continue;
+ }
+ File file = new File(headers.getBasedir(), entry.getFile());
+ if (file == null || !file.exists()) {
+ log.warn("Unable to find file for " + driftFile);
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("Adding " + file.getPath() + " to " + contentFileName);
+ }
+ addFileToContentZipFile(stream, driftFile, file);
+ }
}
- driftClient.sendChangeSetContentToServer(resourceId, headers.getDriftDefinitionName(), contentDir);
}
+
+ 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) +
+ " ms");
+ }
+
} catch (IOException e) {
log.error("Failed to send drift files.", e);
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ private void addFileToContentZipFile(ZipOutputStream stream, DriftFile driftFile, File file) throws IOException {
+ FileInputStream fis = new FileInputStream(file);
+ try {
+ stream.putNextEntry(new ZipEntry(driftFile.getHashId()));
+ StreamUtil.copy(fis, stream, false);
+ } finally {
+ fis.close();
}
}
@@ -100,6 +158,19 @@ public class DriftFilesSender implements Runnable {
}
}
+ private Map<String, FileEntry> createSnapshotIndex() throws IOException {
+ ChangeSetReader reader = changeSetMgr.getChangeSetReader(resourceId, headers.getDriftDefinitionName());
+ try {
+ Map<String, FileEntry> map = new TreeMap<String, FileEntry>();
+ for (FileEntry entry : reader) {
+ map.put(entry.getNewSHA(), entry);
+ }
+ return map;
+ } finally {
+ reader.close();
+ }
+ }
+
private String defToString() {
return "[resourceId: " + resourceId + ", driftDefinitionId: " + headers.getDriftDefinitionId() +
", driftDefinitionName: " + headers.getDriftDefinitionName() + "]";
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 2790f13..3602267 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
@@ -19,30 +19,8 @@
package org.rhq.core.pc.drift;
-import static org.rhq.common.drift.FileEntry.addedFileEntry;
-import static org.rhq.common.drift.FileEntry.changedFileEntry;
-import static org.rhq.common.drift.FileEntry.removedFileEntry;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.DRIFT;
-import static org.rhq.core.domain.drift.DriftComplianceStatus.OUT_OF_COMPLIANCE_NO_BASEDIR;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.util.List;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-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.ChangeSetWriter;
import org.rhq.common.drift.Headers;
import org.rhq.core.clientapi.agent.drift.DriftAgentService;
@@ -63,6 +41,18 @@ import org.rhq.core.pc.measurement.MeasurementManager;
import org.rhq.core.util.file.FileUtil;
import org.rhq.core.util.stream.StreamUtil;
+import java.io.*;
+import java.util.List;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import static org.rhq.common.drift.FileEntry.*;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.DRIFT;
+import static org.rhq.core.domain.drift.DriftComplianceStatus.OUT_OF_COMPLIANCE_NO_BASEDIR;
+
public class DriftManager extends AgentService implements DriftAgentService, DriftClient, ContainerService {
private final Log log = LogFactory.getLog(DriftManager.class);
@@ -252,7 +242,8 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
if (log.isDebugEnabled()) {
log.debug("Resending " + contentZipFile.getPath());
}
- sendContentZipFile(Integer.parseInt(resourceDir.getName()), defDir.getName(), contentZipFile);
+ sendChangeSetContentToServer(Integer.parseInt(resourceDir.getName()), defDir.getName(),
+ contentZipFile);
}
}
}
@@ -343,46 +334,7 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
}
@Override
- public void sendChangeSetContentToServer(int resourceId, String driftDefinitionName, final File contentDir) {
- ZipOutputStream stream = null;
- try {
- String timestamp = Long.toString(System.currentTimeMillis());
- String contentFileName = "content_" + timestamp + ".zip";
- final File zipFile = new File(contentDir.getParentFile(), contentFileName);
- stream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
-
- for (File file : contentDir.listFiles()) {
- FileInputStream fis = new FileInputStream(file);
- try {
- stream.putNextEntry(new ZipEntry(file.getName()));
- StreamUtil.copy(fis, stream, false);
- } finally {
- fis.close();
- }
- }
- stream.close();
- stream = null;
- sendContentZipFile(resourceId, driftDefinitionName, zipFile);
- } catch (IOException e) {
- log.error("An error occurred while trying to send content for changeset[resourceId: " + resourceId
- + ", driftDefinition: " + driftDefinitionName + "]", e);
- } finally {
- if (stream != null) {
- try {
- stream.close();
- } catch (IOException e) {
- }
- }
- }
-
- for (File file : contentDir.listFiles()) {
- if (!file.delete()) {
- log.warn("Unable to clean up content directory. Failed to delete " + file.getPath());
- }
- }
- }
-
- private void sendContentZipFile(int resourceId, String driftDefName, File contentZipFile) {
+ public void sendChangeSetContentToServer(int resourceId, String driftDefName, File contentZipFile) {
try {
int startIndex = "content_".length();
int endIndex = contentZipFile.getName().indexOf(".");
@@ -390,10 +342,10 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
DriftServerService driftServer = pluginContainerConfiguration.getServerServices().getDriftServerService();
driftServer.sendFilesZip(resourceId, driftDefName, token, contentZipFile.length(),
- remoteInputStream(new BufferedInputStream(new FileInputStream(contentZipFile))));
+ remoteInputStream(new BufferedInputStream(new FileInputStream(contentZipFile))));
} catch (FileNotFoundException e) {
log.error("An error occurred while trying to send change set content zip file " + contentZipFile.getPath()
- + " to server.", e);
+ + " to server.", e);
}
}
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
index 77db6b2..d427229 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
@@ -24,12 +24,19 @@ import org.rhq.common.drift.Headers;
import org.rhq.core.domain.drift.DriftChangeSetCategory;
import org.rhq.core.domain.drift.DriftFile;
import org.rhq.core.domain.drift.JPADriftFile;
+import org.rhq.core.util.ZipUtil;
+import org.rhq.test.AssertUtils;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.io.File;
+import java.io.FilenameFilter;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
import static org.rhq.common.drift.FileEntry.addedFileEntry;
import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
@@ -53,6 +60,27 @@ public class DriftFilesSenderTest extends DriftTest {
}
@Test
+ public void sendOneFile() throws Exception {
+ String driftDefName = "send-one-file-test";
+ File serverConf = createRandomFile(resourceDir, "server.conf");
+ String serverConfHash = sha256(serverConf);
+
+ File changeSetDir = changeSetDir(driftDefName);
+ Headers headers = createHeaders(driftDefName, COVERAGE);
+
+ ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), headers);
+ writer.write(addedFileEntry("server.conf", serverConfHash));
+ writer.close();
+
+ sender.setDriftFiles(driftFiles(serverConfHash));
+ sender.setHeaders(headers);
+ sender.run();
+
+ assertContentFileExists(changeSetDir);
+ assertContentFileMatches(changeSetDir, serverConfHash);
+ }
+
+ @Test
public void sendFilesInOneDirectory() throws Exception {
String driftDefName = "single-directory-test";
@@ -73,14 +101,11 @@ public class DriftFilesSenderTest extends DriftTest {
writer.close();
sender.setDriftFiles(driftFiles(server1ConfHash, server2ConfHash));
- sender.setHeaders(createHeaders(driftDefName, COVERAGE));
+ sender.setHeaders(headers);
sender.run();
- File contentDir = mkdir(changeSetDir, "content");
-
- assertEquals(contentDir.list().length, 2, "Expected to find two files in " + contentDir.getAbsolutePath());
- assertFileCopiedToContentDir(contentDir, server1ConfHash);
- assertFileCopiedToContentDir(contentDir, server2ConfHash);
+ assertContentFileExists(changeSetDir);
+ assertContentFileMatches(changeSetDir, server1ConfHash, server2ConfHash);
}
@Test
@@ -113,16 +138,11 @@ public class DriftFilesSenderTest extends DriftTest {
// Note that the order of the drift files is random. When the server sends a request
// for files we cannot assume that the files will be in any particular order.
sender.setDriftFiles(driftFiles(server1JarHash, server2ConfHash, server2JarHash, server1ConfHash));
- sender.setHeaders(createHeaders(driftDefName, COVERAGE));
+ sender.setHeaders(headers);
sender.run();
- File contentDir = mkdir(changeSetDir, "content");
-
- assertEquals(contentDir.list().length, 4, "Expected to find four files in " + contentDir.getAbsolutePath());
- assertFileCopiedToContentDir(contentDir, server1ConfHash);
- assertFileCopiedToContentDir(contentDir, server2ConfHash);
- assertFileCopiedToContentDir(contentDir, server1JarHash);
- assertFileCopiedToContentDir(contentDir, server2JarHash);
+ assertContentFileExists(changeSetDir);
+ assertContentFileMatches(changeSetDir, server1ConfHash, server2ConfHash, server1JarHash, server2JarHash);
}
@Test
@@ -154,10 +174,8 @@ public class DriftFilesSenderTest extends DriftTest {
sender.setHeaders(headers);
sender.run();
- File contentDir = mkdir(changeSetDir, "content");
-
- assertEquals(contentDir.list().length, 1, "Expected to find one file in " + contentDir.getAbsolutePath());
- assertFileCopiedToContentDir(contentDir, server2ConfHash);
+ assertContentFileExists(changeSetDir);
+ assertContentFileMatches(changeSetDir, server2ConfHash);
}
@Test
@@ -183,6 +201,37 @@ public class DriftFilesSenderTest extends DriftTest {
assertEquals(driftClient.getSendChangeSetContentInvocationCount(), 0,
"Do not call DriftClient to send content to server when there is no content to send.");
+ assertContentFileExists(changeSetDir(driftDefName));
+ }
+
+ void assertContentFileExists(File changeSetDir) {
+ File[] files = getContentFiles(changeSetDir);
+ assertEquals(files.length, 1, "Expected to find a single content zip file but found " + Arrays.toString(files));
+ }
+
+ void assertContentFileMatches(File changeSetDir, String... expectedFileNames) throws Exception {
+ File contentFile = getContentFiles(changeSetDir)[0];
+ final List<String> actualFileNames = new LinkedList<String>();
+
+ ZipUtil.walkZipFile(contentFile, new ZipUtil.ZipEntryVisitor() {
+ @Override
+ public boolean visit(ZipEntry entry, ZipInputStream stream) throws Exception {
+ actualFileNames.add(entry.getName());
+ return true;
+ }
+ });
+
+ AssertUtils.assertCollectionEqualsNoOrder(Arrays.asList(expectedFileNames), actualFileNames,
+ "The content file " + contentFile.getPath() + " does not contain the correct entries");
+ }
+
+ private File[] getContentFiles(File changeSetDir) {
+ return changeSetDir.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.startsWith("content_") && name.endsWith(".zip");
+ }
+ });
}
/**
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftManagerTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftManagerTest.java
index c3e28f5..e1ec00d 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftManagerTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftManagerTest.java
@@ -133,7 +133,8 @@ public class DriftManagerTest extends DriftTest {
File changeSetDir = changeSetDir(config.getName());
File snapshotFile = createRandomFile(changeSetDir, "changeset.txt");
File previousSnapshotFile = createRandomFile(changeSetDir, "changeset.txt.previous");
- File changeSetZipFile = createRandomFile(changeSetDir, "changeset_" + System.currentTimeMillis() + ".zip");
+
+ createRandomFile(changeSetDir, "changeset_" + System.currentTimeMillis() + ".zip");
driftMgr.ackChangeSet(resourceId(), config.getName());
@@ -145,53 +146,11 @@ public class DriftManagerTest extends DriftTest {
}
@Test
- public void writeContentZipFileToChangeSetContentDirectory() throws Exception {
- String configName = "send-content-in-zip";
- final File changeSetDir = changeSetDir(configName);
- final File contentDir = mkdir(changeSetDir, "content");
-
- createRandomFile(contentDir, "content-1");
- createRandomFile(contentDir, "content-2");
-
- setDriftServiceCallback(new DriftServiceCallback() {
- @Override
- public void execute() {
- assertThatZipFileExists(changeSetDir, "content_", "Expected to find content zip file in "
- + changeSetDir.getPath() + ". The file name should follow the pattern "
- + "content_<integer_timestamp>.zip");
- }
- });
-
- driftMgr.sendChangeSetContentToServer(resourceId(), configName, contentDir);
- }
-
- @Test
- public void sendContentToServerInZipFile() throws Exception {
- String configName = "send-content-in-zip";
- File changeSetDir = changeSetDir(configName);
- File contentDir = mkdir(changeSetDir, "content");
-
- final File content1 = createRandomFile(contentDir, "content-1");
- final File content2 = createRandomFile(contentDir, "content-2");
-
- setDriftServiceCallback(new DriftServiceCallback() {
- @Override
- public void execute() {
- assertZipFileMatches(driftServerService.inputStream, content1, content2);
- }
- });
-
- driftMgr.sendChangeSetContentToServer(resourceId(), configName, contentDir);
-
- // verify that the content directory is purged
- assertThatDirectoryIsEmpty(contentDir);
- }
-
- @Test
public void cleanUpWhenServerAcksChangeSetContent() throws Exception {
String configName = "cleanup-when-server-acks-content";
File changeSetDir = changeSetDir(configName);
- File contentDir = mkdir(changeSetDir, "content");
+
+ mkdir(changeSetDir, "content");
String token = Long.toString(System.currentTimeMillis());
File contentZipFile = createRandomFile(changeSetDir, "content_" + token + ".zip");
@@ -309,10 +268,6 @@ public class DriftManagerTest extends DriftTest {
}
}
- private void assertThatDirectoryIsEmpty(File dir) {
- assertEquals(dir.listFiles().length, 0, "Expected " + dir.getPath() + " to be empty");
- }
-
private File findFile(File dir, File file) {
for (File f : dir.listFiles()) {
if (f.getName().equals(file.getName())) {
commit e60b0694356357d6c73b04128606afe6d75e3041
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Wed Dec 14 16:00:07 2011 -0500
[Bug 756100 - RFE: use timestamp and file size during drift detection scans]
Worked in review feedback.
- consolidated removed and cantRead entry logic
- fixed up some comments
- clear collections after they are used to possibly help out gc
Decided to still keep around the "bucket" collections and assemble the
snapshot and delta entry lists using the buckets. It just seemed more
clear to me.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
index 869e376..76d7afb 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
@@ -16,7 +16,6 @@
* 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.drift;
import static org.rhq.common.drift.FileEntry.addedFileEntry;
@@ -30,6 +29,7 @@ import static org.rhq.core.util.file.FileUtil.forEachFile;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
@@ -49,6 +49,11 @@ import org.rhq.core.domain.drift.Filter;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.file.FileVisitor;
+/**
+ * Mechanism to detect and report Drift for active Drift Definitions.
+ *
+ * @author John Sanda
+ */
public class DriftDetector implements Runnable {
private Log log = LogFactory.getLog(DriftDetector.class);
@@ -220,119 +225,142 @@ public class DriftDetector implements Runnable {
}
final List<FileEntry> unchangedEntries = new LinkedList<FileEntry>();
- final List<FileEntry> removedEntries = new LinkedList<FileEntry>();
- final List<FileEntry> cantReadEntries = new LinkedList<FileEntry>();
final List<FileEntry> changedEntries = new LinkedList<FileEntry>();
+ final List<FileEntry> removedEntries = new LinkedList<FileEntry>();
+ final List<FileEntry> addedEntries = new LinkedList<FileEntry>();
+ // for pinned snapshots, keep track of the original FileEntry objects for changed entries. These
+ // are used if we re-write the pinned snapshot file.
final List<FileEntry> changedPinnedEntries = isPinned ? new LinkedList<FileEntry>() : null;
- ChangeSetReader snapshotReader = null;
- int newVersion;
- boolean updateSnapshot = false;
try {
- snapshotReader = changeSetMgr.getChangeSetReader(snapshotFile);
-
- if (!basedir.exists()) {
- log.warn("The base directory [" + basedir.getAbsolutePath() + "] for " + schedule + " does not exist.");
- }
+ ChangeSetReader snapshotReader = null;
+ int newVersion;
+ boolean updateSnapshot = false;
+ try {
+ snapshotReader = changeSetMgr.getChangeSetReader(snapshotFile);
- if (isPinned) {
- // If pinned we compare against the pinned snapshot but we need to know the current snapshot version,
- // get it from the current full snapshot.
- ChangeSetReader currentFullSnapshotReader = null;
- try {
- currentFullSnapshotReader = changeSetMgr.getChangeSetReader(currentFullSnapshot);
- newVersion = currentFullSnapshotReader.getHeaders().getVersion() + 1;
- } finally {
- currentFullSnapshotReader.close();
+ if (!basedir.exists()) {
+ log.warn("The base directory [" + basedir.getAbsolutePath() + "] for " + schedule
+ + " does not exist.");
}
- } else {
- newVersion = snapshotReader.getHeaders().getVersion() + 1;
- }
-
- // First look for files that have either been modified or deleted
- updateSnapshot = scanSnapshotFiles(schedule, basedir, snapshotReader, newFiles, unchangedEntries,
- removedEntries, cantReadEntries, changedEntries, changedPinnedEntries);
- } finally {
- snapshotReader.close();
- }
+ if (isPinned) {
+ // If pinned we compare against the pinned snapshot but we need to know the current snapshot version,
+ // get it from the current full snapshot.
+ ChangeSetReader currentFullSnapshotReader = null;
+ try {
+ currentFullSnapshotReader = changeSetMgr.getChangeSetReader(currentFullSnapshot);
+ newVersion = currentFullSnapshotReader.getHeaders().getVersion() + 1;
+ } finally {
+ currentFullSnapshotReader.close();
+ }
+ } else {
+ newVersion = snapshotReader.getHeaders().getVersion() + 1;
+ }
- // if necessary, re-write the pinned snapshot file because we've updated timestamp/filesize info, which
- // on subsequent detection runs will help us avoid SHA generation. It must maintain the same entries.
- if (isPinned && updateSnapshot) {
- changedPinnedEntries.addAll(unchangedEntries);
+ // First look for files that have either been changed or removed
+ updateSnapshot = scanSnapshot(schedule, basedir, snapshotReader, newFiles, unchangedEntries,
+ changedEntries, removedEntries, changedPinnedEntries);
- backupAndDeleteCurrentSnapshot(snapshotFile);
- updatePinnedSnapshot(schedule, snapshotFile, changedPinnedEntries);
- }
+ } finally {
+ snapshotReader.close();
+ }
- final List<FileEntry> snapshotEntries = new LinkedList<FileEntry>(unchangedEntries);
- snapshotEntries.addAll(changedEntries);
+ // if necessary, re-write the pinned snapshot file because we've updated timestamp/filesize info, which
+ // on subsequent detection runs will help us avoid SHA generation. It must maintain the same entries.
+ if (isPinned && updateSnapshot) {
+ changedPinnedEntries.addAll(unchangedEntries);
- final List<FileEntry> deltaEntries = new LinkedList<FileEntry>(changedEntries);
- deltaEntries.addAll(removedEntries);
- deltaEntries.addAll(cantReadEntries);
+ backupAndDeleteCurrentSnapshot(snapshotFile);
+ updatePinnedSnapshot(schedule, snapshotFile, changedPinnedEntries);
+ }
- for (File file : newFiles) {
- try {
- if (log.isInfoEnabled()) {
- log.info("Detected added file for " + schedule + " --> " + file.getAbsolutePath());
- }
+ // add new files to the snapshotEntries and deltaEntries
+ for (File file : newFiles) {
+ try {
+ if (log.isInfoEnabled()) {
+ log.info("Detected added file for " + schedule + " --> " + file.getAbsolutePath());
+ }
- FileEntry newEntry = addedFileEntry(relativePath(basedir, file), sha256(file), file.lastModified(),
- file.length());
+ FileEntry newEntry = addedFileEntry(relativePath(basedir, file), sha256(file), file.lastModified(),
+ file.length());
- deltaEntries.add(newEntry);
- snapshotEntries.add(newEntry);
+ addedEntries.add(newEntry);
- } catch (IOException e) {
- log.error("An error occurred while generating a drift change set for " + schedule + ": "
- + e.getMessage());
- throw new DriftDetectionException("An error occurred while generating a drift change set", e);
+ } catch (IOException e) {
+ log.error("An error occurred while generating a drift change set for " + schedule + ": "
+ + e.getMessage());
+ throw new DriftDetectionException("An error occurred while generating a drift change set", e);
+ }
}
- }
-
- if (deltaEntries.isEmpty()) {
- File newSnapshot = currentFullSnapshot;
- if (!isPinned) {
- // If unpinned and there is no detected drift then we generally don't need to add/update any files.
- // But, if we have timestamp/filesize updates then we want to replace the current snapshot with
- // the updated entries, so we can avoid SHA generation on subsequent runs.
- if (updateSnapshot) {
- currentFullSnapshot.delete();
- newSnapshot = updateCurrentSnapshot(schedule, snapshotEntries, newVersion - 1);
+ // The new snapshot contains all changed, unchanged and added files. Not removed files.
+ final List<FileEntry> snapshotEntries = new LinkedList<FileEntry>(unchangedEntries);
+ snapshotEntries.addAll(changedEntries);
+ snapshotEntries.addAll(addedEntries);
+
+ // The snapshot delta contains all changed, added and removed files.
+ final List<FileEntry> deltaEntries = new LinkedList<FileEntry>(changedEntries);
+ deltaEntries.addAll(removedEntries);
+ deltaEntries.addAll(addedEntries);
+
+ if (deltaEntries.isEmpty()) {
+ File newSnapshot = currentFullSnapshot;
+
+ if (!isPinned) {
+ // If unpinned and there is no detected drift then we generally don't need to add/update any files.
+ // But, if we have timestamp/filesize updates then we want to replace the current snapshot with
+ // the updated entries, so we can avoid SHA generation on subsequent runs.
+ if (updateSnapshot) {
+ currentFullSnapshot.delete();
+ newSnapshot = updateCurrentSnapshot(schedule, snapshotEntries, newVersion - 1);
+ }
+ } else {
+ // If pinned and returning to compliance (meaning no drift now but the previous snapshot did have drift)
+ // then we need to reset the current snapshot to match the pinned snapshot. Note though that we
+ // increment the snapshot version in order to let the server know about the state change.
+ if (newVersion > 1
+ && !isPreviousChangeSetEmpty(schedule.getResourceId(), schedule.getDriftDefinition())) {
+ currentFullSnapshot.delete();
+ newSnapshot = updateCurrentSnapshot(schedule, snapshotEntries, newVersion);
+
+ updateDeltaSnapshot(summary, schedule, deltaEntries, newVersion, currentFullSnapshot,
+ newSnapshot);
+ }
}
+
+ summary.setNewSnapshot(newSnapshot);
+
} else {
- // If pinned and returning to compliance (meaning no drift now but the previous snapshot did have drift)
- // then we need to reset the current snapshot to match the pinned snapshot. Note though that we
- // increment the snapshot version in order to let the server know about the state change.
- if (newVersion > 1
- && !isPreviousChangeSetEmpty(schedule.getResourceId(), schedule.getDriftDefinition())) {
- currentFullSnapshot.delete();
- newSnapshot = updateCurrentSnapshot(schedule, snapshotEntries, newVersion);
-
- updateDeltaSnapshot(summary, schedule, deltaEntries, newVersion, currentFullSnapshot, newSnapshot);
- }
- }
+ // if there is drift, but we're pinned and the drift is the same as the previous detection, just
+ // mark it as a repeat to indicate that we're out of compliance but not in any new way.
+ if (isPinned && newVersion > 1 && isSameAsPreviousChangeSet(deltaEntries, currentFullSnapshot)) {
+ summary.setVersion(newVersion - 1);
+ summary.setRepeat(true);
- summary.setNewSnapshot(newSnapshot);
+ return;
+ }
- } else {
- // if there is drift, but we're pinned and the drift is the same as the previous detection, just
- // mark it as a repeat to indicate that we're out of compliance but not in any new way.
- if (isPinned && newVersion > 1 && isSameAsPreviousChangeSet(deltaEntries, currentFullSnapshot)) {
- summary.setVersion(newVersion - 1);
- summary.setRepeat(true);
+ // otherwise, generate a new current snapshot, and a snapshot delta reflecting the latest drift
+ File oldSnapshot = backupAndDeleteCurrentSnapshot(currentFullSnapshot);
+ File newSnapshot = updateCurrentSnapshot(schedule, snapshotEntries, newVersion);
- return;
+ updateDeltaSnapshot(summary, schedule, deltaEntries, newVersion, oldSnapshot, newSnapshot);
}
+ } finally {
+ // Help out the garbage collector by clearing all of our collections
+ safeClear(newFiles, unchangedEntries, changedEntries, changedPinnedEntries);
+ }
+ }
- // otherwise, generate a new current snapshot, and a snapshot delta reflecting the latest drift
- File oldSnapshot = backupAndDeleteCurrentSnapshot(currentFullSnapshot);
- File newSnapshot = updateCurrentSnapshot(schedule, snapshotEntries, newVersion);
-
- updateDeltaSnapshot(summary, schedule, deltaEntries, newVersion, oldSnapshot, newSnapshot);
+ static private void safeClear(Collection<?>... collections) {
+ if (null == collections) {
+ return;
+ }
+ for (Collection<?> c : collections) {
+ if (null != c) {
+ c.clear();
+ }
}
}
@@ -363,10 +391,9 @@ public class DriftDetector implements Runnable {
* snapshot should be re-written to disk even if there was no drift.
* @throws IOException
*/
- private boolean scanSnapshotFiles(DriftDetectionSchedule schedule, File basedir, ChangeSetReader snapshotReader,
- Set<File> newFiles, List<FileEntry> unchangedEntries, List<FileEntry> removedEntries,
- List<FileEntry> cantReadEntries, List<FileEntry> modifiedEntries, List<FileEntry> changedPinnedEntries)
- throws IOException {
+ private boolean scanSnapshot(DriftDetectionSchedule schedule, File basedir, ChangeSetReader snapshotReader,
+ Set<File> newFiles, List<FileEntry> unchangedEntries, List<FileEntry> changedEntries,
+ List<FileEntry> removedEntries, List<FileEntry> changedPinnedEntries) throws IOException {
boolean result = false;
@@ -374,10 +401,11 @@ public class DriftDetector implements Runnable {
File file = new File(basedir, entry.getFile());
newFiles.remove(file);
- if (!file.exists()) {
- // The file has been deleted since the last scan
+ if (!(file.exists() && file.canRead())) {
+ // The file has been deleted or is no longer readable, since the last scan
if (log.isDebugEnabled()) {
- log.debug("Detected deleted file for " + schedule + " --> " + file.getAbsolutePath());
+ log.debug("Detected " + (file.exists() ? "unreadable" : "deleted") + " file for " + schedule
+ + " --> " + file.getAbsolutePath());
}
removedEntries.add(removedFileEntry(entry.getFile(), entry.getNewSHA()));
@@ -387,37 +415,25 @@ public class DriftDetector implements Runnable {
continue;
- } else if (!file.canRead()) {
- if (log.isDebugEnabled()) {
- log.debug(file.getPath() + " is no longer readable. Treating it as a deleted file.");
- }
- cantReadEntries.add(removedFileEntry(entry.getFile(), entry.getNewSHA()));
-
- if (null != changedPinnedEntries) {
- changedPinnedEntries.add(entry);
- }
-
- continue;
-
} else {
String currentSHA = null;
- boolean isModified = false;
+ boolean isChanged = false;
// perform a SHA comparison if we are unable to compare size and lastModified or if the
- // size or lastModified test fails. We may not have size of lastModified values for the
+ // size or lastModified test fails. We may not have size or lastModified values for the
// entry when the current snapshot was provided by the server, either due to a synch or
// pinning scenario. The server does not store that information and will provide -1 for defaults.
if (entry.getLastModified() == -1 || entry.getSize() == -1
|| entry.getLastModified() != file.lastModified() || entry.getSize() != file.length()) {
currentSHA = sha256(file);
- isModified = !entry.getNewSHA().equals(currentSHA);
+ isChanged = !entry.getNewSHA().equals(currentSHA);
}
- if (isModified) {
- FileEntry modifiedEntry = changedFileEntry(entry.getFile(), entry.getNewSHA(), currentSHA, file
+ if (isChanged) {
+ FileEntry changedEntry = changedFileEntry(entry.getFile(), entry.getNewSHA(), currentSHA, file
.lastModified(), file.length());
- modifiedEntries.add(modifiedEntry);
+ changedEntries.add(changedEntry);
if (null != changedPinnedEntries) {
changedPinnedEntries.add(entry);
commit b7ff74899be79a903a40483691e4916f313e3500
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Wed Dec 14 15:59:24 2011 -0500
- Add some unit tests ensuring timestamp info is updated appropriately.
- remove a bunch of IDE warnings
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftDetectorTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftDetectorTest.java
index b0b1143..0f2d30a 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftDetectorTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftDetectorTest.java
@@ -19,12 +19,22 @@
package org.rhq.core.pc.drift;
-import org.rhq.common.drift.*;
-import org.rhq.core.domain.drift.DriftDefinition;
-import org.rhq.core.system.OperatingSystemType;
-import org.rhq.core.system.SystemInfoFactory;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static org.apache.commons.io.FileUtils.copyFile;
+import static org.apache.commons.io.FileUtils.deleteDirectory;
+import static org.apache.commons.io.FileUtils.touch;
+import static org.rhq.common.drift.FileEntry.addedFileEntry;
+import static org.rhq.common.drift.FileEntry.changedFileEntry;
+import static org.rhq.common.drift.FileEntry.removedFileEntry;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.DRIFT;
+import static org.rhq.test.AssertUtils.assertCollectionMatchesNoOrder;
+import static org.rhq.test.AssertUtils.assertPropertiesMatch;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
import java.io.BufferedReader;
import java.io.File;
@@ -33,15 +43,18 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptyList;
-import static org.apache.commons.io.FileUtils.*;
-import static org.rhq.common.drift.FileEntry.*;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.DRIFT;
-import static org.rhq.test.AssertUtils.assertCollectionMatchesNoOrder;
-import static org.rhq.test.AssertUtils.assertPropertiesMatch;
-import static org.testng.Assert.*;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.common.drift.ChangeSetReader;
+import org.rhq.common.drift.ChangeSetReaderImpl;
+import org.rhq.common.drift.ChangeSetWriter;
+import org.rhq.common.drift.ChangeSetWriterImpl;
+import org.rhq.common.drift.FileEntry;
+import org.rhq.common.drift.Headers;
+import org.rhq.core.domain.drift.DriftDefinition;
+import org.rhq.core.system.OperatingSystemType;
+import org.rhq.core.system.SystemInfoFactory;
public class DriftDetectorTest extends DriftTest {
@@ -66,7 +79,6 @@ public class DriftDetectorTest extends DriftTest {
detector.setScheduleQueue(scheduleQueue);
}
- @SuppressWarnings("unchecked")
@Test
public void excludeEmptyDirsFromCoverageChangeSet() throws Exception {
File confDir = mkdir(resourceDir, "conf");
@@ -74,6 +86,7 @@ public class DriftDetectorTest extends DriftTest {
// create an empty directory
File libDir = mkdir(resourceDir, "lib");
+ assert (libDir.isDirectory());
DriftDefinition driftDef = driftDefinition("coverage-test", resourceDir.getAbsolutePath());
@@ -82,14 +95,13 @@ public class DriftDetectorTest extends DriftTest {
File changeSet = changeSet(driftDef.getName(), COVERAGE);
Headers headers = createHeaders(driftDef, COVERAGE);
- List<FileEntry> expected = asList(addedFileEntry("conf/server.conf", sha256(serverConf),
- serverConf.lastModified(), serverConf.length()));
+ List<FileEntry> expected = asList(addedFileEntry("conf/server.conf", sha256(serverConf), serverConf
+ .lastModified(), serverConf.length()));
assertHeaderEquals(changeSet, headers);
assertFileEntriesMatch("Only files should be included in a change set.", expected, changeSet);
}
- @SuppressWarnings("unchecked")
@Test
public void includeMultipleFilesInDirInCoverageChangeSet() throws Exception {
File confDir = mkdir(resourceDir, "conf");
@@ -102,16 +114,15 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
File changeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> entries = asList(
- addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf.length()),
- addedFileEntry("conf/server-2.conf", sha256(server2Conf), server2Conf.lastModified(), server2Conf.length()));
+ List<FileEntry> entries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf
+ .lastModified(), server1Conf.length()), addedFileEntry("conf/server-2.conf", sha256(server2Conf),
+ server2Conf.lastModified(), server2Conf.length()));
assertHeaderEquals(changeSet, createHeaders(def, COVERAGE));
assertFileEntriesMatch("Each file in a directory should be included in a coverage change set", entries,
changeSet);
}
- @SuppressWarnings("unchecked")
@Test
public void includedSiblingDirsInCoverageChangeSet() throws Exception {
File confDir = mkdir(resourceDir, "conf");
@@ -126,16 +137,15 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
File changeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> entries = asList(
- addedFileEntry("conf/server.conf", sha256(serverConf), serverConf.lastModified(), serverConf.length()),
- addedFileEntry("lib/server.jar", sha256(serverLib), serverLib.lastModified(), serverLib.length()));
+ List<FileEntry> entries = asList(addedFileEntry("conf/server.conf", sha256(serverConf), serverConf
+ .lastModified(), serverConf.length()), addedFileEntry("lib/server.jar", sha256(serverLib), serverLib
+ .lastModified(), serverLib.length()));
assertHeaderEquals(changeSet, createHeaders(def, COVERAGE));
assertFileEntriesMatch("A coverage change set should include files from multiple, sibling directories",
entries, changeSet);
}
- @SuppressWarnings("unchecked")
@Test
public void includeNestedDirsInCoverageChangeSet() throws Exception {
File confDir = mkdir(resourceDir, "conf");
@@ -150,9 +160,9 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
File changeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> entries = asList(
- addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf.length()),
- addedFileEntry("conf/subconf/server-2.conf", sha256(server2Conf), server2Conf.lastModified(), server2Conf.length()));
+ List<FileEntry> entries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf
+ .lastModified(), server1Conf.length()), addedFileEntry("conf/subconf/server-2.conf", sha256(server2Conf),
+ server2Conf.lastModified(), server2Conf.length()));
assertHeaderEquals(changeSet, createHeaders(def, COVERAGE));
assertFileEntriesMatch("A coverage change set should include files in nested sub directories", entries,
@@ -161,12 +171,13 @@ public class DriftDetectorTest extends DriftTest {
@Test
public void updateScheduleAfterGeneratingCoverageChangeSet() throws Exception {
- DriftDefinition driftDef = driftDefinition("update-schedule-after-coverage-changeset",
- resourceDir.getAbsolutePath());
+ DriftDefinition driftDef = driftDefinition("update-schedule-after-coverage-changeset", resourceDir
+ .getAbsolutePath());
DriftDetectionSchedule schedule = new DriftDetectionSchedule(resourceId(), driftDef);
File confDir = mkdir(resourceDir, "conf");
File serverConf = createRandomFile(confDir, "server.conf");
+ assert (serverConf.exists());
long currentTime = System.currentTimeMillis();
@@ -174,8 +185,8 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
assertTrue(schedule.getNextScan() >= (currentTime + driftDef.getInterval()),
- "Failed to update schedule. next scan is " + schedule.getNextScan() + " and should be greater than " +
- (currentTime + driftDef.getInterval()));
+ "Failed to update schedule. next scan is " + schedule.getNextScan() + " and should be greater than "
+ + (currentTime + driftDef.getInterval()));
}
@Test
@@ -183,11 +194,11 @@ public class DriftDetectorTest extends DriftTest {
}
- @SuppressWarnings("unchecked")
@Test
public void doNotUpdateSnapshotOrGenerateDriftChangeSetIfNothingChanges() throws Exception {
File confDir = mkdir(resourceDir, "conf");
File serverConf = createRandomFile(confDir, "server.conf");
+ assert (serverConf.exists());
DriftDefinition def = driftDefinition("nothing-to-update", resourceDir.getAbsolutePath());
@@ -217,7 +228,6 @@ public class DriftDetectorTest extends DriftTest {
+ "no drift");
}
- @SuppressWarnings("unchecked")
@Test
public void skipDetectionForScheduledThatIsDisabled() throws Exception {
detector.setDriftClient(new DriftClientTestStub() {
@@ -245,8 +255,8 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
// make sure that the next scan time is not updated
- assertEquals(schedule.getNextScan(), nextScan, "The next scan time for the drift detection schedule should " +
- " not get updated if drift detection does not actually run for the definition.");
+ assertEquals(schedule.getNextScan(), nextScan, "The next scan time for the drift detection schedule should "
+ + " not get updated if drift detection does not actually run for the definition.");
}
@Test
@@ -255,7 +265,8 @@ public class DriftDetectorTest extends DriftTest {
DriftDetectionSchedule schedule = new DriftDetectionSchedule(resourceId(), driftDef);
File confDir = mkdir(resourceDir, "conf");
- File server1Conf = new File(confDir, "server.conf");
+ File server1Conf = createRandomFile(confDir, "server.conf");
+ assert (server1Conf.exists());
scheduleQueue.addSchedule(schedule);
detector.run();
@@ -263,8 +274,8 @@ public class DriftDetectorTest extends DriftTest {
long nextScan = schedule.getNextScan();
detector.run();
- assertEquals(schedule.getNextScan(), nextScan, "The next scan time for the drift detection schedule should " +
- " not get updated if drift detection does not actually run for the definition.");
+ assertEquals(schedule.getNextScan(), nextScan, "The next scan time for the drift detection schedule should "
+ + " not get updated if drift detection does not actually run for the definition.");
}
@Test
@@ -277,18 +288,17 @@ public class DriftDetectorTest extends DriftTest {
scheduleQueue.addSchedule(new DriftDetectionSchedule(resourceId(), def));
detector.run();
- assertEquals(driftClient.getReportMissingBaseDirInvocationCount(), 1, "A missing base directory should be " +
- "reported to the server if no initial snapshot has already been generated.");
- assertEquals(driftClient.getSendChangeSetInvocationCount(), 0, "No initial change set should be sent to " +
- "the server if the base directory does not exist.");
+ assertEquals(driftClient.getReportMissingBaseDirInvocationCount(), 1, "A missing base directory should be "
+ + "reported to the server if no initial snapshot has already been generated.");
+ assertEquals(driftClient.getSendChangeSetInvocationCount(), 0, "No initial change set should be sent to "
+ + "the server if the base directory does not exist.");
// verify that the initial change set was not generated
File snapshot = changeSet(def.getName(), COVERAGE);
- assertFalse(snapshot.exists(), "An initial snapshot should not be written to disk if the base directory " +
- "does not exist.");
+ assertFalse(snapshot.exists(), "An initial snapshot should not be written to disk if the base directory "
+ + "does not exist.");
}
- @SuppressWarnings("unchecked")
@Test
public void skipDetectionWhenPreviousSnapshotFileExists() throws Exception {
// The presence of a previous snapshot file means that the server has
@@ -327,7 +337,6 @@ public class DriftDetectorTest extends DriftTest {
+ "drift detection should not have run until the server acked the previous snapshot.");
}
- @SuppressWarnings("unchecked")
@Test
public void includeAddedFileInDriftChangeSet() throws Exception {
DriftDefinition def = driftDefinition("file-added-drift-test", resourceDir.getAbsolutePath());
@@ -336,8 +345,8 @@ public class DriftDetectorTest extends DriftTest {
File server1Conf = createRandomFile(confDir, "server-1.conf");
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), createHeaders(def, COVERAGE));
- writer.write(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(),
- server1Conf.length()));
+ writer.write(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf
+ .length()));
writer.close();
// Create some drift
@@ -347,8 +356,8 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
File driftChangeSet = changeSet(def.getName(), DRIFT);
- List<FileEntry> driftEntries = asList(addedFileEntry("conf/server-2.conf", sha256(server2Conf),
- server2Conf.lastModified(), server2Conf.length()));
+ List<FileEntry> driftEntries = asList(addedFileEntry("conf/server-2.conf", sha256(server2Conf), server2Conf
+ .lastModified(), server2Conf.length()));
// verify that the drift change set was generated
assertTrue(driftChangeSet.exists(), "Expected to find drift change set " + driftChangeSet.getPath());
@@ -356,9 +365,9 @@ public class DriftDetectorTest extends DriftTest {
assertFileEntriesMatch("The drift change set does not match the expected values", driftEntries, driftChangeSet);
File coverageChangeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> coverageEntries = asList(
- addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf.length()),
- addedFileEntry("conf/server-2.conf", sha256(server2Conf), server2Conf.lastModified(), server2Conf.length()));
+ List<FileEntry> coverageEntries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf
+ .lastModified(), server1Conf.length()), addedFileEntry("conf/server-2.conf", sha256(server2Conf),
+ server2Conf.lastModified(), server2Conf.length()));
// verify that the coverage change set was updated
assertHeaderEquals(coverageChangeSet, createHeaders(def, COVERAGE, 1));
@@ -366,7 +375,6 @@ public class DriftDetectorTest extends DriftTest {
coverageChangeSet);
}
- @SuppressWarnings("unchecked")
@Test
public void includeModifiedFileInDriftChangeSet() throws Exception {
DriftDefinition def = driftDefinition("file-modified-drift-test", resourceDir.getAbsolutePath());
@@ -388,8 +396,8 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
File driftChangeSet = changeSet(def.getName(), DRIFT);
- List<FileEntry> driftEntries = asList(changedFileEntry("conf/server-1.conf", oldHash, newHash,
- server1Conf.lastModified(), server1Conf.length()));
+ List<FileEntry> driftEntries = asList(changedFileEntry("conf/server-1.conf", oldHash, newHash, server1Conf
+ .lastModified(), server1Conf.length()));
// verify that the drift change set was generated
assertTrue(driftChangeSet.exists(), "Expected to find drift change set " + driftChangeSet.getPath());
@@ -397,8 +405,8 @@ public class DriftDetectorTest extends DriftTest {
assertFileEntriesMatch("The drift change set does not match the expected values", driftEntries, driftChangeSet);
File coverageChangeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> coverageEntries = asList(changedFileEntry("conf/server-1.conf", oldHash, newHash,
- server1Conf.lastModified(), server1Conf.length()));
+ List<FileEntry> coverageEntries = asList(changedFileEntry("conf/server-1.conf", oldHash, newHash, server1Conf
+ .lastModified(), server1Conf.length()));
// verify that the coverage change set was updated
assertHeaderEquals(coverageChangeSet, createHeaders(def, COVERAGE, 1));
@@ -406,7 +414,6 @@ public class DriftDetectorTest extends DriftTest {
coverageChangeSet);
}
- @SuppressWarnings("unchecked")
@Test(enabled = false)
public void includeFiledAddedInNewDirectoryInDriftChangeSet() throws Exception {
DriftDefinition def = driftDefinition("file-added-in-new-dir", resourceDir.getAbsolutePath());
@@ -415,8 +422,8 @@ public class DriftDetectorTest extends DriftTest {
File server1Conf = createRandomFile(confDir, "server-1.conf");
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), createHeaders(def, COVERAGE));
- writer.write(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(),
- server1Conf.length()));
+ writer.write(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf
+ .length()));
writer.close();
// create some drift
@@ -436,9 +443,9 @@ public class DriftDetectorTest extends DriftTest {
assertFileEntriesMatch("The drift change set does not match the expected values", driftEntries, driftChangeSet);
File coverageChangeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> coverageEntries = asList(
- addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf.length()),
- addedFileEntry("conf/subconf/server-2.conf", sha256(server2Conf), server2Conf.lastModified(), server2Conf.length()));
+ List<FileEntry> coverageEntries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf
+ .lastModified(), server1Conf.length()), addedFileEntry("conf/subconf/server-2.conf", sha256(server2Conf),
+ server2Conf.lastModified(), server2Conf.length()));
// verify that the coverage change set was updated
assertHeaderEquals(coverageChangeSet, createHeaders(def, COVERAGE, 1));
@@ -446,7 +453,6 @@ public class DriftDetectorTest extends DriftTest {
coverageChangeSet);
}
- @SuppressWarnings("unchecked")
@Test
public void includeRemovedFileInDriftChangeSet() throws Exception {
DriftDefinition def = driftDefinition("file-removed-drift-test", resourceDir.getAbsolutePath());
@@ -458,10 +464,10 @@ public class DriftDetectorTest extends DriftTest {
String server2ConfHash = sha256(server2Conf);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), createHeaders(def, COVERAGE));
- writer.write(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(),
- server1Conf.length()));
- writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash, server2Conf.lastModified(),
- server2Conf.length()));
+ writer.write(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf
+ .length()));
+ writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash, server2Conf.lastModified(), server2Conf
+ .length()));
writer.close();
// create some drift
@@ -480,8 +486,8 @@ public class DriftDetectorTest extends DriftTest {
// verify that the coverage change set was updated
File coverageChangeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> coverageEntries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf),
- server1Conf.lastModified(), server1Conf.length()));
+ List<FileEntry> coverageEntries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf
+ .lastModified(), server1Conf.length()));
assertHeaderEquals(coverageChangeSet, createHeaders(def, COVERAGE, 1));
assertFileEntriesMatch("The coverage change set was not updated as expected", coverageEntries,
@@ -529,7 +535,6 @@ public class DriftDetectorTest extends DriftTest {
}
- @SuppressWarnings("unchecked")
@Test
public void includeFilesInRemovedDirectoryInDriftChangeSet() throws Exception {
DriftDefinition def = driftDefinition("dir-removed-test", resourceDir.getAbsolutePath());
@@ -539,7 +544,8 @@ public class DriftDetectorTest extends DriftTest {
String server1Hash = sha256(server1Conf);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), createHeaders(def, COVERAGE));
- writer.write(addedFileEntry("conf/server-1.conf", server1Hash, server1Conf.lastModified(), server1Conf.length()));
+ writer
+ .write(addedFileEntry("conf/server-1.conf", server1Hash, server1Conf.lastModified(), server1Conf.length()));
writer.close();
// create some drift
@@ -566,7 +572,6 @@ public class DriftDetectorTest extends DriftTest {
coverageChangeSet);
}
- @SuppressWarnings("unchecked")
@Test
public void revertToPreviousSnapshotWhenSendingChangeSetFails() throws Exception {
DriftDefinition def = driftDefinition("revert-snapshot-test", resourceDir.getAbsolutePath());
@@ -574,6 +579,7 @@ public class DriftDetectorTest extends DriftTest {
File confDir = mkdir(resourceDir, "conf");
File server1Conf = createRandomFile(confDir, "server.conf");
+ assert (server1Conf.exists());
scheduleQueue.addSchedule(schedule);
// generate the initial snapshot
@@ -612,7 +618,6 @@ public class DriftDetectorTest extends DriftTest {
+ "should be deleted once we have reverted back to it and have a new, current snapsot file.");
}
- @SuppressWarnings("unchecked")
@Test
public void purgeSnapshotWhenSendingInitialChangeSetFails() throws Exception {
// If we have just generated the initial change set and sending it to
@@ -650,8 +655,8 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
File changeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> entries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf),
- server1Conf.lastModified(), server1Conf.length()));
+ List<FileEntry> entries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf
+ .lastModified(), server1Conf.length()));
assertHeaderEquals(changeSet, createHeaders(def, COVERAGE));
assertFileEntriesMatch("Files that are non-readable should be skipped but other, readable file should still "
@@ -760,14 +765,14 @@ public class DriftDetectorTest extends DriftTest {
String newPinnedHash = sha256(pinnedSnapshot);
- assertEquals(newPinnedHash, originalPinnedHash, "When a snapshot is pinned, it should not get updated during " +
- "drift detection");
+ assertEquals(newPinnedHash, originalPinnedHash, "When a snapshot is pinned, it should not get updated during "
+ + "drift detection");
// We always generate/update the current snapshot so we still need to verify that it
// was generated/updated correctly
- List<FileEntry> fileEntries = asList(
- addedFileEntry("conf/server1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf.length()),
- addedFileEntry("conf/server2.conf", sha256(server2Conf), server2Conf.lastModified(), server2Conf.length()));
+ List<FileEntry> fileEntries = asList(addedFileEntry("conf/server1.conf", sha256(server1Conf), server1Conf
+ .lastModified(), server1Conf.length()), addedFileEntry("conf/server2.conf", sha256(server2Conf),
+ server2Conf.lastModified(), server2Conf.length()));
assertHeaderEquals(currentSnapshot, createHeaders(driftDef, COVERAGE, 1));
assertFileEntriesMatch("The current snapshot file should still get updated even when using a pinned snapshot",
@@ -801,10 +806,10 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
// verify that the current snapshot was updated
- List<FileEntry> currentSnapshotEntries = asList(
- addedFileEntry("conf/server1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf.length()),
- addedFileEntry("conf/server2.conf", sha256(server2Conf), server2Conf.lastModified(), server2Conf.length()),
- addedFileEntry("conf/server3.conf", sha256(server3Conf), server3Conf.lastModified(), server3Conf.length()));
+ List<FileEntry> currentSnapshotEntries = asList(addedFileEntry("conf/server1.conf", sha256(server1Conf),
+ server1Conf.lastModified(), server1Conf.length()), addedFileEntry("conf/server2.conf", sha256(server2Conf),
+ server2Conf.lastModified(), server2Conf.length()), addedFileEntry("conf/server3.conf", sha256(server3Conf),
+ server3Conf.lastModified(), server3Conf.length()));
assertHeaderEquals(currentSnapshot, createHeaders(driftDef, COVERAGE, 2));
assertFileEntriesMatch("The current snapshot file should still get updated even when using a pinned snapshot",
@@ -812,9 +817,9 @@ public class DriftDetectorTest extends DriftTest {
// verify that the the drift/delta change set was generated
File driftChangeSet = changeSet(driftDef.getName(), DRIFT);
- List<FileEntry> driftEntries = asList(
- addedFileEntry("conf/server2.conf", sha256(server2Conf), server2Conf.lastModified(), server2Conf.length()),
- addedFileEntry("conf/server3.conf", sha256(server3Conf), server3Conf.lastModified(), server3Conf.length()));
+ List<FileEntry> driftEntries = asList(addedFileEntry("conf/server2.conf", sha256(server2Conf), server2Conf
+ .lastModified(), server2Conf.length()), addedFileEntry("conf/server3.conf", sha256(server3Conf),
+ server3Conf.lastModified(), server3Conf.length()));
assertHeaderEquals(driftChangeSet, createHeaders(driftDef, DRIFT, 2));
assertFileEntriesMatch("The drift change set was not generated correctly when using a pinned snapshot",
@@ -835,16 +840,16 @@ public class DriftDetectorTest extends DriftTest {
File changeSet = changeSet(driftDef.getName(), COVERAGE);
File pinnedSnapshot = new File(changeSet.getParentFile(), "snapshot.pinned");
- List<FileEntry> entries = asList(addedFileEntry("conf/server.conf", sha256(serverConf),
- serverConf.lastModified(), serverConf.length()));
+ List<FileEntry> entries = asList(addedFileEntry("conf/server.conf", sha256(serverConf), serverConf
+ .lastModified(), serverConf.length()));
assertTrue(changeSet.exists(), "An initial snapshot file should be generated even when it is pinned");
assertHeaderEquals(changeSet, createHeaders(driftDef, COVERAGE));
assertFileEntriesMatch("Initial snapshot entries are wrong for pinned snapshot", entries, changeSet);
assertTrue(pinnedSnapshot.exists(), "Pinned snapshot file should be generated when initial version is pinned");
- assertEquals(sha256(changeSet), sha256(pinnedSnapshot), "The contents of the pinned snapshot file and the " +
- "initial snapshot should be identical");
+ assertEquals(sha256(changeSet), sha256(pinnedSnapshot), "The contents of the pinned snapshot file and the "
+ + "initial snapshot should be identical");
}
@Test
@@ -895,8 +900,8 @@ public class DriftDetectorTest extends DriftTest {
public void repeatChangeSet(int resourceId, String driftDefName, int version) {
repeatChangeSetCalled.set(true);
assertEquals(resourceId, resourceId(), "The resource id for the repeat change set is wrong");
- assertEquals(driftDefName, driftDef.getName(), "The drift definition name for the repeat change set " +
- "is wrong");
+ assertEquals(driftDefName, driftDef.getName(), "The drift definition name for the repeat change set "
+ + "is wrong");
assertEquals(version, 1, "The snapshot version should not have changed since no new drift was detected");
}
});
@@ -914,8 +919,8 @@ public class DriftDetectorTest extends DriftTest {
assertTrue(repeatChangeSetCalled.get(), "Failed to notify server of repeat change set");
// verify that the previous version snapshot file has been deleted
- assertFalse(previousSnapshot.exists(), "There should be no previous version snapshot file because the " +
- "server has already acknowledged the current snapshot.");
+ assertFalse(previousSnapshot.exists(), "There should be no previous version snapshot file because the "
+ + "server has already acknowledged the current snapshot.");
}
@@ -933,7 +938,8 @@ public class DriftDetectorTest extends DriftTest {
// generate the pinned snapshot which is version zero
File pinnedSnapshot = pinnedSnapshot(driftDef.getName());
ChangeSetWriter writer = new ChangeSetWriterImpl(pinnedSnapshot, headers);
- writer.write(addedFileEntry("conf/server.conf", serverConfHash, serverConf.lastModified(), serverConf.length()));
+ writer
+ .write(addedFileEntry("conf/server.conf", serverConfHash, serverConf.lastModified(), serverConf.length()));
writer.close();
// generate the current snapshot file. we will take a shortcut here by
@@ -946,6 +952,7 @@ public class DriftDetectorTest extends DriftTest {
// now generate some drift causing the resource to go out of compliance
File newServerConf = createRandomFile(confDir, "new_server.conf");
String newServerConfHash = sha256(newServerConf);
+ assert (null != newServerConfHash);
// do a drift detection run
DriftDetectionSchedule schedule = new DriftDetectionSchedule(resourceId(), driftDef);
@@ -965,12 +972,81 @@ public class DriftDetectorTest extends DriftTest {
// verify that that current snapshot has been updated to reflect that
// the resource is back in compliance.
- List<FileEntry> entries = asList(addedFileEntry("conf/server.conf", serverConfHash,
- serverConf.lastModified(), serverConf.length()));
+ List<FileEntry> entries = asList(addedFileEntry("conf/server.conf", serverConfHash, serverConf.lastModified(),
+ serverConf.length()));
assertHeaderEquals(currentSnapshot, createHeaders(driftDef, COVERAGE, 2));
- assertFileEntriesMatch("The entries in the current snapshot should match those in the pinned snapshot " +
- "once the resource has gone back into compliance.", entries, currentSnapshot);
+ assertFileEntriesMatch("The entries in the current snapshot should match those in the pinned snapshot "
+ + "once the resource has gone back into compliance.", entries, currentSnapshot);
+ }
+
+ @Test
+ public void updateTimestampInfoNoDriftTest() throws Exception {
+ DriftDefinition def = driftDefinition("update-timestamp-nodrift-test", resourceDir.getAbsolutePath());
+
+ File confDir = mkdir(resourceDir, "conf");
+ File server1Conf = createRandomFile(confDir, "server-1.conf");
+ String server1Hash = sha256(server1Conf);
+
+ ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), createHeaders(def, COVERAGE));
+ writer.write(addedFileEntry("conf/server-1.conf", server1Hash, -1L, -1L));
+ writer.close();
+
+ scheduleQueue.addSchedule(new DriftDetectionSchedule(resourceId(), def));
+ detector.run();
+
+ // verify that no drift change set was generated
+ File driftChangeSet = changeSet(def.getName(), DRIFT);
+ assertFalse(driftChangeSet.exists(), "Expected no drift change set " + driftChangeSet.getPath());
+
+ // verify that the coverage change set was updated with timestamp info, version is still 0
+ File coverageChangeSet = changeSet(def.getName(), COVERAGE);
+ List<FileEntry> coverageEntries = asList(addedFileEntry("conf/server-1.conf", server1Hash, server1Conf
+ .lastModified(), server1Conf.length()));
+
+ assertHeaderEquals(coverageChangeSet, createHeaders(def, COVERAGE, 0));
+ assertFileEntriesMatch("The coverage change set was not updated as expected", coverageEntries,
+ coverageChangeSet);
+ }
+
+ @Test
+ public void updateTimestampInfoDriftTest() throws Exception {
+ DriftDefinition def = driftDefinition("update-timestamp-drift-test", resourceDir.getAbsolutePath());
+
+ File confDir = mkdir(resourceDir, "conf");
+ File server1Conf = createRandomFile(confDir, "server-1.conf");
+ String server1Hash = sha256(server1Conf);
+ File server2Conf = createRandomFile(confDir, "server-2.conf");
+ String server2Hash = sha256(server2Conf);
+
+ ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), createHeaders(def, COVERAGE));
+ writer.write(addedFileEntry("conf/server-1.conf", server1Hash, -1L, -1L));
+ writer.write(addedFileEntry("conf/server-2.conf", server2Hash, -1L, -1L));
+ writer.close();
+
+ // create some drift
+ server1Conf.delete();
+ confDir.delete();
+
+ scheduleQueue.addSchedule(new DriftDetectionSchedule(resourceId(), def));
+ detector.run();
+
+ File driftChangeSet = changeSet(def.getName(), DRIFT);
+ List<FileEntry> driftEntries = asList(removedFileEntry("conf/server-1.conf", server1Hash));
+
+ // verify that the drift change set was generated
+ assertTrue(driftChangeSet.exists(), "Expected to find drift change set " + driftChangeSet.getPath());
+ assertHeaderEquals(driftChangeSet, createHeaders(def, DRIFT, 1));
+ assertFileEntriesMatch("The drift change set does not match the expected values", driftEntries, driftChangeSet);
+
+ // verify that the coverage change set was updated with timestamp info and incremented version
+ File coverageChangeSet = changeSet(def.getName(), COVERAGE);
+ List<FileEntry> coverageEntries = asList(addedFileEntry("conf/server-2.conf", server2Hash, server2Conf
+ .lastModified(), server2Conf.length()));
+
+ assertHeaderEquals(coverageChangeSet, createHeaders(def, COVERAGE, 1));
+ assertFileEntriesMatch("The coverage change set was not updated as expected", coverageEntries,
+ coverageChangeSet);
}
private void assertHeaderEquals(File changeSet, Headers expected) throws Exception {
commit 3300dff0ec830f6b4f5295240cebea76a6a00a38
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Wed Dec 14 15:46:58 2011 -0500
[BZ 760139] have live data requests return empty lists even when random runtime exceptions occur to avoid serialization issues in UI.
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 a57f522..7ffb8e1 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
@@ -724,8 +724,8 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal,
List<List<MeasurementDataNumericHighLowComposite>> findDataForCompatibleGroup(Subject subject, int groupId,
int definitionId, long beginTime, long endTime, int numPoints) {
- List<List<MeasurementDataNumericHighLowComposite>> ret = findDataForContext(subject, EntityContext
- .forGroup(groupId), definitionId, beginTime, endTime, numPoints);
+ List<List<MeasurementDataNumericHighLowComposite>> ret = findDataForContext(subject,
+ EntityContext.forGroup(groupId), definitionId, beginTime, endTime, numPoints);
return ret;
}
@@ -790,6 +790,11 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal,
AgentClient ac = agentClientManager.getAgentClient(agent);
Set<MeasurementData> values = ac.getMeasurementAgentService().getRealTimeMeasurementValue(resourceId,
createRequests(definitions));
+ //[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) {
+ values = Collections.emptySet();
+ }
return values;
}
commit 37dac4382571c22297dc4ff7497564eb7864b1fd
Author: John Sanda <jsanda(a)redhat.com>
Date: Wed Dec 14 15:24:35 2011 -0500
Add dependency needed as a result of REST integration into server/jar
Also adding itests module to enterprise profile so that it will get
built by jenkins.
diff --git a/modules/enterprise/pom.xml b/modules/enterprise/pom.xml
index e119090..eb6a9cf 100644
--- a/modules/enterprise/pom.xml
+++ b/modules/enterprise/pom.xml
@@ -73,6 +73,7 @@
<module>server/container-lib</module>
<module>server/container</module>
<module>server/client-api</module>
+ <module>server/itests</module>
</modules>
</profile>
diff --git a/modules/enterprise/server/itests/pom.xml b/modules/enterprise/server/itests/pom.xml
index f269e77..8753e6f 100644
--- a/modules/enterprise/server/itests/pom.xml
+++ b/modules/enterprise/server/itests/pom.xml
@@ -220,6 +220,12 @@
<version>2.3.18</version>
<scope>provided</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ <version>${resteasy.version}</version>
+ </dependency>
</dependencies>
<build>
commit 4f832a42b5477490cdcdaaf334846980b813ff4e
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Dec 14 14:38:43 2011 -0500
[BZ 760185] fix NPEs that occurred if user hovered over the Severity or Source Location columns while grid data was still loading (https://bugzilla.redhat.com/show_bug.cgi?id=760185)
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeDatasource.java
index c935e70..afcca26 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeDatasource.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
+ * Copyright (C) 2005-2011 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -99,22 +99,25 @@ public class EventCompositeDatasource extends RPCDataSource<EventComposite, Even
});
severityField.setShowHover(true);
severityField.setHoverCustomizer(new HoverCustomizer() {
- @Override
public String hoverHTML(Object value, ListGridRecord record, int rowNum, int colNum) {
- EventSeverity severity = EventSeverity.valueOf(record.getAttribute("severity"));
+ if (value == null) {
+ return null;
+ }
+ EventSeverity severity = EventSeverity.valueOf((String)value);
switch (severity) {
- case DEBUG:
- return MSG.common_severity_debug();
- case INFO:
- return MSG.common_severity_info();
- case WARN:
- return MSG.common_severity_warn();
- case ERROR:
- return MSG.common_severity_error();
- case FATAL:
- return MSG.common_severity_fatal();
+ case DEBUG:
+ return MSG.common_severity_debug();
+ case INFO:
+ return MSG.common_severity_info();
+ case WARN:
+ return MSG.common_severity_warn();
+ case ERROR:
+ return MSG.common_severity_error();
+ case FATAL:
+ return MSG.common_severity_fatal();
+ default:
+ return null;
}
- return null;
}
});
fields.add(severityField);
@@ -147,9 +150,11 @@ public class EventCompositeDatasource extends RPCDataSource<EventComposite, Even
});
sourceField.setShowHover(true);
sourceField.setHoverCustomizer(new HoverCustomizer() {
- @Override
public String hoverHTML(Object value, ListGridRecord record, int rowNum, int colNum) {
- String sourceLocation = record.getAttribute("source");
+ if (value == null) {
+ return null;
+ }
+ String sourceLocation = (String)value;
return (sourceLocation.length() > 40) ? sourceLocation : null;
}
});
@@ -166,7 +171,6 @@ public class EventCompositeDatasource extends RPCDataSource<EventComposite, Even
});
resourceNameField.setShowHover(true);
resourceNameField.setHoverCustomizer(new HoverCustomizer() {
-
public String hoverHTML(Object value, ListGridRecord listGridRecord, int rowNum, int colNum) {
return AncestryUtil.getResourceHoverHTML(listGridRecord, 0);
}
commit 2e75028c77cc24a2b097e82385d4c7dfb9b774d5
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue Dec 13 17:17:29 2011 -0500
[Bug 756100 - RFE: use timestamp and file size during drift detection scans]
More work on using timestamp (and filesize) info to avoid SHA digest
generation. Handle situations where the current changeset is supplied
by the server, due to pinning or agent sync. In these situations work
to replace the non-timestamped changesets with timestamped versions as
soon as possible.
diff --git a/modules/common/drift/src/main/java/org/rhq/common/drift/FileEntry.java b/modules/common/drift/src/main/java/org/rhq/common/drift/FileEntry.java
index e1766a3..564e9c5 100644
--- a/modules/common/drift/src/main/java/org/rhq/common/drift/FileEntry.java
+++ b/modules/common/drift/src/main/java/org/rhq/common/drift/FileEntry.java
@@ -29,7 +29,7 @@ import java.util.Date;
import org.rhq.core.domain.drift.DriftCategory;
import org.rhq.core.util.file.FileUtil;
-public class FileEntry implements Serializable {
+public class FileEntry implements Serializable, Comparable<FileEntry> {
private static final long serialVersionUID = 1L;
@@ -117,9 +117,23 @@ public class FileEntry implements Serializable {
return size;
}
+ public void setLastModified(Long lastModified) {
+ this.lastModified = lastModified;
+ }
+
+ public void setSize(Long size) {
+ this.size = size;
+ }
+
@Override
public String toString() {
return getClass().getSimpleName() + "[newSHA: " + newSHA + ", oldSHA: " + oldSHA + ", file: " + file
+ ", type: " + type.code() + ", lastModified: " + new Date(lastModified) + ", size: " + size + "]";
}
+
+ // Support Sets and Ordering by deferring to a String compare on the file path
+ @Override
+ public int compareTo(FileEntry o) {
+ return this.file.compareTo(o.getFile());
+ }
}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
index 10d2006..869e376 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
@@ -184,117 +184,152 @@ public class DriftDetector implements Runnable {
log.debug("Generating drift change set for " + schedule);
- File currentSnapshot = changeSetMgr.findChangeSet(schedule.getResourceId(), schedule.getDriftDefinition()
+ boolean isPinned = schedule.getDriftDefinition().isPinned();
+ final File basedir = new File(basedir(schedule.getResourceId(), schedule.getDriftDefinition()));
+
+ File currentFullSnapshot = changeSetMgr.findChangeSet(schedule.getResourceId(), schedule.getDriftDefinition()
.getName(), COVERAGE);
- File snapshotFile = currentSnapshot;
- if (schedule.getDriftDefinition().isPinned()) {
- snapshotFile = new File(snapshotFile.getParentFile(), FILE_SNAPSHOT_PINNED);
+ // unless pinned use the current full snapshot file for the definition, otherwise use the pinned snapshot
+ File snapshotFile = isPinned ? new File(currentFullSnapshot.getParentFile(), FILE_SNAPSHOT_PINNED)
+ : currentFullSnapshot;
+
+ // get a Set of all files in the detection, consider them initially new files, and we'll knock the
+ // list down as we go. As we build up FileEntries in memory this Set will shrink. It's marginally
+ // less memory than if we had both in memory at the same time.
+ final Set<File> newFiles = new HashSet<File>(1000);
+
+ // If the basedir is still valid we need to do a directory tree scan to look for newly added files
+ if (basedir.isDirectory()) {
+ DriftDefinition driftDef = schedule.getDriftDefinition();
+ List<Filter> includes = driftDef.getIncludes();
+ List<Filter> excludes = driftDef.getExcludes();
+
+ for (File dir : getScanDirectories(basedir, includes)) {
+ forEachFile(dir, new FilterFileVisitor(basedir, includes, excludes, new FileVisitor() {
+ @Override
+ public void visit(File file) {
+ if (file.canRead()) {
+ newFiles.add(file);
+ } else if (log.isDebugEnabled()) {
+ log.debug("Skipping " + file.getPath() + " as new file since it is not readable.");
+ }
+ }
+ }));
+ }
}
- final File basedir = new File(basedir(schedule.getResourceId(), schedule.getDriftDefinition()));
- final Set<File> processedFiles = new HashSet<File>();
- final List<FileEntry> snapshotEntries = new LinkedList<FileEntry>();
- final List<FileEntry> deltaEntries = new LinkedList<FileEntry>();
+ final List<FileEntry> unchangedEntries = new LinkedList<FileEntry>();
+ final List<FileEntry> removedEntries = new LinkedList<FileEntry>();
+ final List<FileEntry> cantReadEntries = new LinkedList<FileEntry>();
+ final List<FileEntry> changedEntries = new LinkedList<FileEntry>();
+ final List<FileEntry> changedPinnedEntries = isPinned ? new LinkedList<FileEntry>() : null;
- ChangeSetReader coverageReader = null;
+ ChangeSetReader snapshotReader = null;
int newVersion;
+ boolean updateSnapshot = false;
try {
- coverageReader = changeSetMgr.getChangeSetReader(snapshotFile);
+ snapshotReader = changeSetMgr.getChangeSetReader(snapshotFile);
if (!basedir.exists()) {
log.warn("The base directory [" + basedir.getAbsolutePath() + "] for " + schedule + " does not exist.");
}
- if (schedule.getDriftDefinition().isPinned()) {
- ChangeSetReader snapshotReader = null;
+ if (isPinned) {
+ // If pinned we compare against the pinned snapshot but we need to know the current snapshot version,
+ // get it from the current full snapshot.
+ ChangeSetReader currentFullSnapshotReader = null;
try {
- snapshotReader = changeSetMgr.getChangeSetReader(currentSnapshot);
- newVersion = snapshotReader.getHeaders().getVersion() + 1;
+ currentFullSnapshotReader = changeSetMgr.getChangeSetReader(currentFullSnapshot);
+ newVersion = currentFullSnapshotReader.getHeaders().getVersion() + 1;
} finally {
- snapshotReader.close();
+ currentFullSnapshotReader.close();
}
} else {
- newVersion = coverageReader.getHeaders().getVersion() + 1;
+ newVersion = snapshotReader.getHeaders().getVersion() + 1;
}
// First look for files that have either been modified or deleted
- scanForModifiedOrDeletedFiles(schedule, basedir, processedFiles, snapshotEntries, deltaEntries,
- coverageReader);
+ updateSnapshot = scanSnapshotFiles(schedule, basedir, snapshotReader, newFiles, unchangedEntries,
+ removedEntries, cantReadEntries, changedEntries, changedPinnedEntries);
+
} finally {
- coverageReader.close();
+ snapshotReader.close();
}
- // If the basedir is still valid we need to do a directory tree scan to look for newly added files
- if (basedir.isDirectory()) {
- DriftDefinition driftDef = schedule.getDriftDefinition();
- List<Filter> includes = driftDef.getIncludes();
- List<Filter> excludes = driftDef.getExcludes();
+ // if necessary, re-write the pinned snapshot file because we've updated timestamp/filesize info, which
+ // on subsequent detection runs will help us avoid SHA generation. It must maintain the same entries.
+ if (isPinned && updateSnapshot) {
+ changedPinnedEntries.addAll(unchangedEntries);
- for (File dir : getScanDirectories(basedir, includes)) {
- forEachFile(dir, new FilterFileVisitor(basedir, includes, excludes, new FileVisitor() {
- @Override
- public void visit(File file) {
- try {
- if (processedFiles.contains(file)) {
- return;
- }
+ backupAndDeleteCurrentSnapshot(snapshotFile);
+ updatePinnedSnapshot(schedule, snapshotFile, changedPinnedEntries);
+ }
- if (!file.canRead()) {
- if (log.isDebugEnabled()) {
- log.debug("Skipping " + file.getPath() + " since it is not readable.");
- }
- return;
- }
+ final List<FileEntry> snapshotEntries = new LinkedList<FileEntry>(unchangedEntries);
+ snapshotEntries.addAll(changedEntries);
- if (log.isInfoEnabled()) {
- log.info("Detected added file for " + schedule + " --> " + file.getAbsolutePath());
- }
+ final List<FileEntry> deltaEntries = new LinkedList<FileEntry>(changedEntries);
+ deltaEntries.addAll(removedEntries);
+ deltaEntries.addAll(cantReadEntries);
- FileEntry newEntry = addedFileEntry(relativePath(basedir, file), sha256(file), file
- .lastModified(), file.length());
- deltaEntries.add(newEntry);
- snapshotEntries.add(newEntry);
- } catch (IOException e) {
- log.error("An error occurred while generating a drift change set for " + schedule + ": "
- + e.getMessage());
- throw new DriftDetectionException("An error occurred while generating a drift change set",
- e);
- }
- }
- }));
+ for (File file : newFiles) {
+ try {
+ if (log.isInfoEnabled()) {
+ log.info("Detected added file for " + schedule + " --> " + file.getAbsolutePath());
+ }
+
+ FileEntry newEntry = addedFileEntry(relativePath(basedir, file), sha256(file), file.lastModified(),
+ file.length());
+
+ deltaEntries.add(newEntry);
+ snapshotEntries.add(newEntry);
+
+ } catch (IOException e) {
+ log.error("An error occurred while generating a drift change set for " + schedule + ": "
+ + e.getMessage());
+ throw new DriftDetectionException("An error occurred while generating a drift change set", e);
}
}
if (deltaEntries.isEmpty()) {
- summary.setNewSnapshot(currentSnapshot);
-
- // If nothing has changed, there is no need to add/update any files
- // unless the definition is pinned in which case we need to reset
- // the current snapshot to match the pinned snapshot. Note though
- // that we increment the snapshot version in order to let the server
- // know about the state change.
- // if no timestamp must re-gen the files.
- if (schedule.getDriftDefinition().isPinned() && newVersion > 1
- && !isPreviousChangeSetEmpty(schedule.getResourceId(), schedule.getDriftDefinition())) {
- currentSnapshot.delete();
- File newSnapshot = updateCurrentSnapshot(schedule, snapshotEntries, newVersion);
-
- updateDeltaSnapshot(summary, schedule, deltaEntries, newVersion, currentSnapshot, newSnapshot);
- // TODO report back to the server that we are back in compliance
+ File newSnapshot = currentFullSnapshot;
+
+ if (!isPinned) {
+ // If unpinned and there is no detected drift then we generally don't need to add/update any files.
+ // But, if we have timestamp/filesize updates then we want to replace the current snapshot with
+ // the updated entries, so we can avoid SHA generation on subsequent runs.
+ if (updateSnapshot) {
+ currentFullSnapshot.delete();
+ newSnapshot = updateCurrentSnapshot(schedule, snapshotEntries, newVersion - 1);
+ }
+ } else {
+ // If pinned and returning to compliance (meaning no drift now but the previous snapshot did have drift)
+ // then we need to reset the current snapshot to match the pinned snapshot. Note though that we
+ // increment the snapshot version in order to let the server know about the state change.
+ if (newVersion > 1
+ && !isPreviousChangeSetEmpty(schedule.getResourceId(), schedule.getDriftDefinition())) {
+ currentFullSnapshot.delete();
+ newSnapshot = updateCurrentSnapshot(schedule, snapshotEntries, newVersion);
+
+ updateDeltaSnapshot(summary, schedule, deltaEntries, newVersion, currentFullSnapshot, newSnapshot);
+ }
}
+
+ summary.setNewSnapshot(newSnapshot);
+
} else {
- if (schedule.getDriftDefinition().isPinned() && newVersion > 1
- && isSameAsPreviousChangeSet(deltaEntries, currentSnapshot)) {
- // if we are still out of compliance just report, we report a
- // repeat change set to indicate no changes but also still out
- // of compliance.
+ // if there is drift, but we're pinned and the drift is the same as the previous detection, just
+ // mark it as a repeat to indicate that we're out of compliance but not in any new way.
+ if (isPinned && newVersion > 1 && isSameAsPreviousChangeSet(deltaEntries, currentFullSnapshot)) {
summary.setVersion(newVersion - 1);
summary.setRepeat(true);
+
return;
}
- File oldSnapshot = backupAndDeleteCurrentSnapshot(currentSnapshot);
+ // otherwise, generate a new current snapshot, and a snapshot delta reflecting the latest drift
+ File oldSnapshot = backupAndDeleteCurrentSnapshot(currentFullSnapshot);
File newSnapshot = updateCurrentSnapshot(schedule, snapshotEntries, newVersion);
updateDeltaSnapshot(summary, schedule, deltaEntries, newVersion, oldSnapshot, newSnapshot);
@@ -321,55 +356,88 @@ public class DriftDetector implements Runnable {
return directories;
}
- private void scanForModifiedOrDeletedFiles(DriftDetectionSchedule schedule, File basedir, Set<File> processedFiles,
- List<FileEntry> snapshotEntries, List<FileEntry> deltaEntries, ChangeSetReader coverageReader)
+ /**
+ * Process the entries for the snapshotReader. Each entry will be placed in one of the various Lists depending
+ * on what bucket it fall into.
+ * @return true if unchangedEntries (meaning no drift) had timestamp/filesize info updated, in which case the
+ * snapshot should be re-written to disk even if there was no drift.
+ * @throws IOException
+ */
+ private boolean scanSnapshotFiles(DriftDetectionSchedule schedule, File basedir, ChangeSetReader snapshotReader,
+ Set<File> newFiles, List<FileEntry> unchangedEntries, List<FileEntry> removedEntries,
+ List<FileEntry> cantReadEntries, List<FileEntry> modifiedEntries, List<FileEntry> changedPinnedEntries)
throws IOException {
- for (FileEntry entry : coverageReader) {
+ boolean result = false;
+
+ for (FileEntry entry : snapshotReader) {
File file = new File(basedir, entry.getFile());
+ newFiles.remove(file);
+
if (!file.exists()) {
// The file has been deleted since the last scan
if (log.isDebugEnabled()) {
log.debug("Detected deleted file for " + schedule + " --> " + file.getAbsolutePath());
}
- deltaEntries.add(removedFileEntry(entry.getFile(), entry.getNewSHA()));
+ removedEntries.add(removedFileEntry(entry.getFile(), entry.getNewSHA()));
+
+ if (null != changedPinnedEntries) {
+ changedPinnedEntries.add(entry);
+ }
+
+ continue;
+
} else if (!file.canRead()) {
- processedFiles.add(file);
if (log.isDebugEnabled()) {
log.debug(file.getPath() + " is no longer readable. Treating it as a deleted file.");
}
- deltaEntries.add(removedFileEntry(entry.getFile(), entry.getNewSHA()));
+ cantReadEntries.add(removedFileEntry(entry.getFile(), entry.getNewSHA()));
+
+ if (null != changedPinnedEntries) {
+ changedPinnedEntries.add(entry);
+ }
+
+ continue;
+
} else {
- processedFiles.add(file);
- // if we do not have the last modification time and the file size, then we
- // have to compare SHAs. We can wind up without a timestamp of a file size
- // when the agent is restarted and the data directory is purged. The server
- // sends snapshots down to the agent and since the server does not store the
- // file modification time or size, the fields will get initialized to -1.
- if (entry.getLastModified() == -1 || entry.getSize() == -1) {
- String currentSHA = sha256(file);
- if (!entry.getNewSHA().equals(currentSHA)) {
- FileEntry modifiedEntry = changedFileEntry(entry.getFile(), entry.getNewSHA(), currentSHA, file
- .lastModified(), file.length());
- deltaEntries.add(modifiedEntry);
- snapshotEntries.add(modifiedEntry);
- }
- } else if (entry.getLastModified() != -1 && entry.getSize() != -1
- && (entry.getLastModified() != file.lastModified() || entry.getSize() != file.length())) {
- if (log.isDebugEnabled()) {
- log.debug("Detected modified file for " + schedule + " --> " + file.getAbsolutePath());
- }
- String currentSHA = sha256(file);
+ String currentSHA = null;
+ boolean isModified = false;
+
+ // perform a SHA comparison if we are unable to compare size and lastModified or if the
+ // size or lastModified test fails. We may not have size of lastModified values for the
+ // entry when the current snapshot was provided by the server, either due to a synch or
+ // pinning scenario. The server does not store that information and will provide -1 for defaults.
+ if (entry.getLastModified() == -1 || entry.getSize() == -1
+ || entry.getLastModified() != file.lastModified() || entry.getSize() != file.length()) {
+
+ currentSHA = sha256(file);
+ isModified = !entry.getNewSHA().equals(currentSHA);
+ }
+
+ if (isModified) {
FileEntry modifiedEntry = changedFileEntry(entry.getFile(), entry.getNewSHA(), currentSHA, file
.lastModified(), file.length());
- deltaEntries.add(modifiedEntry);
- snapshotEntries.add(modifiedEntry);
+ modifiedEntries.add(modifiedEntry);
+
+ if (null != changedPinnedEntries) {
+ changedPinnedEntries.add(entry);
+ }
+
} else {
- // The file has not changed
- snapshotEntries.add(entry);
+ if (-1 == entry.getLastModified()) {
+ entry.setLastModified(file.lastModified());
+ result = true;
+ }
+ if (-1 == entry.getSize()) {
+ entry.setSize(file.length());
+ result = true;
+ }
+ unchangedEntries.add(entry);
}
}
}
+
+ return result;
}
@SuppressWarnings("unused")
@@ -449,6 +517,26 @@ public class DriftDetector implements Runnable {
}
}
+ private File updatePinnedSnapshot(DriftDetectionSchedule schedule, File pinnedSnapshot,
+ List<FileEntry> snapshotEntries) throws IOException {
+
+ ChangeSetWriter newSnapshotWriter = null;
+
+ try {
+ Headers snapshotHeaders = createHeaders(schedule, COVERAGE, 0);
+ newSnapshotWriter = changeSetMgr.getChangeSetWriter(pinnedSnapshot, snapshotHeaders);
+
+ for (FileEntry entry : snapshotEntries) {
+ newSnapshotWriter.write(entry);
+ }
+
+ return pinnedSnapshot;
+
+ } finally {
+ newSnapshotWriter.close();
+ }
+ }
+
private boolean isSameAsPreviousChangeSet(List<FileEntry> entries, File currentSnapsotFile) throws IOException {
HashMap<String, FileEntry> entriesMap = new HashMap<String, FileEntry>();
for (FileEntry e : entries) {
commit ee66d10c7c3dee5a9c9bd102d9ea2db347e0e769
Author: John Sanda <jsanda(a)redhat.com>
Date: Tue Dec 13 17:12:32 2011 -0500
[BZ 767328] Make sure that each drift def is loaded into the persistence context
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftTemplateManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftTemplateManagerBean.java
index 361eb44..9a1c980 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftTemplateManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftTemplateManagerBean.java
@@ -19,26 +19,11 @@
package org.rhq.enterprise.server.drift;
-import static javax.ejb.TransactionAttributeType.NEVER;
-import static org.rhq.core.domain.common.EntityContext.forResource;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
-import static org.rhq.core.domain.drift.DriftConfigurationDefinition.DriftHandlingMode.normal;
-
-import javax.ejb.EJB;
-import javax.ejb.Stateless;
-import javax.ejb.TransactionAttribute;
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.criteria.DriftDefinitionCriteria;
import org.rhq.core.domain.criteria.DriftDefinitionTemplateCriteria;
-import org.rhq.core.domain.drift.DriftDefinition;
-import org.rhq.core.domain.drift.DriftDefinitionComparator;
-import org.rhq.core.domain.drift.DriftDefinitionTemplate;
-import org.rhq.core.domain.drift.DriftSnapshot;
-import org.rhq.core.domain.drift.DriftSnapshotRequest;
+import org.rhq.core.domain.drift.*;
import org.rhq.core.domain.drift.dto.DriftChangeSetDTO;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageList;
@@ -49,6 +34,17 @@ import org.rhq.enterprise.server.resource.ResourceTypeNotFoundException;
import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
import org.rhq.enterprise.server.util.CriteriaQueryRunner;
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+import javax.ejb.TransactionAttribute;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+import static javax.ejb.TransactionAttributeType.NEVER;
+import static org.rhq.core.domain.common.EntityContext.forResource;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
+import static org.rhq.core.domain.drift.DriftConfigurationDefinition.DriftHandlingMode.normal;
+
@Stateless
public class DriftTemplateManagerBean implements DriftTemplateManagerLocal, DriftTemplateManagerRemote {
@@ -205,13 +201,15 @@ public class DriftTemplateManagerBean implements DriftTemplateManagerLocal, Drif
DriftDefinition templateDef = template.getTemplateDefinition();
for (DriftDefinition resourceDef : template.getDriftDefinitions()) {
- if (resourceDef.isAttached()) {
- resourceDef.setInterval(templateDef.getInterval());
- resourceDef.setDriftHandlingMode(templateDef.getDriftHandlingMode());
- resourceDef.setEnabled(templateDef.isEnabled());
+ DriftDefinition driftDef = entityMgr.find(DriftDefinition.class, resourceDef.getId());
+ if (driftDef.isAttached()) {
+ driftDef.setInterval(templateDef.getInterval());
+ driftDef.setDriftHandlingMode(templateDef.getDriftHandlingMode());
+ driftDef.setEnabled(templateDef.isEnabled());
- driftMgr.updateDriftDefinition(subject, forResource(resourceDef.getResource().getId()), resourceDef);
+ driftMgr.updateDriftDefinition(subject, forResource(driftDef.getResource().getId()), driftDef);
}
}
}
+
}
commit bf599134469592012e7ee69a00354cc815e7db8e
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue Dec 13 16:22:13 2011 -0500
Make sure the drift def id is also in the copy so it can be applied to
generated changeset headers.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetectionSchedule.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetectionSchedule.java
index 8ddfc03..60fb35b 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetectionSchedule.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetectionSchedule.java
@@ -43,6 +43,7 @@ public class DriftDetectionSchedule implements Comparable<DriftDetectionSchedule
public DriftDetectionSchedule copy() {
DriftDetectionSchedule copy = new DriftDetectionSchedule(resourceId, new DriftDefinition(driftDef
.getConfiguration().deepCopyWithoutProxies()));
+ copy.driftDef.setId(driftDef.getId());
copy.nextScan = nextScan;
return copy;
}
commit 9b42a3a83b51bdce587b6841774e373b25343e5a
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Dec 13 14:48:51 2011 -0500
baseDir might be null, so don't assume it isn't
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerBean.java
index c06f7a4..12c7233 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerBean.java
@@ -68,8 +68,11 @@ import org.rhq.core.domain.drift.DriftChangeSetCategory;
import org.rhq.core.domain.drift.DriftComplianceStatus;
import org.rhq.core.domain.drift.DriftComposite;
import org.rhq.core.domain.drift.DriftConfigurationDefinition;
+import org.rhq.core.domain.drift.DriftConfigurationDefinition.DriftHandlingMode;
import org.rhq.core.domain.drift.DriftDefinition;
+import org.rhq.core.domain.drift.DriftDefinition.BaseDirectory;
import org.rhq.core.domain.drift.DriftDefinitionComparator;
+import org.rhq.core.domain.drift.DriftDefinitionComparator.CompareMode;
import org.rhq.core.domain.drift.DriftDefinitionComposite;
import org.rhq.core.domain.drift.DriftDefinitionTemplate;
import org.rhq.core.domain.drift.DriftDetails;
@@ -78,9 +81,6 @@ import org.rhq.core.domain.drift.DriftSnapshot;
import org.rhq.core.domain.drift.DriftSnapshotRequest;
import org.rhq.core.domain.drift.FileDiffReport;
import org.rhq.core.domain.drift.Filter;
-import org.rhq.core.domain.drift.DriftConfigurationDefinition.DriftHandlingMode;
-import org.rhq.core.domain.drift.DriftDefinition.BaseDirectory;
-import org.rhq.core.domain.drift.DriftDefinitionComparator.CompareMode;
import org.rhq.core.domain.drift.dto.DriftChangeSetDTO;
import org.rhq.core.domain.drift.dto.DriftDTO;
import org.rhq.core.domain.drift.dto.DriftFileDTO;
@@ -803,7 +803,7 @@ public class DriftManagerBean implements DriftManagerLocal, DriftManagerRemote {
if (null == baseDir
|| !baseDir.getValueName().matches(DriftConfigurationDefinition.PROP_BASEDIR_PATH_REGEX_PATTERN)) {
throw new IllegalArgumentException(
- "Drift definition base directory is null or contains invalid characters: " + baseDir.getValueName());
+ "Drift definition base directory is null or contains invalid characters: " + baseDir);
}
List<List<Filter>> filtersList = new ArrayList<List<Filter>>(2);
filtersList.add(driftDef.getIncludes());
commit 1c2b7c69036191a7a79a9421aba63dff18cf0a8b
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Dec 13 13:46:12 2011 -0500
[BZ 767263] don't assume there is always a template
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionDataSource.java
index b29e9a6..bece740 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionDataSource.java
@@ -198,6 +198,9 @@ public class DriftDefinitionDataSource extends RPCDataSource<DriftDefinitionComp
templateField.setCellFormatter(new CellFormatter() {
public String format(Object o, ListGridRecord listGridRecord, int i, int i1) {
DriftDefinition def = (DriftDefinition) listGridRecord.getAttributeAsObject(ATTR_ENTITY);
+ if (null == def.getTemplate()) {
+ return MSG.common_val_none();
+ }
if (null != globalPermissions && globalPermissions.contains(Permission.MANAGE_SETTINGS)) {
int typeId = def.getResource().getResourceType().getId();
int templateId = def.getTemplate().getId();
@@ -422,7 +425,11 @@ public class DriftDefinitionDataSource extends RPCDataSource<DriftDefinitionComp
record.setAttribute(ATTR_IS_PINNED, def.isPinned() ? ImageManager.getPinnedIcon() : ImageManager
.getUnpinnedIcon());
record.setAttribute(ATTR_ATTACHED, def.isAttached() ? MSG.common_val_yes() : MSG.common_val_no());
- record.setAttribute(ATTR_TEMPLATE, def.getTemplate().getName());
+ if (def.getTemplate() != null) {
+ record.setAttribute(ATTR_TEMPLATE, def.getTemplate().getName());
+ } else {
+ record.setAttribute(ATTR_TEMPLATE, MSG.common_val_none());
+ }
record.setAttribute(ATTR_CHANGE_SET_VERSION, (null != changeSet) ? String.valueOf(changeSet.getVersion()) : MSG
.common_label_none());
commit b664d35951234f42400d90d1b5c7b477b0e9d3d5
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Tue Dec 13 13:05:19 2011 -0500
minor - fix some typos in javadoc
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainerConfiguration.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainerConfiguration.java
index d786ee3..570f7da 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainerConfiguration.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainerConfiguration.java
@@ -453,7 +453,7 @@ public class PluginContainerConfiguration {
}
/**
- * When measurement's are scheduled for collection, the collection will be performed by threads from a thread pool.
+ * When measurements are scheduled for collection, the collection will be performed by threads from a thread pool.
* This defines the number of threads within that thread pool, effectively defining the number of measurements that
* can be collected concurrently.
*
@@ -465,9 +465,9 @@ public class PluginContainerConfiguration {
}
/**
- * Defines the number of threads that can concurrent collection measurements.
+ * Defines the number of threads that can concurrently collection measurements.
*
- * @param size the new size of the threadpool
+ * @param size the new size of the thread pool
*/
public void setMeasurementCollectionThreadPoolSize(int size) {
configuration.put(MEASUREMENT_COLLECTION_THREADCOUNT_PROP, Integer.valueOf(size));
@@ -609,7 +609,7 @@ public class PluginContainerConfiguration {
/**
* Defines the number of threads that can concurrent execute operations.
*
- * @param size the new size of the threadpool
+ * @param size the new size of the thread pool
*/
public void setOperationInvokerThreadPoolSize(int size) {
configuration.put(OPERATION_INVOKER_THREADCOUNT_PROP, Integer.valueOf(size));
commit 54ccb75ffb746b3e167f8fdfb2fba3cc70dc13e2
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Dec 12 15:53:14 2011 -0500
Ensure we have both the timestamp and the filesize before we skip using
a SHA test.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
index 11a2d85..10d2006 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
@@ -346,7 +346,7 @@ public class DriftDetector implements Runnable {
// when the agent is restarted and the data directory is purged. The server
// sends snapshots down to the agent and since the server does not store the
// file modification time or size, the fields will get initialized to -1.
- if (entry.getLastModified() == -1 && entry.getSize() == -1) {
+ if (entry.getLastModified() == -1 || entry.getSize() == -1) {
String currentSHA = sha256(file);
if (!entry.getNewSHA().equals(currentSHA)) {
FileEntry modifiedEntry = changedFileEntry(entry.getFile(), entry.getNewSHA(), currentSHA, file
commit 610d9447060444806f5fd27c29a5f118195636c0
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Dec 12 15:51:46 2011 -0500
Just some cleanup
- remove unused/obsolete methods from ChangeSetManager and the impl
- move some commonly referenced filenames into constants
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ChangeSetManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ChangeSetManager.java
index 1fc9fe9..5117ab1 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ChangeSetManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ChangeSetManager.java
@@ -26,7 +26,6 @@ import org.rhq.common.drift.ChangeSetReader;
import org.rhq.common.drift.ChangeSetWriter;
import org.rhq.common.drift.Headers;
import org.rhq.core.domain.drift.DriftChangeSetCategory;
-import org.rhq.core.domain.drift.DriftDefinition;
public interface ChangeSetManager {
@@ -66,11 +65,4 @@ public interface ChangeSetManager {
ChangeSetWriter getChangeSetWriter(int resourceId, Headers headers) throws IOException;
ChangeSetWriter getChangeSetWriter(File changeSetFile, Headers headers) throws IOException;
-
- ChangeSetWriter getChangeSetWriterForUpdate(int resourceId, Headers headers) throws IOException;
-
- void updateChangeSet(int resourceId, Headers headers) throws IOException;
-
- void addFileToChangeSet(int resourceId, DriftDefinition driftDefinition, File file);
-
}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ChangeSetManagerImpl.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ChangeSetManagerImpl.java
index 132a7ca..97e92d3 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ChangeSetManagerImpl.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ChangeSetManagerImpl.java
@@ -21,11 +21,7 @@ package org.rhq.core.pc.drift;
import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
import org.rhq.common.drift.ChangeSetReader;
@@ -34,8 +30,6 @@ import org.rhq.common.drift.ChangeSetWriter;
import org.rhq.common.drift.ChangeSetWriterImpl;
import org.rhq.common.drift.Headers;
import org.rhq.core.domain.drift.DriftChangeSetCategory;
-import org.rhq.core.domain.drift.DriftDefinition;
-import org.rhq.core.util.stream.StreamUtil;
public class ChangeSetManagerImpl implements ChangeSetManager {
@@ -51,13 +45,13 @@ public class ChangeSetManagerImpl implements ChangeSetManager {
if (changeSetDir == null || !changeSetDir.exists()) {
return false;
}
- return new File(changeSetDir, "changeset.txt").exists();
+ return new File(changeSetDir, DriftDetector.FILE_CHANGESET_FULL).exists();
}
@Override
public File findChangeSet(int resourceId, String driftDefinitionName) throws IOException {
File changeSetDir = findChangeSetDir(resourceId, driftDefinitionName);
- File changeSetFile = new File(changeSetDir, "changeset.txt");
+ File changeSetFile = new File(changeSetDir, DriftDetector.FILE_CHANGESET_FULL);
if (changeSetFile.exists()) {
return changeSetFile;
@@ -76,9 +70,9 @@ public class ChangeSetManagerImpl implements ChangeSetManager {
switch (type) {
case COVERAGE:
- return new File(changeSetDir, "changeset.txt");
+ return new File(changeSetDir, DriftDetector.FILE_CHANGESET_FULL);
case DRIFT:
- return new File(changeSetDir, "drift-changeset.txt");
+ return new File(changeSetDir, DriftDetector.FILE_CHANGESET_DELTA);
default:
throw new IllegalArgumentException(type + " is not a recognized, supported change set type.");
}
@@ -111,9 +105,9 @@ public class ChangeSetManagerImpl implements ChangeSetManager {
File changeSet;
if (headers.getType() == COVERAGE) {
- changeSet = new File(changeSetDir, "changeset.txt");
+ changeSet = new File(changeSetDir, DriftDetector.FILE_CHANGESET_FULL);
} else {
- changeSet = new File(changeSetDir, "drift-changeset.txt");
+ changeSet = new File(changeSetDir, DriftDetector.FILE_CHANGESET_DELTA);
}
return new ChangeSetWriterImpl(changeSet, headers);
}
@@ -123,35 +117,6 @@ public class ChangeSetManagerImpl implements ChangeSetManager {
return new ChangeSetWriterImpl(changeSetFile, headers);
}
- @Override
- public ChangeSetWriter getChangeSetWriterForUpdate(int resourceId, Headers headers) throws IOException {
- File resourceDir = new File(changeSetsDir, Integer.toString(resourceId));
- File changeSetDir = new File(resourceDir, headers.getDriftDefinitionName());
-
- return new ChangeSetWriterImpl(new File(changeSetDir, "changeset.working"), headers);
- }
-
- @Override
- public void updateChangeSet(int resourceId, Headers headers) throws IOException {
- File resourceDir = new File(changeSetsDir, Integer.toString(resourceId));
- File changeSetDir = new File(resourceDir, headers.getDriftDefinitionName());
- File newChangeSet = new File(changeSetDir, "changeset.working");
- File changeSet = new File(changeSetDir, "changeset.txt");
-
- if (!newChangeSet.exists()) {
- return;
- }
-
- changeSet.delete();
-
- StreamUtil.copy(new BufferedInputStream(new FileInputStream(newChangeSet)), new BufferedOutputStream(
- new FileOutputStream(changeSet)));
- }
-
- @Override
- public void addFileToChangeSet(int resourceId, DriftDefinition driftDefinition, File file) {
- }
-
private File findChangeSetDir(int resourceId, String driftDefinitionName) {
File resourceDir = new File(changeSetsDir, Integer.toString(resourceId));
if (!resourceDir.exists()) {
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
index 848ae93..11a2d85 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
@@ -19,8 +19,26 @@
package org.rhq.core.pc.drift;
+import static org.rhq.common.drift.FileEntry.addedFileEntry;
+import static org.rhq.common.drift.FileEntry.changedFileEntry;
+import static org.rhq.common.drift.FileEntry.removedFileEntry;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.DRIFT;
+import static org.rhq.core.util.file.FileUtil.copyFile;
+import static org.rhq.core.util.file.FileUtil.forEachFile;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.rhq.common.drift.ChangeSetReader;
import org.rhq.common.drift.ChangeSetWriter;
import org.rhq.common.drift.FileEntry;
@@ -31,20 +49,13 @@ import org.rhq.core.domain.drift.Filter;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.file.FileVisitor;
-import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.util.*;
-
-import static org.rhq.common.drift.FileEntry.*;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.DRIFT;
-import static org.rhq.core.util.file.FileUtil.copyFile;
-import static org.rhq.core.util.file.FileUtil.forEachFile;
-
public class DriftDetector implements Runnable {
private Log log = LogFactory.getLog(DriftDetector.class);
+ static final String FILE_CHANGESET_FULL = "changeset.txt";
+ static final String FILE_CHANGESET_DELTA = "drift-changeset.txt";
+ static final String FILE_SNAPSHOT_PINNED = "snapshot.pinned";
+
private ScheduleQueue scheduleQueue;
private ChangeSetManager changeSetMgr;
@@ -178,7 +189,7 @@ public class DriftDetector implements Runnable {
File snapshotFile = currentSnapshot;
if (schedule.getDriftDefinition().isPinned()) {
- snapshotFile = new File(snapshotFile.getParentFile(), "snapshot.pinned");
+ snapshotFile = new File(snapshotFile.getParentFile(), FILE_SNAPSHOT_PINNED);
}
final File basedir = new File(basedir(schedule.getResourceId(), schedule.getDriftDefinition()));
@@ -240,14 +251,16 @@ public class DriftDetector implements Runnable {
log.info("Detected added file for " + schedule + " --> " + file.getAbsolutePath());
}
- FileEntry newEntry = addedFileEntry(relativePath(basedir, file), sha256(file),
- file.lastModified(), file.length());
- deltaEntries.add(newEntry);
- snapshotEntries.add(newEntry);
- } catch (IOException e) {
- log.error("An error occurred while generating a drift change set for " + schedule + ": "
- + e.getMessage());
- throw new DriftDetectionException("An error occurred while generating a drift change set", e);
+ FileEntry newEntry = addedFileEntry(relativePath(basedir, file), sha256(file), file
+ .lastModified(), file.length());
+ deltaEntries.add(newEntry);
+ snapshotEntries.add(newEntry);
+ } catch (IOException e) {
+ log.error("An error occurred while generating a drift change set for " + schedule + ": "
+ + e.getMessage());
+ throw new DriftDetectionException("An error occurred while generating a drift change set",
+ e);
+ }
}
}));
}
@@ -261,6 +274,7 @@ public class DriftDetector implements Runnable {
// the current snapshot to match the pinned snapshot. Note though
// that we increment the snapshot version in order to let the server
// know about the state change.
+ // if no timestamp must re-gen the files.
if (schedule.getDriftDefinition().isPinned() && newVersion > 1
&& !isPreviousChangeSetEmpty(schedule.getResourceId(), schedule.getDriftDefinition())) {
currentSnapshot.delete();
@@ -335,19 +349,19 @@ public class DriftDetector implements Runnable {
if (entry.getLastModified() == -1 && entry.getSize() == -1) {
String currentSHA = sha256(file);
if (!entry.getNewSHA().equals(currentSHA)) {
- FileEntry modifiedEntry = changedFileEntry(entry.getFile(), entry.getNewSHA(), currentSHA,
- file.lastModified(), file.length());
+ FileEntry modifiedEntry = changedFileEntry(entry.getFile(), entry.getNewSHA(), currentSHA, file
+ .lastModified(), file.length());
deltaEntries.add(modifiedEntry);
snapshotEntries.add(modifiedEntry);
}
- } else if (entry.getLastModified() != -1 && entry.getSize() != -1 &&
- (entry.getLastModified() != file.lastModified() || entry.getSize() != file.length())) {
+ } else if (entry.getLastModified() != -1 && entry.getSize() != -1
+ && (entry.getLastModified() != file.lastModified() || entry.getSize() != file.length())) {
if (log.isDebugEnabled()) {
log.debug("Detected modified file for " + schedule + " --> " + file.getAbsolutePath());
}
String currentSHA = sha256(file);
- FileEntry modifiedEntry = changedFileEntry(entry.getFile(), entry.getNewSHA(), currentSHA,
- file.lastModified(), file.length());
+ FileEntry modifiedEntry = changedFileEntry(entry.getFile(), entry.getNewSHA(), currentSHA, file
+ .lastModified(), file.length());
deltaEntries.add(modifiedEntry);
snapshotEntries.add(modifiedEntry);
} else {
@@ -443,7 +457,7 @@ public class DriftDetector implements Runnable {
ChangeSetReader reader = null;
try {
- File deltaChangeSet = new File(currentSnapsotFile.getParentFile(), "drift-changeset.txt");
+ File deltaChangeSet = new File(currentSnapsotFile.getParentFile(), FILE_CHANGESET_DELTA);
reader = changeSetMgr.getChangeSetReader(deltaChangeSet);
int numEntries = 0;
@@ -511,7 +525,7 @@ public class DriftDetector implements Runnable {
writer = null;
}
if (schedule.getDriftDefinition().isPinned()) {
- copyFile(snapshot, new File(snapshot.getParentFile(), "snapshot.pinned"));
+ copyFile(snapshot, new File(snapshot.getParentFile(), FILE_SNAPSHOT_PINNED));
}
summary.setNewSnapshot(snapshot);
} finally {
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 1182407..386ad73 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
@@ -201,7 +201,7 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
// change set.
DriftSnapshot pinnedSnapshot = driftServer.getSnapshot(driftDefinition.getId(), 0, 0);
Headers pinnedHeaders = createHeaders(resource.getId(), driftDefinition);
- File pinnedSnapshotFile = new File(currentSnapshotFile.getParent(), "snapshot.pinned");
+ File pinnedSnapshotFile = new File(currentSnapshotFile.getParent(), DriftDetector.FILE_SNAPSHOT_PINNED);
log.info("Preparing to write pinned snapshot to disk for "
+ toString(resource.getId(), driftDefinition));
writeSnapshotToFile(pinnedSnapshot, pinnedSnapshotFile, pinnedHeaders);
@@ -212,7 +212,7 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
// drift that has already been reported to the server.
DriftSnapshot deltaSnapshot = driftServer.getSnapshot(driftDefinition.getId(), snapshot
.getVersion(), snapshot.getVersion());
- File deltaFile = new File(currentSnapshotFile.getParentFile(), "drift-changeset.txt");
+ File deltaFile = new File(currentSnapshotFile.getParentFile(), DriftDetector.FILE_CHANGESET_DELTA);
Headers deltaHeaders = createHeaders(resource.getId(), driftDefinition);
deltaHeaders.setVersion(snapshot.getVersion());
deltaHeaders.setType(DRIFT);
@@ -546,7 +546,7 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
public void run() {
File currentSnapshot = changeSetMgr.findChangeSet(schedule.getResourceId(), schedule
.getDriftDefinition().getName(), COVERAGE);
- File pinnedSnapshot = new File(currentSnapshot.getParentFile(), "snapshot.pinned");
+ File pinnedSnapshot = new File(currentSnapshot.getParentFile(), DriftDetector.FILE_SNAPSHOT_PINNED);
pinnedSnapshot.delete();
if (log.isDebugEnabled()) {
@@ -561,7 +561,7 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
@Override
public void updateDriftDetection(int resourceId, DriftDefinition driftDef, DriftSnapshot driftSnapshot) {
File currentSnapshot = changeSetMgr.findChangeSet(resourceId, driftDef.getName(), COVERAGE);
- File pinnedSnapshot = new File(currentSnapshot.getParentFile(), "snapshot.pinned");
+ File pinnedSnapshot = new File(currentSnapshot.getParentFile(), DriftDetector.FILE_SNAPSHOT_PINNED);
Headers headers = createHeaders(resourceId, driftDef);
try {
@@ -777,8 +777,8 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
writer.write(addedFileEntry(drift.getPath(), drift.getNewDriftFile().getHashId(), -1L, -1L));
break;
case FILE_CHANGED:
- writer.write(changedFileEntry(drift.getPath(), drift.getOldDriftFile().getHashId(),
- drift.getNewDriftFile().getHashId(), -1L, -1L));
+ writer.write(changedFileEntry(drift.getPath(), drift.getOldDriftFile().getHashId(), drift
+ .getNewDriftFile().getHashId(), -1L, -1L));
break;
default: // FILE_REMOVED
writer.write(removedFileEntry(drift.getPath(), drift.getOldDriftFile().getHashId()));
commit 1ca18175b45456a6963f706cf1c4c7427384edcb
Merge: 579510c e8db9a1
Author: John Sanda <jsanda(a)redhat.com>
Date: Sat Dec 10 12:46:22 2011 -0500
Merge branch 'master' into jsanda/drift
Conflicts:
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java
diff --cc modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
index c8c3bb0,21341c4..848ae93
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
@@@ -210,37 -216,42 +216,41 @@@ public class DriftDetector implements R
// If the basedir is still valid we need to do a directory tree scan to look for newly added files
if (basedir.isDirectory()) {
- forEachFile(basedir, new FilterFileVisitor(basedir, schedule.getDriftDefinition().getIncludes(), schedule
- .getDriftDefinition().getExcludes(), new FileVisitor() {
- @Override
- public void visit(File file) {
- try {
- if (processedFiles.contains(file)) {
- return;
- }
+ DriftDefinition driftDef = schedule.getDriftDefinition();
+ List<Filter> includes = driftDef.getIncludes();
+ List<Filter> excludes = driftDef.getExcludes();
+
+ for (File dir : getScanDirectories(basedir, includes)) {
+ forEachFile(dir, new FilterFileVisitor(basedir, includes, excludes, new FileVisitor() {
+ @Override
+ public void visit(File file) {
+ try {
+ if (processedFiles.contains(file)) {
+ return;
+ }
- if (!file.canRead()) {
- if (log.isDebugEnabled()) {
- log.debug("Skipping " + file.getPath() + " since it is not readable.");
+ if (!file.canRead()) {
+ if (log.isDebugEnabled()) {
+ log.debug("Skipping " + file.getPath() + " since it is not readable.");
+ }
return;
}
- }
- if (log.isInfoEnabled()) {
- log.info("Detected added file for " + schedule + " --> " + file.getAbsolutePath());
- }
+ if (log.isInfoEnabled()) {
+ log.info("Detected added file for " + schedule + " --> " + file.getAbsolutePath());
+ }
- FileEntry newEntry = addedFileEntry(relativePath(basedir, file), sha256(file));
- deltaEntries.add(newEntry);
- snapshotEntries.add(newEntry);
- } catch (IOException e) {
- log.error("An error occurred while generating a drift change set for " + schedule + ": "
- + e.getMessage());
- throw new DriftDetectionException("An error occurred while generating a drift change set",
- e);
- }
+ FileEntry newEntry = addedFileEntry(relativePath(basedir, file), sha256(file),
+ file.lastModified(), file.length());
+ deltaEntries.add(newEntry);
+ snapshotEntries.add(newEntry);
+ } catch (IOException e) {
+ log.error("An error occurred while generating a drift change set for " + schedule + ": "
+ + e.getMessage());
+ throw new DriftDetectionException("An error occurred while generating a drift change set", e);
}
- }
- }));
+ }));
+ }
}
if (deltaEntries.isEmpty()) {
diff --cc modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java
index 4241b31,2790f13..1182407
--- 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
@@@ -758,16 -771,16 +771,16 @@@ public class DriftManager extends Agent
private void writeSnapshotToFile(DriftSnapshot snapshot, File file, Headers headers) throws IOException {
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(file, headers);
try {
- for (Drift drift : snapshot.getDriftInstances()) {
+ for (Drift<?, ?> drift : snapshot.getDriftInstances()) {
switch (drift.getCategory()) {
case FILE_ADDED:
- writer.write(addedFileEntry(drift.getPath(), drift.getNewDriftFile().getHashId()));
+ writer.write(addedFileEntry(drift.getPath(), drift.getNewDriftFile().getHashId(), -1L, -1L));
break;
case FILE_CHANGED:
- writer.write(changedFileEntry(drift.getPath(), drift.getOldDriftFile().getHashId(), drift
- .getNewDriftFile().getHashId()));
+ writer.write(changedFileEntry(drift.getPath(), drift.getOldDriftFile().getHashId(),
+ drift.getNewDriftFile().getHashId(), -1L, -1L));
break;
- default: // FILE_REMOVED
+ default: // FILE_REMOVED
writer.write(removedFileEntry(drift.getPath(), drift.getOldDriftFile().getHashId()));
}
}
commit 579510cd6bb0e810f551b06a5fa9a0d777a2e50c
Author: John Sanda <jsanda(a)redhat.com>
Date: Tue Nov 22 11:59:44 2011 -0500
[BZ 756100] Use file timestamp and size during drift detection
This commit introduces an enhancement to drift detection by reducing the
amount of digest calculation that is performed. Digest calculation is
CPU-intensive.
The change set parser code has been updated to read/write file timestamp
and size. DriftDetector looks at the addition file info now to determine
if there has been a change. If the timestamp and size have not changed,
DriftDetector will skip recalculating the SHA. This results in a
significant speed up in drift detection.
Since the additional fields are not persisted on the server, there may
be times when the file timestamp and size are not available. This can
happen for example when the agent is restarted and the data directory is
purged. The agent has to download snapshots from the server at that
point, and they will not have the file modification time or size.
diff --git a/modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetReaderImpl.java b/modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetReaderImpl.java
index 5da6078..f0dd8ac 100644
--- a/modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetReaderImpl.java
+++ b/modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetReaderImpl.java
@@ -19,6 +19,10 @@
package org.rhq.common.drift;
+import static org.rhq.common.drift.FileEntry.addedFileEntry;
+import static org.rhq.common.drift.FileEntry.changedFileEntry;
+import static org.rhq.common.drift.FileEntry.removedFileEntry;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
@@ -31,10 +35,6 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.drift.DriftChangeSetCategory;
-import static org.rhq.common.drift.FileEntry.addedFileEntry;
-import static org.rhq.common.drift.FileEntry.changedFileEntry;
-import static org.rhq.common.drift.FileEntry.removedFileEntry;
-
/**
* Note that this implementation does not do any validation for the most part. It assumes
* that entries in the change set file contain valid, 64 character SHA-256 hashes. It
@@ -121,19 +121,30 @@ public class ChangeSetReaderImpl implements ChangeSetReader {
}
if (line.charAt(0) == 'A') { // file added
- String sha = line.substring(2, 66);
- String fileName = line.substring(69);
- return addedFileEntry(fileName, sha);
+ int fileSizeEndIndex = line.indexOf(' ', 2);
+ long size = Long.parseLong(line.substring(2, fileSizeEndIndex));
+ int lastModifiedEndIndex = line.indexOf(' ', fileSizeEndIndex + 1);
+ long lastModified = Long.parseLong(line.substring(fileSizeEndIndex + 1, lastModifiedEndIndex));
+ int shaEndIndex = lastModifiedEndIndex + 65;
+ String sha = line.substring(lastModifiedEndIndex + 1, shaEndIndex);
+ String fileName = line.substring(shaEndIndex + 3);
+ return addedFileEntry(fileName, sha, lastModified, size);
}
if (line.charAt(0) == 'C') { // file modified
- String newSha = line.substring(2, 66);
- String oldSha = line.substring(67, 131);
- String fileName = line.substring(132);
- return changedFileEntry(fileName, oldSha, newSha);
+ int fileSizeEndIndex = line.indexOf(' ', 2);
+ long size = Long.parseLong(line.substring(2, fileSizeEndIndex));
+ int lastModifiedEndIndex = line.indexOf(' ', fileSizeEndIndex + 1);
+ long lastModified = Long.parseLong(line.substring(fileSizeEndIndex + 1, lastModifiedEndIndex));
+ int newShaIndex = lastModifiedEndIndex + 65;
+ String newSha = line.substring(lastModifiedEndIndex + 1, newShaIndex);
+ int oldShaIndex = newShaIndex + 65;
+ String oldSha = line.substring(newShaIndex + 1, oldShaIndex);
+ String fileName = line.substring(oldShaIndex + 1);
+ return changedFileEntry(fileName, oldSha, newSha, lastModified, size);
}
if (line.charAt(0) == 'R') { // file deleted
- String sha = line.substring(4, 68);
- String fileName = line.substring(69);
+ String sha = line.substring(10, 74);
+ String fileName = line.substring(75);
return removedFileEntry(fileName, sha);
}
diff --git a/modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetWriter.java b/modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetWriter.java
index 5e9c6ed..9631490 100644
--- a/modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetWriter.java
+++ b/modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetWriter.java
@@ -46,7 +46,15 @@ import java.io.IOException;
* </ul>
* <br/>
* <br/>
- * FILE_ENTRY has four, space-delimited fields - type, new_sha, old_sha, file_name.<br/>
+ * FILE_ENTRY has six, space-delimited fields:
+ * <ul>
+ * <li>type</li>
+ * <li>file_size</li>
+ * <li>timestamp</li>
+ * <li>new_sha</li>
+ * <li>old_sha</li>
+ * <li>file_name</li>
+ * </ul>
* Here is an example change set:
*
* <pre>
@@ -54,17 +62,19 @@ import java.io.IOException;
* 2345
* Core Server JARs
* /var/lib/myserver
- * C 1706b5c18e4358041b463995efc30f8f721766fab0e018d50d85978b46df013c 1536b5c18e4358041b463995efc30f8f721766fab0e018d50d85978b46df013c lib/foo.jar
- * A 2706b5c18e4358041b463995efc30f8f721766fab0e018d50d85978b46df013a 0 lib/bar.jar
- * R 0 2206b5af8e4358041b463995efc30f8f721766fab0e018d50d85978b46df013a conf/foo.conf
+ * C 1024 1321975943000 1706b5c18e4358041b463995efc30f8f721766fab0e018d50d85978b46df013c 1536b5c18e4358041b463995efc30f8f721766fab0e018d50d85978b46df013c lib/foo.jar
+ * A 512 1121975943000 2706b5c18e4358041b463995efc30f8f721766fab0e018d50d85978b46df013a 0 lib/bar.jar
+ * R -1 -1 0 2206b5af8e4358041b463995efc30f8f721766fab0e018d50d85978b46df013a conf/foo.conf
* </pre>
*
* Note that the file paths in each entry are relative to the path in the base directory
- * header. For the entry with a path of lib/bar.jar notice that the old_sha field has a
- * value of 0. This is because it is a new file, and there is no previous SHA-256 hash for
- * the file. For the entry with conf/foo.conf as its path, notices that the new_sha field
- * has a value of 0 for foo.conf. This is because the file has been deleted and so there is
- * no new SHA-256 hash.
+ * header. The timestamp field is the last modification time of the file. For the entry
+ * with a path of lib/bar.jar notice that the old_sha field has a value of 0. This is
+ * because it is a new file, and there is no previous SHA-256 hash for the file. For the
+ * entry with conf/foo.conf as its path, notices that the new_sha field has a value of 0 for foo.conf.
+ * This is because the file has been deleted and so there is no new SHA-256 hash. Also
+ * note that this entry has a value of -1 for its file size and timestamp fields. This
+ * denotes that those values are no longer available since the file was removed.
* <p/>
* Lastly and importantly, the format of this file is still subject to change. Additional
* headers may be added, maybe allowing for optional headers. The format of the file entry
diff --git a/modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetWriterImpl.java b/modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetWriterImpl.java
index c0fdf50..57a9c1a 100644
--- a/modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetWriterImpl.java
+++ b/modules/common/drift/src/main/java/org/rhq/common/drift/ChangeSetWriterImpl.java
@@ -57,14 +57,31 @@ public class ChangeSetWriterImpl implements ChangeSetWriter {
public void write(FileEntry entry) throws IOException {
switch (entry.getType()) {
case FILE_ADDED:
- writer.write(entry.getType().code() + " " + entry.getNewSHA() + " 0 " + entry.getFile() + "\n");
+ writer.write(
+ entry.getType().code() + " " +
+ entry.getSize() + " " +
+ entry.getLastModified() + " " +
+ entry.getNewSHA() +
+ " 0 " +
+ entry.getFile() + "\n");
break;
case FILE_CHANGED:
- writer.write(entry.getType().code() + " " + entry.getNewSHA() + " " + entry.getOldSHA() + " " +
+ writer.write(
+ entry.getType().code() + " " +
+ entry.getSize() + " " +
+ entry.getLastModified() + " " +
+ entry.getNewSHA() + " " +
+ entry.getOldSHA() + " " +
entry.getFile() + "\n");
break;
case FILE_REMOVED:
- writer.write(entry.getType().code() + " 0 " + entry.getOldSHA() + " " + entry.getFile() + "\n");
+ writer.write(
+ entry.getType().code() + " " +
+ "-1 " +
+ "-1 " +
+ "0 " +
+ entry.getOldSHA() + " " +
+ entry.getFile() + "\n");
break;
}
}
diff --git a/modules/common/drift/src/main/java/org/rhq/common/drift/FileEntry.java b/modules/common/drift/src/main/java/org/rhq/common/drift/FileEntry.java
index bafd297..e1766a3 100644
--- a/modules/common/drift/src/main/java/org/rhq/common/drift/FileEntry.java
+++ b/modules/common/drift/src/main/java/org/rhq/common/drift/FileEntry.java
@@ -24,6 +24,7 @@ import static org.rhq.core.domain.drift.DriftCategory.FILE_CHANGED;
import static org.rhq.core.domain.drift.DriftCategory.FILE_REMOVED;
import java.io.Serializable;
+import java.util.Date;
import org.rhq.core.domain.drift.DriftCategory;
import org.rhq.core.util.file.FileUtil;
@@ -38,26 +39,32 @@ public class FileEntry implements Serializable {
entry.oldSHA = sha;
entry.newSHA = "0";
entry.type = FILE_REMOVED;
+ entry.lastModified = -1L;
+ entry.size = -1L;
return entry;
}
- public static FileEntry addedFileEntry(String file, String sha) {
+ public static FileEntry addedFileEntry(String file, String sha, Long lastModified, Long size) {
FileEntry entry = new FileEntry();
entry.file = FileUtil.useForwardSlash(file);
entry.oldSHA = "0";
entry.newSHA = sha;
entry.type = FILE_ADDED;
+ entry.lastModified = lastModified;
+ entry.size = size;
return entry;
}
- public static FileEntry changedFileEntry(String file, String oldSHA, String newSHA) {
+ public static FileEntry changedFileEntry(String file, String oldSHA, String newSHA, Long lastModified, Long size) {
FileEntry entry = new FileEntry();
entry.file = FileUtil.useForwardSlash(file);
entry.oldSHA = oldSHA;
entry.newSHA = newSHA;
entry.type = FILE_CHANGED;
+ entry.lastModified = lastModified;
+ entry.size = size;
return entry;
}
@@ -70,14 +77,20 @@ public class FileEntry implements Serializable {
private DriftCategory type;
+ private Long lastModified;
+
+ private Long size;
+
private FileEntry() {
}
- public FileEntry(String newSHA, String oldSHA, String file, String type) {
+ public FileEntry(String newSHA, String oldSHA, String file, String type, Long lastModified, Long size) {
this.newSHA = newSHA;
this.oldSHA = oldSHA;
this.file = file;
this.type = DriftCategory.fromCode(type);
+ this.lastModified = lastModified;
+ this.size = size;
}
public String getFile() {
@@ -96,9 +109,17 @@ public class FileEntry implements Serializable {
return type;
}
+ public Long getLastModified() {
+ return lastModified;
+ }
+
+ public Long getSize() {
+ return size;
+ }
+
@Override
public String toString() {
return getClass().getSimpleName() + "[newSHA: " + newSHA + ", oldSHA: " + oldSHA + ", file: " + file
- + ", type: " + type.code() + "]";
+ + ", type: " + type.code() + ", lastModified: " + new Date(lastModified) + ", size: " + size + "]";
}
}
diff --git a/modules/common/drift/src/test/java/org/rhq/common/drift/ChangeSetReaderImplTest.java b/modules/common/drift/src/test/java/org/rhq/common/drift/ChangeSetReaderImplTest.java
index 1a6f5dd..e8b1cd6 100644
--- a/modules/common/drift/src/test/java/org/rhq/common/drift/ChangeSetReaderImplTest.java
+++ b/modules/common/drift/src/test/java/org/rhq/common/drift/ChangeSetReaderImplTest.java
@@ -1,15 +1,16 @@
package org.rhq.common.drift;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
+import static org.rhq.test.AssertUtils.assertPropertiesMatch;
+import static org.testng.Assert.assertEquals;
+
import java.io.StringReader;
+import java.util.Date;
import org.testng.annotations.Test;
import org.rhq.core.util.MessageDigestGenerator;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
-import static org.rhq.test.AssertUtils.assertPropertiesMatch;
-import static org.testng.Assert.assertEquals;
-
public class ChangeSetReaderImplTest {
MessageDigestGenerator digestGenerator = new MessageDigestGenerator(MessageDigestGenerator.SHA_256);
@@ -18,13 +19,14 @@ public class ChangeSetReaderImplTest {
@SuppressWarnings("unchecked")
public void readFileAddedEntry() throws Exception {
String sha = sha256("myconf.conf");
+ long timestamp = new Date().getTime();
String changeset = "1\n" +
"1\n" +
"file-added-test\n" +
"myresource\n" +
"C\n" +
"1\n" +
- "A " + sha + " 0 conf/myconf.conf";
+ "A 1024 " + timestamp + " " + sha + " 0 conf/myconf.conf";
ChangeSetReaderImpl reader = new ChangeSetReaderImpl(new StringReader(changeset));
@@ -39,7 +41,7 @@ public class ChangeSetReaderImplTest {
assertHeadersEquals(actualHeaders, expectedHeaders);
- FileEntry expectedFileEntry = new FileEntry(sha, "0", "conf/myconf.conf", "A");
+ FileEntry expectedFileEntry = new FileEntry(sha, "0", "conf/myconf.conf", "A", timestamp, 1024L);
FileEntry actualFileEntry = reader.read();
reader.close();
@@ -56,7 +58,7 @@ public class ChangeSetReaderImplTest {
"myresource\n" +
"C\n" +
"1\n" +
- "R 0 " + sha + " conf/myconf.conf";
+ "R -1 -1 0 " + sha + " conf/myconf.conf";
ChangeSetReaderImpl reader = new ChangeSetReaderImpl(new StringReader(changeset));
@@ -71,7 +73,7 @@ public class ChangeSetReaderImplTest {
assertHeadersEquals(actualHeaders, expectedHeaders);
- FileEntry expectedFileEntry = new FileEntry("0", sha, "conf/myconf.conf", "R");
+ FileEntry expectedFileEntry = new FileEntry("0", sha, "conf/myconf.conf", "R", -1L, -1L);
FileEntry actualFileEntry = reader.read();
reader.close();
@@ -83,13 +85,14 @@ public class ChangeSetReaderImplTest {
public void readChangedFileEntry() throws Exception {
String oldSha = sha256("myconf.conf.old");
String newSha = sha256("myconf.conf.new");
+ long timestamp = new Date().getTime();
String changeset = "1\n" +
"1\n" +
"file-changed-test\n" +
"myresource\n" +
"C\n" +
"1\n" +
- "C " + newSha + " " + oldSha + " conf/myconf.conf";
+ "C 1024 " + timestamp + " " + newSha + " " + oldSha + " conf/myconf.conf";
ChangeSetReaderImpl reader = new ChangeSetReaderImpl(new StringReader(changeset));
@@ -104,7 +107,7 @@ public class ChangeSetReaderImplTest {
assertHeadersEquals(actualHeaders, expectedHeaders);
- FileEntry expectedFileEntry = new FileEntry(newSha, oldSha, "conf/myconf.conf", "C");
+ FileEntry expectedFileEntry = new FileEntry(newSha, oldSha, "conf/myconf.conf", "C", timestamp, 1024L);
FileEntry actualFileEntry = reader.read();
reader.close();
@@ -115,13 +118,14 @@ public class ChangeSetReaderImplTest {
@SuppressWarnings("unchecked")
public void readFileEntryWithSpacesInPath() throws Exception {
String sha = sha256("file with spaces.conf");
+ long timestamp = new Date().getTime();
String changeset = "1\n" +
"1\n" +
"file-name-test\n" +
"myresource\n" +
"C\n" +
"1\n" +
- "A " + sha + " 0 conf/file with spaces.conf";
+ "A 1024 " + timestamp + " " + sha + " 0 conf/file with spaces.conf";
ChangeSetReaderImpl reader = new ChangeSetReaderImpl(new StringReader(changeset));
@@ -136,7 +140,7 @@ public class ChangeSetReaderImplTest {
assertHeadersEquals(actualHeaders, expectedHeaders);
- FileEntry expectedFileEntry = new FileEntry(sha, "0", "conf/file with spaces.conf", "A");
+ FileEntry expectedFileEntry = new FileEntry(sha, "0", "conf/file with spaces.conf", "A", timestamp, 1024L);
FileEntry actualFileEntry = reader.read();
reader.close();
@@ -162,8 +166,8 @@ public class ChangeSetReaderImplTest {
"myresource\n" +
"C\n" +
"1\n" +
- "A " + sha256("resource.conf") + " 0 conf/resource.conf\n" +
- "A " + sha256("resource.jar") + " 0 lib/resource.jar";
+ "A 1024 5678 " + sha256("resource.conf") + " 0 conf/resource.conf\n" +
+ "A 1024 5678 " + sha256("resource.jar") + " 0 lib/resource.jar";
ChangeSetReaderImpl reader = new ChangeSetReaderImpl(new StringReader(changeset));
int numEntries = 0;
@@ -185,7 +189,7 @@ public class ChangeSetReaderImplTest {
"myresource\n" +
"C\n" +
"1\n" +
- "A " + sha + " 0 conf/resource.conf\n";
+ "A 1024 5678 " + sha + " 0 conf/resource.conf\n";
ChangeSetReaderImpl reader = new ChangeSetReaderImpl(new StringReader(changeset));
int numEntries = 0;
@@ -227,9 +231,12 @@ public class ChangeSetReaderImplTest {
void assertFileEntryEquals(FileEntry actual, FileEntry expected) {
assertEquals(actual.getType(), expected.getType(), "The first column, the entry type, is wrong");
- assertEquals(actual.getNewSHA(), expected.getNewSHA(), "The second column, the new SHA-256, is wrong");
- assertEquals(actual.getOldSHA (), expected.getOldSHA(), "The third column, the old SHA-256, is wrong");
- assertEquals(actual.getFile(), expected.getFile(), "The fourth column, the file name, is wrong");
+ assertEquals(actual.getSize(), expected.getSize(), "The second column, the file size, is wrong");
+ assertEquals(actual.getLastModified(), expected.getLastModified(), "The third column, the last modification " +
+ "time, is wrong");
+ assertEquals(actual.getNewSHA(), expected.getNewSHA(), "The fourth column, the new SHA-256, is wrong");
+ assertEquals(actual.getOldSHA (), expected.getOldSHA(), "The fifth column, the old SHA-256, is wrong");
+ assertEquals(actual.getFile(), expected.getFile(), "The sixth column, the file name, is wrong");
}
String sha256(String s) throws Exception {
diff --git a/modules/common/drift/src/test/java/org/rhq/common/drift/ChangeSetWriterImplTest.java b/modules/common/drift/src/test/java/org/rhq/common/drift/ChangeSetWriterImplTest.java
index e782cda..73d8d16 100644
--- a/modules/common/drift/src/test/java/org/rhq/common/drift/ChangeSetWriterImplTest.java
+++ b/modules/common/drift/src/test/java/org/rhq/common/drift/ChangeSetWriterImplTest.java
@@ -19,13 +19,6 @@
package org.rhq.common.drift;
-import java.io.File;
-import java.io.FileInputStream;
-import java.util.List;
-
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
import static org.apache.commons.io.FileUtils.deleteDirectory;
import static org.apache.commons.io.IOUtils.readLines;
import static org.rhq.common.drift.FileEntry.addedFileEntry;
@@ -34,6 +27,14 @@ import static org.rhq.common.drift.FileEntry.removedFileEntry;
import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
import static org.testng.Assert.assertEquals;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Date;
+import java.util.List;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
public class ChangeSetWriterImplTest {
File changeSetsDir;
@@ -69,9 +70,10 @@ public class ChangeSetWriterImplTest {
headers.setType(COVERAGE);
headers.setVersion(1);
+ long timestamp = new Date().getTime();
ChangeSetWriterImpl writer = new ChangeSetWriterImpl(changeSetFile, headers);
- writer.write(addedFileEntry("conf/myconf.conf", "a34ef6"));
+ writer.write(addedFileEntry("conf/myconf.conf", "a34ef6", timestamp, 1024L));
writer.close();
File metaDataFile = writer.getChangeSetFile();
@@ -80,7 +82,7 @@ public class ChangeSetWriterImplTest {
assertEquals(lines.size(), 7, "Expected to find seven lines in " + metaDataFile.getPath()
+ " - six for the header followed by one file entry.");
assertHeadersEquals(lines, headers);
- assertFileEntryEquals(lines.get(6), "A a34ef6 0 conf/myconf.conf");
+ assertFileEntryEquals(lines.get(6), "A 1024 " + timestamp + " a34ef6 0 conf/myconf.conf");
}
@Test
@@ -108,7 +110,7 @@ public class ChangeSetWriterImplTest {
assertEquals(lines.size(), 7, "Expected to find seven lines in " + metaDataFile.getPath()
+ " - six for the header followed by one file entry.");
assertHeadersEquals(lines, headers);
- assertFileEntryEquals(lines.get(6), "R 0 a34ef6 conf/myconf.conf");
+ assertFileEntryEquals(lines.get(6), "R -1 -1 0 a34ef6 conf/myconf.conf");
}
@Test
@@ -127,7 +129,8 @@ public class ChangeSetWriterImplTest {
ChangeSetWriterImpl writer = new ChangeSetWriterImpl(changeSetFile, headers);
- writer.write(changedFileEntry("conf/myconf.conf", "a34ef6", "c2d55f"));
+ long timestamp = new Date().getTime();
+ writer.write(changedFileEntry("conf/myconf.conf", "a34ef6", "c2d55f", timestamp, 1024L));
writer.close();
File metaDataFile = writer.getChangeSetFile();
@@ -136,7 +139,7 @@ public class ChangeSetWriterImplTest {
assertEquals(lines.size(), 7, "Expected to find seven lines in " + metaDataFile.getPath()
+ " - six for the header followed by one file entry.");
assertHeadersEquals(lines, headers);
- assertFileEntryEquals(lines.get(6), "C c2d55f a34ef6 conf/myconf.conf");
+ assertFileEntryEquals(lines.get(6), "C 1024 " + timestamp + " c2d55f a34ef6 conf/myconf.conf");
}
/**
@@ -173,13 +176,15 @@ public class ChangeSetWriterImplTest {
String[] expectedFields = expected.split(" ");
String[] actualFields = actual.split(" ");
- assertEquals(expectedFields.length, 4, "<" + expected + "> should contain 4 fields");
- assertEquals(actualFields.length, 4, "<" + actual + "> should contain 4 fields");
+ assertEquals(expectedFields.length, 6, "<" + expected + "> should contain 6 fields");
+ assertEquals(actualFields.length, 6, "<" + actual + "> should contain 6 fields");
- assertEquals(actualFields[0], expectedFields[0], "The first column, the SHA-256, is wrong");
- assertEquals(actualFields[1], expectedFields[1], "The second column, the old SHA-256, is wrong");
- assertEquals(actualFields[2], expectedFields[2], "The third column, the file name, is wrong");
- assertEquals(actualFields[3], expectedFields[3], "The fourth column, the type, is wrong");
+ assertEquals(actualFields[0], expectedFields[0], "The first column, the type, is wrong");
+ assertEquals(actualFields[1], expectedFields[1], "The second column, the file size, is wrong");
+ assertEquals(actualFields[2], expectedFields[2], "The third column, the last modification time, is wrong");
+ assertEquals(actualFields[3], expectedFields[3], "The fourth column, the SHA-256, is wrong");
+ assertEquals(actualFields[4], expectedFields[4], "The fifth column, the old SHA-256, is wrong");
+ assertEquals(actualFields[5], expectedFields[5], "The sixth column, the file name, is wrong");
}
}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
index e0f7509..c8c3bb0 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
@@ -230,7 +230,8 @@ public class DriftDetector implements Runnable {
log.info("Detected added file for " + schedule + " --> " + file.getAbsolutePath());
}
- FileEntry newEntry = addedFileEntry(relativePath(basedir, file), sha256(file));
+ FileEntry newEntry = addedFileEntry(relativePath(basedir, file), sha256(file),
+ file.lastModified(), file.length());
deltaEntries.add(newEntry);
snapshotEntries.add(newEntry);
} catch (IOException e) {
@@ -296,12 +297,27 @@ public class DriftDetector implements Runnable {
deltaEntries.add(removedFileEntry(entry.getFile(), entry.getNewSHA()));
} else {
processedFiles.add(file);
- String currentSHA = sha256(file);
- if (!currentSHA.equals(entry.getNewSHA())) {
+ // if we do not have the last modification time and the file size, then we
+ // have to compare SHAs. We can wind up without a timestamp of a file size
+ // when the agent is restarted and the data directory is purged. The server
+ // sends snapshots down to the agent and since the server does not store the
+ // file modification time or size, the fields will get initialized to -1.
+ if (entry.getLastModified() == -1 && entry.getSize() == -1) {
+ String currentSHA = sha256(file);
+ if (!entry.getNewSHA().equals(currentSHA)) {
+ FileEntry modifiedEntry = changedFileEntry(entry.getFile(), entry.getNewSHA(), currentSHA,
+ file.lastModified(), file.length());
+ deltaEntries.add(modifiedEntry);
+ snapshotEntries.add(modifiedEntry);
+ }
+ } else if (entry.getLastModified() != -1 && entry.getSize() != -1 &&
+ (entry.getLastModified() != file.lastModified() || entry.getSize() != file.length())) {
if (log.isDebugEnabled()) {
log.debug("Detected modified file for " + schedule + " --> " + file.getAbsolutePath());
}
- FileEntry modifiedEntry = changedFileEntry(entry.getFile(), entry.getNewSHA(), currentSHA);
+ String currentSHA = sha256(file);
+ FileEntry modifiedEntry = changedFileEntry(entry.getFile(), entry.getNewSHA(), currentSHA,
+ file.lastModified(), file.length());
deltaEntries.add(modifiedEntry);
snapshotEntries.add(modifiedEntry);
} else {
@@ -492,7 +508,8 @@ public class DriftDetector implements Runnable {
if (log.isDebugEnabled()) {
log.debug("Adding " + file.getPath() + " to coverage change set for " + schedule);
}
- writer.write(addedFileEntry(relativePath(basedir, file), sha256(file)));
+ writer.write(addedFileEntry(relativePath(basedir, file), sha256(file), file.lastModified(),
+ file.length()));
} catch (IOException e) {
log.error("An error occurred while generating a coverage change set for " + schedule + ": "
+ e.getMessage());
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 c70b546..4241b31 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
@@ -761,11 +761,11 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
for (Drift drift : snapshot.getDriftInstances()) {
switch (drift.getCategory()) {
case FILE_ADDED:
- writer.write(addedFileEntry(drift.getPath(), drift.getNewDriftFile().getHashId()));
+ writer.write(addedFileEntry(drift.getPath(), drift.getNewDriftFile().getHashId(), -1L, -1L));
break;
case FILE_CHANGED:
writer.write(changedFileEntry(drift.getPath(), drift.getOldDriftFile().getHashId(),
- drift.getNewDriftFile().getHashId()));
+ drift.getNewDriftFile().getHashId(), -1L, -1L));
break;
default: // FILE_REMOVED
writer.write(removedFileEntry(drift.getPath(), drift.getOldDriftFile().getHashId()));
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/ChangeSetManagerImplTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/ChangeSetManagerImplTest.java
index 6e016b6..351f42f 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/ChangeSetManagerImplTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/ChangeSetManagerImplTest.java
@@ -53,7 +53,7 @@ public class ChangeSetManagerImplTest extends DriftTest {
String serverConfHash = sha256(serverConf);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), createHeaders(config, COVERAGE));
- writer.write(addedFileEntry("conf/server.conf", serverConfHash));
+ writer.write(addedFileEntry("conf/server.conf", serverConfHash, serverConf.lastModified(), serverConf.length()));
writer.close();
ChangeSetReader reader = changeSetMgr.getChangeSetReader(resourceId(), config);
@@ -72,7 +72,7 @@ public class ChangeSetManagerImplTest extends DriftTest {
Headers headers = createHeaders(config, COVERAGE);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), headers);
- writer.write(addedFileEntry("conf/server.conf", sha256(serverConf)));
+ writer.write(addedFileEntry("conf/server.conf", sha256(serverConf), serverConf.lastModified(), serverConf.length()));
writer.close();
assertTrue(changeSetMgr.changeSetExists(resourceId(), headers), "Expected to find change set file.");
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftDetectorTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftDetectorTest.java
index 4a2b333..dee1c6d 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftDetectorTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftDetectorTest.java
@@ -95,7 +95,8 @@ public class DriftDetectorTest extends DriftTest {
File changeSet = changeSet(driftDef.getName(), COVERAGE);
Headers headers = createHeaders(driftDef, COVERAGE);
- List<FileEntry> expected = asList(addedFileEntry("conf/server.conf", sha256(serverConf)));
+ List<FileEntry> expected = asList(addedFileEntry("conf/server.conf", sha256(serverConf),
+ serverConf.lastModified(), serverConf.length()));
assertHeaderEquals(changeSet, headers);
assertFileEntriesMatch("Only files should be included in a change set.", expected, changeSet);
@@ -114,8 +115,9 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
File changeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> entries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf)), addedFileEntry(
- "conf/server-2.conf", sha256(server2Conf)));
+ List<FileEntry> entries = asList(
+ addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf.length()),
+ addedFileEntry("conf/server-2.conf", sha256(server2Conf), server2Conf.lastModified(), server2Conf.length()));
assertHeaderEquals(changeSet, createHeaders(def, COVERAGE));
assertFileEntriesMatch("Each file in a directory should be included in a coverage change set", entries,
@@ -137,8 +139,9 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
File changeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> entries = asList(addedFileEntry("conf/server.conf", sha256(serverConf)), addedFileEntry(
- "lib/server.jar", sha256(serverLib)));
+ List<FileEntry> entries = asList(
+ addedFileEntry("conf/server.conf", sha256(serverConf), serverConf.lastModified(), serverConf.length()),
+ addedFileEntry("lib/server.jar", sha256(serverLib), serverLib.lastModified(), serverLib.length()));
assertHeaderEquals(changeSet, createHeaders(def, COVERAGE));
assertFileEntriesMatch("A coverage change set should include files from multiple, sibling directories",
@@ -160,8 +163,9 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
File changeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> entries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf)), addedFileEntry(
- "conf/subconf/server-2.conf", sha256(server2Conf)));
+ List<FileEntry> entries = asList(
+ addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf.length()),
+ addedFileEntry("conf/subconf/server-2.conf", sha256(server2Conf), server2Conf.lastModified(), server2Conf.length()));
assertHeaderEquals(changeSet, createHeaders(def, COVERAGE));
assertFileEntriesMatch("A coverage change set should include files in nested sub directories", entries,
@@ -296,7 +300,8 @@ public class DriftDetectorTest extends DriftTest {
File server1Conf = createRandomFile(confDir, "server-1.conf");
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), createHeaders(def, COVERAGE));
- writer.write(addedFileEntry("conf/server-1.conf", sha256(server1Conf)));
+ writer.write(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(),
+ server1Conf.length()));
writer.close();
// Create some drift
@@ -306,7 +311,8 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
File driftChangeSet = changeSet(def.getName(), DRIFT);
- List<FileEntry> driftEntries = asList(addedFileEntry("conf/server-2.conf", sha256(server2Conf)));
+ List<FileEntry> driftEntries = asList(addedFileEntry("conf/server-2.conf", sha256(server2Conf),
+ server2Conf.lastModified(), server2Conf.length()));
// verify that the drift change set was generated
assertTrue(driftChangeSet.exists(), "Expected to find drift change set " + driftChangeSet.getPath());
@@ -314,8 +320,9 @@ public class DriftDetectorTest extends DriftTest {
assertFileEntriesMatch("The drift change set does not match the expected values", driftEntries, driftChangeSet);
File coverageChangeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> coverageEntries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf)),
- addedFileEntry("conf/server-2.conf", sha256(server2Conf)));
+ List<FileEntry> coverageEntries = asList(
+ addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf.length()),
+ addedFileEntry("conf/server-2.conf", sha256(server2Conf), server2Conf.lastModified(), server2Conf.length()));
// verify that the coverage change set was updated
assertHeaderEquals(coverageChangeSet, createHeaders(def, COVERAGE, 1));
@@ -333,19 +340,20 @@ public class DriftDetectorTest extends DriftTest {
String oldHash = sha256(server1Conf);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), createHeaders(def, COVERAGE));
- writer.write(addedFileEntry("conf/server-1.conf", oldHash));
+ writer.write(addedFileEntry("conf/server-1.conf", oldHash, server1Conf.lastModified(), server1Conf.length()));
writer.close();
// create some drift
server1Conf.delete();
- server1Conf = createRandomFile(confDir, "server-1.conf");
+ server1Conf = createRandomFile(confDir, "server-1.conf", 48);
String newHash = sha256(server1Conf);
scheduleQueue.addSchedule(new DriftDetectionSchedule(resourceId(), def));
detector.run();
File driftChangeSet = changeSet(def.getName(), DRIFT);
- List<FileEntry> driftEntries = asList(changedFileEntry("conf/server-1.conf", oldHash, newHash));
+ List<FileEntry> driftEntries = asList(changedFileEntry("conf/server-1.conf", oldHash, newHash,
+ server1Conf.lastModified(), server1Conf.length()));
// verify that the drift change set was generated
assertTrue(driftChangeSet.exists(), "Expected to find drift change set " + driftChangeSet.getPath());
@@ -353,7 +361,8 @@ public class DriftDetectorTest extends DriftTest {
assertFileEntriesMatch("The drift change set does not match the expected values", driftEntries, driftChangeSet);
File coverageChangeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> coverageEntries = asList(changedFileEntry("conf/server-1.conf", oldHash, newHash));
+ List<FileEntry> coverageEntries = asList(changedFileEntry("conf/server-1.conf", oldHash, newHash,
+ server1Conf.lastModified(), server1Conf.length()));
// verify that the coverage change set was updated
assertHeaderEquals(coverageChangeSet, createHeaders(def, COVERAGE, 1));
@@ -370,7 +379,8 @@ public class DriftDetectorTest extends DriftTest {
File server1Conf = createRandomFile(confDir, "server-1.conf");
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), createHeaders(def, COVERAGE));
- writer.write(addedFileEntry("conf/server-1.conf", sha256(server1Conf)));
+ writer.write(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(),
+ server1Conf.length()));
writer.close();
// create some drift
@@ -381,7 +391,8 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
File driftChangeSet = changeSet(def.getName(), DRIFT);
- List<FileEntry> driftEntries = asList(addedFileEntry("conf/subconf/server-2.conf", sha256(server2Conf)));
+ List<FileEntry> driftEntries = asList(addedFileEntry("conf/subconf/server-2.conf", sha256(server2Conf),
+ server2Conf.lastModified(), server2Conf.length()));
// verify that the drift change set was generated
assertTrue(driftChangeSet.exists(), "Expected to find drift change set " + driftChangeSet.getPath());
@@ -389,8 +400,9 @@ public class DriftDetectorTest extends DriftTest {
assertFileEntriesMatch("The drift change set does not match the expected values", driftEntries, driftChangeSet);
File coverageChangeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> coverageEntries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf)),
- addedFileEntry("conf/subconf/server-2.conf", sha256(server2Conf)));
+ List<FileEntry> coverageEntries = asList(
+ addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf.length()),
+ addedFileEntry("conf/subconf/server-2.conf", sha256(server2Conf), server2Conf.lastModified(), server2Conf.length()));
// verify that the coverage change set was updated
assertHeaderEquals(coverageChangeSet, createHeaders(def, COVERAGE, 1));
@@ -410,8 +422,10 @@ public class DriftDetectorTest extends DriftTest {
String server2ConfHash = sha256(server2Conf);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), createHeaders(def, COVERAGE));
- writer.write(addedFileEntry("conf/server-1.conf", sha256(server1Conf)));
- writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash));
+ writer.write(addedFileEntry("conf/server-1.conf", sha256(server1Conf), server1Conf.lastModified(),
+ server1Conf.length()));
+ writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash, server2Conf.lastModified(),
+ server2Conf.length()));
writer.close();
// create some drift
@@ -430,7 +444,8 @@ public class DriftDetectorTest extends DriftTest {
// verify that the coverage change set was updated
File coverageChangeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> coverageEntries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf)));
+ List<FileEntry> coverageEntries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf),
+ server1Conf.lastModified(), server1Conf.length()));
assertHeaderEquals(coverageChangeSet, createHeaders(def, COVERAGE, 1));
assertFileEntriesMatch("The coverage change set was not updated as expected", coverageEntries,
@@ -488,7 +503,7 @@ public class DriftDetectorTest extends DriftTest {
String server1Hash = sha256(server1Conf);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), createHeaders(def, COVERAGE));
- writer.write(addedFileEntry("conf/server-1.conf", server1Hash));
+ writer.write(addedFileEntry("conf/server-1.conf", server1Hash, server1Conf.lastModified(), server1Conf.length()));
writer.close();
// create some drift
@@ -599,7 +614,8 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
File changeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> entries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf)));
+ List<FileEntry> entries = asList(addedFileEntry("conf/server-1.conf", sha256(server1Conf),
+ server1Conf.lastModified(), server1Conf.length()));
assertHeaderEquals(changeSet, createHeaders(def, COVERAGE));
assertFileEntriesMatch("Files that are non-readable should be skipped but other, readable file should still "
@@ -620,7 +636,7 @@ public class DriftDetectorTest extends DriftTest {
// create some drift that includes a new file that is not readable
server1Conf.delete();
- server1Conf = createRandomFile(confDir, "server-1.conf");
+ server1Conf = createRandomFile(confDir, "server-1.conf", 48);
String newServer1Hash = sha256(server1Conf);
File server2Conf = createRandomFile(confDir, "server-2.conf");
@@ -630,7 +646,8 @@ public class DriftDetectorTest extends DriftTest {
detector.run();
File driftChangeSet = changeSet(def.getName(), DRIFT);
- List<FileEntry> driftEntries = asList(changedFileEntry("conf/server-1.conf", oldServer1Hash, newServer1Hash));
+ List<FileEntry> driftEntries = asList(changedFileEntry("conf/server-1.conf", oldServer1Hash, newServer1Hash,
+ server1Conf.lastModified(), server1Conf.length()));
// verify that the drift change set was generated
assertTrue(driftChangeSet.exists(), "Expected to find drift change set " + driftChangeSet.getPath());
@@ -639,7 +656,8 @@ public class DriftDetectorTest extends DriftTest {
// verify that the coverage change set was updated
File coverageChangeSet = changeSet(def.getName(), COVERAGE);
- List<FileEntry> coverageEntries = asList(changedFileEntry("conf/server-1.conf", oldServer1Hash, newServer1Hash));
+ List<FileEntry> coverageEntries = asList(changedFileEntry("conf/server-1.conf", oldServer1Hash, newServer1Hash,
+ server1Conf.lastModified(), server1Conf.length()));
assertHeaderEquals(coverageChangeSet, createHeaders(def, COVERAGE, 1));
assertFileEntriesMatch("The coverage change set was not updated as expected", coverageEntries,
@@ -712,8 +730,8 @@ public class DriftDetectorTest extends DriftTest {
// We always generate/update the current snapshot so we still need to verify that it
// was generated/updated correctly
List<FileEntry> fileEntries = asList(
- addedFileEntry("conf/server1.conf", sha256(server1Conf)),
- addedFileEntry("conf/server2.conf", sha256(server2Conf)));
+ addedFileEntry("conf/server1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf.length()),
+ addedFileEntry("conf/server2.conf", sha256(server2Conf), server2Conf.lastModified(), server2Conf.length()));
assertHeaderEquals(currentSnapshot, createHeaders(driftDef, COVERAGE, 1));
assertFileEntriesMatch("The current snapshot file should still get updated even when using a pinned snapshot",
@@ -748,9 +766,9 @@ public class DriftDetectorTest extends DriftTest {
// verify that the current snapshot was updated
List<FileEntry> currentSnapshotEntries = asList(
- addedFileEntry("conf/server1.conf", sha256(server1Conf)),
- addedFileEntry("conf/server2.conf", sha256(server2Conf)),
- addedFileEntry("conf/server3.conf", sha256(server3Conf)));
+ addedFileEntry("conf/server1.conf", sha256(server1Conf), server1Conf.lastModified(), server1Conf.length()),
+ addedFileEntry("conf/server2.conf", sha256(server2Conf), server2Conf.lastModified(), server2Conf.length()),
+ addedFileEntry("conf/server3.conf", sha256(server3Conf), server3Conf.lastModified(), server3Conf.length()));
assertHeaderEquals(currentSnapshot, createHeaders(driftDef, COVERAGE, 2));
assertFileEntriesMatch("The current snapshot file should still get updated even when using a pinned snapshot",
@@ -759,8 +777,8 @@ public class DriftDetectorTest extends DriftTest {
// verify that the the drift/delta change set was generated
File driftChangeSet = changeSet(driftDef.getName(), DRIFT);
List<FileEntry> driftEntries = asList(
- addedFileEntry("conf/server2.conf", sha256(server2Conf)),
- addedFileEntry("conf/server3.conf", sha256(server3Conf)));
+ addedFileEntry("conf/server2.conf", sha256(server2Conf), server2Conf.lastModified(), server2Conf.length()),
+ addedFileEntry("conf/server3.conf", sha256(server3Conf), server3Conf.lastModified(), server3Conf.length()));
assertHeaderEquals(driftChangeSet, createHeaders(driftDef, DRIFT, 2));
assertFileEntriesMatch("The drift change set was not generated correctly when using a pinned snapshot",
@@ -781,7 +799,8 @@ public class DriftDetectorTest extends DriftTest {
File changeSet = changeSet(driftDef.getName(), COVERAGE);
File pinnedSnapshot = new File(changeSet.getParentFile(), "snapshot.pinned");
- List<FileEntry> entries = asList(addedFileEntry("conf/server.conf", sha256(serverConf)));
+ List<FileEntry> entries = asList(addedFileEntry("conf/server.conf", sha256(serverConf),
+ serverConf.lastModified(), serverConf.length()));
assertTrue(changeSet.exists(), "An initial snapshot file should be generated even when it is pinned");
assertHeaderEquals(changeSet, createHeaders(driftDef, COVERAGE));
@@ -878,7 +897,7 @@ public class DriftDetectorTest extends DriftTest {
// generate the pinned snapshot which is version zero
File pinnedSnapshot = pinnedSnapshot(driftDef.getName());
ChangeSetWriter writer = new ChangeSetWriterImpl(pinnedSnapshot, headers);
- writer.write(addedFileEntry("conf/server.conf", serverConfHash));
+ writer.write(addedFileEntry("conf/server.conf", serverConfHash, serverConf.lastModified(), serverConf.length()));
writer.close();
// generate the current snapshot file. we will take a shortcut here by
@@ -910,7 +929,8 @@ public class DriftDetectorTest extends DriftTest {
// verify that that current snapshot has been updated to reflect that
// the resource is back in compliance.
- List<FileEntry> entries = asList(addedFileEntry("conf/server.conf", serverConfHash));
+ List<FileEntry> entries = asList(addedFileEntry("conf/server.conf", serverConfHash,
+ serverConf.lastModified(), serverConf.length()));
assertHeaderEquals(currentSnapshot, createHeaders(driftDef, COVERAGE, 2));
assertFileEntriesMatch("The entries in the current snapshot should match those in the pinned snapshot " +
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
index 5fd6528..b102300 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
@@ -19,6 +19,11 @@
package org.rhq.core.pc.drift;
+import static org.rhq.common.drift.FileEntry.addedFileEntry;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@@ -32,11 +37,6 @@ import org.rhq.core.domain.drift.DriftChangeSetCategory;
import org.rhq.core.domain.drift.DriftFile;
import org.rhq.core.domain.drift.JPADriftFile;
-import static org.rhq.common.drift.FileEntry.addedFileEntry;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
public class DriftFilesSenderTest extends DriftTest {
DriftClient driftClient;
@@ -69,8 +69,10 @@ public class DriftFilesSenderTest extends DriftTest {
Headers headers = createHeaders(driftDefName, COVERAGE);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), headers);
- writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash));
- writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash));
+ writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash, server1Conf.lastModified(),
+ server1Conf.length()));
+ writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash, server2Conf.lastModified(),
+ server2Conf.length()));
writer.close();
sender.setDriftFiles(driftFiles(server1ConfHash, server2ConfHash));
@@ -105,10 +107,14 @@ public class DriftFilesSenderTest extends DriftTest {
Headers headers = createHeaders(driftDefName, COVERAGE);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), headers);
- writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash));
- writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash));
- writer.write(addedFileEntry("lib/server-1.jar", server1JarHash));
- writer.write(addedFileEntry("lib/server-2.jar", server2JarHash));
+ writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash, server1Conf.lastModified(),
+ server1Conf.length()));
+ writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash, server2Conf.lastModified(),
+ server2Conf.length()));
+ writer.write(addedFileEntry("lib/server-1.jar", server1JarHash, server1Jar.lastModified(),
+ server1Jar.length()));
+ writer.write(addedFileEntry("lib/server-2.jar", server2JarHash, server2Jar.lastModified(),
+ server2Jar.length()));
writer.close();
// Note that the order of the drift files is random. When the server sends a request
@@ -142,8 +148,10 @@ public class DriftFilesSenderTest extends DriftTest {
Headers headers = createHeaders(driftDefName, COVERAGE);
ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), headers);
- writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash));
- writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash));
+ writer.write(addedFileEntry("conf/server-1.conf", server1ConfHash, server1Conf.lastModified(),
+ server1Conf.length()));
+ writer.write(addedFileEntry("conf/server-2.conf", server2ConfHash, server2Conf.lastModified(),
+ server2Conf.length()));
writer.close();
// It is possible that the server can request a file that has been deleted since it
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftTest.java
index 41b725b..2f238f8 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftTest.java
@@ -229,9 +229,13 @@ public class DriftTest {
}
protected File createRandomFile(File dir, String fileName) throws Exception {
+ return createRandomFile(dir, fileName, 32);
+ }
+
+ protected File createRandomFile(File dir, String fileName, int numBytes) throws Exception {
File file = new File(dir, fileName);
FileOutputStream stream = new FileOutputStream(file);
- byte[] bytes = new byte[32];
+ byte[] bytes = new byte[numBytes];
random.nextBytes(bytes);
write(bytes, stream);
stream.close();
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/drift/DriftManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/drift/DriftManagerBeanTest.java
index 5dabd97..f7152a9 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/drift/DriftManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/drift/DriftManagerBeanTest.java
@@ -158,7 +158,7 @@ public class DriftManagerBeanTest extends AbstractEJB3Test {
File changeSet1 = new File(changeSetsDir, "changeset-1.txt");
ChangeSetWriter writer = new ChangeSetWriterImpl(changeSet1, headers);
- writer.write(addedFileEntry("test/file-1", file1Hash));
+ writer.write(addedFileEntry("test/file-1", file1Hash, 56789L, 1024L));
writer.close();
File changeSet1Zip = new File(changeSetsDir, "changeset-1.zip");
@@ -188,7 +188,7 @@ public class DriftManagerBeanTest extends AbstractEJB3Test {
File changeSet2 = new File(changeSetsDir, "changeset-2.txt");
writer = new ChangeSetWriterImpl(changeSet2, headers);
- writer.write(changedFileEntry("test/file-1", file1Hash, modifiedFile1Hash));
+ writer.write(changedFileEntry("test/file-1", file1Hash, modifiedFile1Hash, 56789L, 1024L));
writer.close();
File changeSet2Zip = new File(changeSetsDir, "changeset-2.zip");
12 years, 4 months
[rhq] Branch 'lkrejci/dissalow-alert-scripts-from-accessing-local-slsbs' - 60 commits - modules/core modules/enterprise modules/integration-tests modules/jopr modules/plugins modules/test-utils pom.xml
by lkrejci
modules/core/dbutils/pom.xml | 2
modules/core/dbutils/src/main/java/org/rhq/core/db/DatabaseType.java | 20
modules/core/dbutils/src/main/java/org/rhq/core/db/OracleDatabaseType.java | 4
modules/core/dbutils/src/main/java/org/rhq/core/db/PostgresqlDatabaseType.java | 2
modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DriftPathDirectoryDatabaseUpgradeTask.java | 71
modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DriftTemplateMapDatabaseUpgradeTask.java | 116
modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml | 60
modules/core/dbutils/src/test/java/org/rhq/core/db/ant/dbupdate/SchemaVersionTest.java | 2
modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftConfigurationDefinition.java | 7
modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftDefinition.java | 4
modules/core/domain/src/main/java/org/rhq/core/domain/drift/Filter.java | 2
modules/core/plugin-container/src/main/java/org/rhq/core/pc/bundle/BundleManager.java | 39
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java | 210
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftFilesSender.java | 37
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ScheduleQueue.java | 2
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ScheduleQueueImpl.java | 31
modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftClientTestStub.java | 11
modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftDetectorTest.java | 94
modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java | 40
modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftManagerTest.java | 2
modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/AbstractPerspectiveResourceUIBean.java | 2
modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/PerspectiveClientUIBean.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDataStep.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentListView.java | 10
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleResourceDeploymentHistoryListView.java | 3
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/IsLongValidator.java | 13
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/AbstractWizard.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/AbstractWizardStep.java | 5
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/Wizard.java | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/WizardStep.java | 38
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/WizardView.java | 13
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java | 7
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselMemberView.java | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java | 21
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftAddDefinitionWizardInfoStep.java | 7
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/summary/ActivityView.java | 46
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java | 9
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryConfigurationStep.java | 37
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties | 508
modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml | 6
modules/enterprise/gui/rest-war/src/main/webapp/bars_simple.html | 206
modules/enterprise/gui/rest-war/src/main/webapp/index.html | 1
modules/enterprise/gui/rest-war/src/main/webapp/js/jquery.js | 9266 ++++++++++
modules/enterprise/gui/rest-war/src/main/webapp/js/resource_tree.js | 3
modules/enterprise/gui/rest-war/src/main/webapp/js/rhq.js | 120
modules/enterprise/gui/rest-war/src/main/webapp/js/whisker.js | 92
modules/enterprise/gui/rest-war/src/main/webapp/stacked1.html | 74
modules/enterprise/gui/rest-war/src/main/webapp/stacked2.html | 182
modules/enterprise/gui/rest-war/src/main/webapp/whisker.html | 92
modules/enterprise/gui/rest-war/src/main/webapp/whisker2.html | 61
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java | 1
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java | 1
modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/LoginCommand.java | 4
modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java | 2
modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/client/RemoteClient.java | 506
modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/client/RemoteClientProxy.java | 101
modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java | 506
modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java | 101
modules/enterprise/server/client-api/pom.xml | 7
modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/security/test/EjbAccessTest.java | 111
modules/enterprise/server/client-api/src/test/resources/META-INF/ejb-jar.xml | 34
modules/enterprise/server/client-api/src/test/resources/META-INF/jboss.xml | 168
modules/enterprise/server/container-lib/pom.xml | 5
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingContextDecorator.java | 237
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryBuilder.java | 180
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryDecorator.java | 60
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AllowRhqServerInternalsAccessPermission.java | 36
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java | 104
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java | 54
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstaller.java | 45
modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstallerMBean.java | 32
modules/enterprise/server/container/pom.xml | 19
modules/enterprise/server/container/src/main/resources/jbossas/server/default/conf/jboss-service.xml | 7
modules/enterprise/server/container/src/main/resources/jbossas/server/default/deploy/rhq-cache-service.xml | 170
modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml | 21
modules/enterprise/server/ear/pom.xml | 69
modules/enterprise/server/jar/pom.xml | 39
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SessionManager.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java | 28
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerBean.java | 9
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java | 283
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java | 38
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java | 286
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java | 78
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java | 266
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java | 49
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java | 315
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java | 94
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ParameterMissingException.java | 12
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java | 207
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java | 60
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java | 68
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 | 12
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java | 3
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertRest.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AvailabilityRest.java | 3
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java | 82
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Link.java | 50
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricAggregate.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java | 58
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationDefinitionRest.java | 52
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationHistoryRest.java | 72
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationRest.java | 117
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java | 28
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Status.java | 68
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessInterceptor.java | 46
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessPermission.java | 36
modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml | 6
modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl | 49
modules/enterprise/server/jar/src/main/resources/rest_templates/listGroup.ftl | 32
modules/enterprise/server/jar/src/main/resources/rest_templates/metricData.ftl | 4
modules/enterprise/server/jar/src/main/resources/rest_templates/metricSchedule.ftl | 9
modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl | 2
modules/enterprise/server/jar/src/main/resources/rest_templates/status.ftl | 21
modules/enterprise/server/jar/src/test/resources/embedded-jboss-beans.xml | 10
modules/integration-tests/rest-api/README.md | 13
modules/integration-tests/rest-api/pom.xml | 56
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GetStatusTest.java | 78
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java | 104
modules/jopr/modules-plugins-pom.xml | 148
modules/jopr/modules-pom.xml | 248
modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/JBossASDiscoveryComponent.java | 96
modules/plugins/platform/src/main/java/org/rhq/plugins/platform/CpuComponent.java | 11
modules/plugins/rhq-agent/src/main/java/org/rhq/plugins/agent/AgentDiscoveryComponent.java | 2
modules/plugins/script/src/main/java/org/rhq/plugins/script/ScriptDiscoveryComponent.java | 2
modules/test-utils/src/main/java/org/rhq/test/DuplicatePackagesDetector.java | 194
pom.xml | 3
129 files changed, 15240 insertions(+), 2503 deletions(-)
New commits:
commit f2803b9046bfe26c9cbc80ec15bd458ac4f46db5
Merge: 8f9acfd 35fcafb
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Dec 19 19:56:15 2011 +0100
Merge branch 'master' into lkrejci/dissalow-alert-scripts-from-accessing-local-slsbs
commit 8f9acfd64f725fb1ce4d1fafb3e44fde57de4b99
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Dec 19 19:55:08 2011 +0100
Revamped the script security to apply the checks at the JNDI lookup level
to support restricting access to EntityManager or a datasource.
diff --git a/modules/enterprise/server/client-api/pom.xml b/modules/enterprise/server/client-api/pom.xml
index 6932b60..4dfd109 100644
--- a/modules/enterprise/server/client-api/pom.xml
+++ b/modules/enterprise/server/client-api/pom.xml
@@ -93,6 +93,13 @@
</dependency>
<dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-container-lib</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
<groupId>hibernate</groupId>
<artifactId>hibernate3</artifactId>
<!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
diff --git a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/security/test/EjbAccessTest.java b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/security/test/EjbAccessTest.java
index 9c9d1bb..dc1fc83 100644
--- a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/security/test/EjbAccessTest.java
+++ b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/security/test/EjbAccessTest.java
@@ -22,9 +22,6 @@ import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.SerializablePermission;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
import java.security.PermissionCollection;
import java.util.Collections;
@@ -41,9 +38,9 @@ import org.rhq.bindings.StandardScriptPermissions;
import org.rhq.bindings.util.PackageFinder;
import org.rhq.core.domain.auth.Subject;
import org.rhq.enterprise.client.LocalClient;
-import org.rhq.enterprise.server.security.AllowEjbAccessPermission;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.jndi.AllowRhqServerInternalsAccessPermission;
/**
*
@@ -78,7 +75,7 @@ public class EjbAccessTest extends AbstractEJB3Test {
Assert.fail("The script shouldn't have been able to call local SLSB method.");
} catch (ScriptException e) {
- assert e.getMessage().contains(AllowEjbAccessPermission.class.getName());
+ checkIsDesiredSecurityException(e);
}
}
@@ -95,66 +92,34 @@ public class EjbAccessTest extends AbstractEJB3Test {
Assert.fail("The script shouldn't have been able to call remote SLSB method directly.");
} catch (ScriptException e) {
- //TODO java.io.IOException: access denied (java.io.SerializablePermission enableSubclassImplementation)
- assert e.getMessage().contains(AllowEjbAccessPermission.class.getName());
+ checkIsDesiredSecurityException(e);
}
}
- public void testScriptCantUseSessionManager() throws ScriptException, IOException {
- Subject overlord = LookupUtil.getSubjectManager().getOverlord();
-
- ScriptEngine engine = getEngine(overlord);
-
- try {
- engine.eval("org.rhq.enterprise.server.auth.SessionManager.getInstance();");
-
- Assert.fail("The script shouldn't have been able to get instance of SessionManager.");
- } catch (ScriptException e) {
- assert e.getMessage().contains(AllowEjbAccessPermission.class.getName());
- }
- }
-
- @SuppressWarnings("unused")
public void testScriptCantUseSessionManagerMethods() throws Exception {
- //The code below cannot work in Rhino because as of now, Rhino modifies
- //the return value of Class.getDeclaredField() to be null when there
- //is a security manager installed.
- //This has been filed as a bug at Oracle (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7119959)
-
- if (true) {
- return;
- }
-
Subject overlord = LookupUtil.getSubjectManager().getOverlord();
final ScriptEngine engine = getEngine(overlord);
class G {
- private String obtainSessionManagerUsingReflection = ""
- + "var sessionManagerClass = java.lang.Class.forName(\"org.rhq.enterprise.server.auth.SessionManager\");\n"
- + "println(sessionManagerClass);\n"
- + "var managerField = sessionManagerClass.getDeclaredField(\"_manager\");\n"
- + "println(managerField);\n"
- + "managerField.setAccessible(true);\n"
- + "var manager = managerField.get(null);\n"
- + "println(manager);\n"
- + "manager.";
+ private String sessionManager = ""
+ + "org.rhq.enterprise.server.auth.SessionManager.getInstance().";
public void testInvoke(String methodCall) throws ScriptException {
- String code = obtainSessionManagerUsingReflection + methodCall;
+ String code = sessionManager + methodCall;
try {
engine.eval(code);
- Assert.fail("The script shouldn't have been able to a method on a SessionManager.");
+ Assert.fail("The script shouldn't have been able to call a method on a SessionManager: " + methodCall);
} catch (ScriptException e) {
- assert e.getMessage().contains(AllowEjbAccessPermission.class.getName());
+ checkIsDesiredSecurityException(e);
}
}
};
G manager = new G();
- manager.testInvoke("getLastAccess(0);");
+ manager.testInvoke("getlastAccess(0);");
manager.testInvoke("getOverlord()");
manager.testInvoke("getSubject(2);");
manager.testInvoke("invalidate(0);");
@@ -163,6 +128,57 @@ public class EjbAccessTest extends AbstractEJB3Test {
manager.testInvoke("put(new org.rhq.core.domain.auth.Subject(), 0);");
}
+ public void testScriptCantObtainRawJDBCConnectionsWithoutCredentials() throws Exception {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ ScriptEngine engine = getEngine(overlord);
+
+ try {
+ engine.eval(""
+ + "context = new javax.naming.InitialContext();\n"
+ + "datasource = context.lookup('java:/RHQDS');\n"
+ + "con = datasource.getConnection();");
+
+ Assert.fail("The script shouldn't have been able to obtain the datasource from the JNDI.");
+ } catch (ScriptException e) {
+ checkIsDesiredSecurityException(e);
+ }
+ }
+
+ public void testScriptCantUseEntityManager() throws Exception {
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ ScriptEngine engine = getEngine(overlord);
+
+ try {
+ engine.eval(""
+ + "context = new javax.naming.InitialContext();\n"
+ + "entityManagerFactory = context.lookup('java:/RHQEntityManagerFactory');\n"
+ + "entityManager = entityManagerFactory.createEntityManager();\n"
+ + "entityManager.find(java.lang.Class.forName('org.rhq.core.domain.resource.Resource'), java.lang.Integer.valueOf('10001'));");
+
+ Assert.fail("The script shouldn't have been able to use the EntityManager.");
+ } catch (ScriptException e) {
+ checkIsDesiredSecurityException(e);
+ }
+
+ //try harder with manually specifying the initial context factory
+ try {
+ engine.eval(""
+ + "env = new java.util.Hashtable();"
+ + "env.put('java.naming.factory.initial', 'org.jnp.interfaces.LocalOnlyContextFactory');"
+ + "env.put('java.naming.factory.url.pkgs', 'org.jboss.naming:org.jnp.interfaces');"
+ + "context = new javax.naming.InitialContext(env);\n"
+ + "entityManagerFactory = context.lookup('java:/RHQEntityManagerFactory');\n"
+ + "entityManager = entityManagerFactory.createEntityManager();\n"
+ + "entityManager.find(java.lang.Class.forName('org.rhq.core.domain.resource.Resource'), java.lang.Integer.valueOf('10001'));");
+
+ Assert.fail("The script shouldn't have been able to use the EntityManager even using custom initial context factory.");
+ } catch (ScriptException e) {
+ checkIsDesiredSecurityException(e);
+ }
+ }
+
private ScriptEngine getEngine(Subject subject) throws ScriptException, IOException {
StandardBindings bindings = new StandardBindings(new PrintWriter(System.out), new LocalClient(subject));
ScriptEngine engine = ScriptEngineFactory.getScriptEngine("JavaScript", new PackageFinder(Collections.<File>emptyList()), bindings);
@@ -172,4 +188,11 @@ public class EjbAccessTest extends AbstractEJB3Test {
return new SandboxedScriptEngine(engine, perms);
}
+
+ private static void checkIsDesiredSecurityException(ScriptException e) {
+ String message = e.getMessage();
+ String permissionTrace = AllowRhqServerInternalsAccessPermission.class.getName();
+
+ Assert.assertTrue(message.contains(permissionTrace), "The script exception doesn't seem to be caused by the AllowRhqServerInternalsAccessPermission security exception. " + message);
+ }
}
diff --git a/modules/enterprise/server/client-api/src/test/resources/META-INF/ejb-jar.xml b/modules/enterprise/server/client-api/src/test/resources/META-INF/ejb-jar.xml
deleted file mode 100644
index caa7513..0000000
--- a/modules/enterprise/server/client-api/src/test/resources/META-INF/ejb-jar.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
- version="3.0">
-
- <description>RHQ</description>
- <display-name>RHQ</display-name>
-
- <assembly-descriptor>
-
- <!-- This interceptor checks that the alert CLI scripts don't try to circumvent our access objects by accessing the local SLSB beans directly. -->
- <interceptor-binding>
- <ejb-name>*</ejb-name>
- <interceptor-class>org.rhq.enterprise.server.security.AllowEjbAccessInterceptor</interceptor-class>
- </interceptor-binding>
-
- <!-- all our EJB3 SLSBs can define custom @RequiredPermissions annotations for authorization checks-->
- <interceptor-binding>
- <ejb-name>*</ejb-name>
- <interceptor-class>org.rhq.enterprise.server.authz.RequiredPermissionsInterceptor</interceptor-class>
- </interceptor-binding>
- <interceptor-binding>
- <ejb-name>*</ejb-name>
- <interceptor-class>org.rhq.enterprise.server.common.TransactionInterruptInterceptor</interceptor-class>
- </interceptor-binding>
- <interceptor-binding>
- <ejb-name>*</ejb-name>
- <interceptor-class>org.rhq.enterprise.server.common.PerformanceMonitorInterceptor</interceptor-class>
- </interceptor-binding>
-
- </assembly-descriptor>
-
-</ejb-jar>
diff --git a/modules/enterprise/server/client-api/src/test/resources/META-INF/jboss.xml b/modules/enterprise/server/client-api/src/test/resources/META-INF/jboss.xml
deleted file mode 100644
index b7c5c66..0000000
--- a/modules/enterprise/server/client-api/src/test/resources/META-INF/jboss.xml
+++ /dev/null
@@ -1,168 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<jboss xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss_5_0.xsd"
- version="3.0">
-
- <enterprise-beans>
-
- <!--
- The AlertConditionLogManagerBean, AlertConditionManagerBean, AlertDampeningManagerBean,
- AlertDefinitionManagerBean, AlertManagerBean, AuthorizationManagerBean, CachedConditionManagerBean, and
- SubjectManager SLSB's are all invoked, either directly or indirectly, by the AlertConditionConsumerBean MDB.
- Since MDB invocations are always done in new threads, using the default SLSB pool impl (ThreadlocalPool) would
- cause a new instance of these SLSB's to be created every time they were invoked by AlertConditionConsumerBean.
- This would be bad if only because existing instances would
- not be reused, but it is really bad because the instances would also never get destroyed, causing heap space to
- gradually leak until the Server eventually ran out of memory. Hence, we must use a StrictMaxPool, which
- will use a fixed pool of instances of this SLSB, instead of a ThreadlocalPool. Because lots of alert
- definitions could result in many concurrent calls to AlertConditionConsumerBean, and because most of these
- SLSB's are also invoked by other callers (i.e. Agents, GUI's, or CLI's), we set the max pool size to 100 to
- minimize the chances of AlertConditionConsumerBean invocations, which are the most critical, from having to
- block and potentially getting backed up in the queue. We set the pool timeout extremely high to essentially
- prevent queued callers from timing out. Note, MDB's are configured in ejb3-interceptors-aop.xml to use a strict
- max pool with a max of 15 and a timeout of 10000, so AlertConditionConsumerBean might become a bottleneck for
- systems with a lot of alerts defined. (ips, 05/10/11)
-
- For more details, see https://bugzilla.redhat.com/show_bug.cgi?id=693232 .
- -->
-
- <session>
- <ejb-name>AlertConditionLogManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>AlertConditionManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>AlertDampeningManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>AlertDefinitionManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>AlertManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>AuthorizationManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>CachedConditionManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>SubjectManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>100</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
-
- <!--
- The CacheConsistencyManagerBean, CloudManagerBean, ServerManagerBean, StatusManagerBean, and SystemManagerBean
- SLSB's are all invoked, either directly or indirectly, by EJB timers. Since EJB timer invocations are always
- done in new threads, using the default SLSB pool impl (ThreadlocalPool) would cause a new instance of this
- SLSB to be created every time it was invoked by an EJB timer. This would be bad if only because an existing
- instance would not be reused, but it is really bad because the instance would also never get destroyed, causing
- heap space to gradually leak until the Server eventually ran out of memory. Hence, we must use a
- StrictMaxPool, which will use a fixed pool of instances of this SLSB, instead of a ThreadlocalPool.
- The timer invocations will only require one or two instances at any given time, but because most of these
- SLSB's are also invoked by other callers (i.e. Agents, GUI's, or CLI's, we set the max pool size to 30, to
- minimize the chances of EJB timer invocations, which are the most critical, from having to block and
- potentially getting backed up in the queue. We set the pool timeout extremely high to essentially prevent
- queued callers from timing out. (ips, 05/10/11)
-
- For more details, see https://bugzilla.redhat.com/show_bug.cgi?id=693232 .
- -->
-
- <session>
- <ejb-name>CacheConsistencyManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>30</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>CloudManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>30</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>ServerManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>30</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>StatusManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>30</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- <session>
- <ejb-name>SystemManagerBean</ejb-name>
- <pool-config>
- <pool-class>org.jboss.ejb3.StrictMaxPool</pool-class>
- <pool-max-size>30</pool-max-size>
- <pool-timeout>1000000000</pool-timeout>
- </pool-config>
- </session>
-
- </enterprise-beans>
-
-</jboss>
diff --git a/modules/enterprise/server/container-lib/pom.xml b/modules/enterprise/server/container-lib/pom.xml
index b832b06..9d7d603 100644
--- a/modules/enterprise/server/container-lib/pom.xml
+++ b/modules/enterprise/server/container-lib/pom.xml
@@ -39,6 +39,11 @@
<scope>provided</scope> <!-- by JBossAS -->
</dependency>
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jnpserver</artifactId>
+ <version>4.2.2.GA</version>
+ </dependency>
</dependencies>
<profiles>
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingContextDecorator.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingContextDecorator.java
new file mode 100644
index 0000000..df42afe
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingContextDecorator.java
@@ -0,0 +1,237 @@
+/*
+ * 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.jndi;
+
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NameClassPair;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+
+/**
+ * This is the "meat" of the RHQ's secured JNDI access. This {@link Context} decorator
+ * applied security checks in each method (lookups, (un)bindings, etc).
+ * <p>
+ * The security check consists of checking if the current callstack has the {@link AllowRhqServerInternalsAccessPermission}.
+ * <p>
+ * This decorator applies the security check on any JNDI name without a scheme and
+ * on any name that has a scheme listed in the {@link #checkedSchemes} list supplied
+ * in the constructor.
+ *
+ * @author Lukas Krejci
+ */
+public class AccessCheckingContextDecorator implements Context {
+
+ private static final AllowRhqServerInternalsAccessPermission PERM = new AllowRhqServerInternalsAccessPermission();
+ private Context original;
+ private List<String> checkedSchemes;
+
+ public AccessCheckingContextDecorator(Context original, String... checkedSchemes) {
+ this.original = original;
+ this.checkedSchemes = Arrays.asList(checkedSchemes);
+ }
+
+ private static void check() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) sm.checkPermission(PERM);
+ }
+
+ private void checkScheme(String scheme) {
+ if (scheme == null || checkedSchemes.contains(scheme)) {
+ check();
+ }
+ }
+
+ private void check(String name) {
+ checkScheme(getURLScheme(name));
+ }
+
+ private void check(Name name) {
+ if (name.size() == 0) {
+ check();
+ } else {
+ String first = name.get(0);
+ checkScheme(getURLScheme(first));
+ }
+ }
+
+ public Object lookup(Name name) throws NamingException {
+ check(name);
+ return original.lookup(name);
+ }
+
+ public Object lookup(String name) throws NamingException {
+ check(name);
+ return original.lookup(name);
+ }
+
+ public void bind(Name name, Object obj) throws NamingException {
+ check(name);
+ original.bind(name, obj);
+ }
+
+ public void bind(String name, Object obj) throws NamingException {
+ check(name);
+ original.bind(name, obj);
+ }
+
+ public void rebind(Name name, Object obj) throws NamingException {
+ check(name);
+ original.rebind(name, obj);
+ }
+
+ public void rebind(String name, Object obj) throws NamingException {
+ check(name);
+ original.rebind(name, obj);
+ }
+
+ public void unbind(Name name) throws NamingException {
+ check(name);
+ original.unbind(name);
+ }
+
+ public void unbind(String name) throws NamingException {
+ check(name);
+ original.unbind(name);
+ }
+
+ public void rename(Name oldName, Name newName) throws NamingException {
+ check(oldName);
+ check(newName);
+ original.rename(oldName, newName);
+ }
+
+ public void rename(String oldName, String newName) throws NamingException {
+ check(oldName);
+ check(newName);
+ original.rename(oldName, newName);
+ }
+
+ public NamingEnumeration<NameClassPair> list(Name name) throws NamingException {
+ check(name);
+ return original.list(name);
+ }
+
+ public NamingEnumeration<NameClassPair> list(String name) throws NamingException {
+ check(name);
+ return original.list(name);
+ }
+
+ public NamingEnumeration<Binding> listBindings(Name name) throws NamingException {
+ check(name);
+ return original.listBindings(name);
+ }
+
+ public NamingEnumeration<Binding> listBindings(String name) throws NamingException {
+ check(name);
+ return original.listBindings(name);
+ }
+
+ public void destroySubcontext(Name name) throws NamingException {
+ check(name);
+ original.destroySubcontext(name);
+ }
+
+ public void destroySubcontext(String name) throws NamingException {
+ check(name);
+ original.destroySubcontext(name);
+ }
+
+ public Context createSubcontext(Name name) throws NamingException {
+ check(name);
+ return original.createSubcontext(name);
+ }
+
+ public Context createSubcontext(String name) throws NamingException {
+ check(name);
+ return original.createSubcontext(name);
+ }
+
+ public Object lookupLink(Name name) throws NamingException {
+ check(name);
+ return original.lookupLink(name);
+ }
+
+ public Object lookupLink(String name) throws NamingException {
+ check(name);
+ return original.lookupLink(name);
+ }
+
+ public NameParser getNameParser(Name name) throws NamingException {
+ check(name);
+ return original.getNameParser(name);
+ }
+
+ public NameParser getNameParser(String name) throws NamingException {
+ check(name);
+ return original.getNameParser(name);
+ }
+
+ public Name composeName(Name name, Name prefix) throws NamingException {
+ check(name);
+ return original.composeName(name, prefix);
+ }
+
+ public String composeName(String name, String prefix) throws NamingException {
+ check(name);
+ return original.composeName(name, prefix);
+ }
+
+ public Object addToEnvironment(String propName, Object propVal) throws NamingException {
+ check();
+ return original.addToEnvironment(propName, propVal);
+ }
+
+ public Object removeFromEnvironment(String propName) throws NamingException {
+ check();
+ return original.removeFromEnvironment(propName);
+ }
+
+ public Hashtable<?, ?> getEnvironment() throws NamingException {
+ check();
+ return original.getEnvironment();
+ }
+
+ public void close() throws NamingException {
+ check();
+ original.close();
+ }
+
+ public String getNameInNamespace() throws NamingException {
+ check();
+ return original.getNameInNamespace();
+ }
+
+ //copied from InitialContext
+ private static String getURLScheme(String str) {
+ int colon_posn = str.indexOf(':');
+ int slash_posn = str.indexOf('/');
+
+ if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))
+ return str.substring(0, colon_posn);
+ return null;
+ }
+}
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryBuilder.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryBuilder.java
new file mode 100644
index 0000000..1a9562a
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryBuilder.java
@@ -0,0 +1,180 @@
+/*
+ * 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.jndi;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.UnknownHostException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+import javax.naming.spi.InitialContextFactoryBuilder;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jnp.interfaces.NamingContextFactory;
+
+/**
+ * This initial context factory builder is installed early on during the RHQ server startup
+ * and is later on used for obtaining the {@link Context}s for all JNDI lookups in the
+ * RHQ server.
+ * <p>
+ * We use a custom initial context factory builder to prevent the potential malicious 3rd party
+ * code (like CLI alert scripts) from supplying custom environment variables to {@link InitialContext}
+ * that would modify the JNDI lookup to skip our security access checks.
+ * <p>
+ * By using a builder we effectively take control of the initial context creation process
+ * and are free to ignore whatever the script is trying to supply.
+ * <p>
+ * This builder makes sure to install the RHQ server's security access checks to whatever
+ * initial context that is configured by the standard environment variables
+ * ({@link Context#INITIAL_CONTEXT_FACTORY}, etc.)
+ * <p>
+ * This class is heavily inspired by the implementation of a similar builder in JBoss AS 7.
+ *
+ * @see AllowRhqServerInternalsAccessPermission
+ *
+ * @author Lukas Krejci
+ */
+public class AccessCheckingInitialContextFactoryBuilder implements InitialContextFactoryBuilder {
+ private static final Log LOG = LogFactory.getLog(AccessCheckingInitialContextFactoryBuilder.class);
+
+ /**
+ * The list of JNDI name schemes that should be checked for security permissions
+ * (in addition to the names with no scheme).
+ *
+ * @see AccessCheckingContextDecorator
+ */
+ private static final String[] CHECKED_SCHEMES = { "java" };
+
+ private static final Set<InetAddress> SERVER_BIND_IPS;
+
+ static {
+ SERVER_BIND_IPS = new HashSet<InetAddress>();
+
+ try {
+ String bindingAddressString = System.getProperty("jboss.bind.address");
+ InetAddress bindingAddress = InetAddress.getByName(bindingAddressString);
+
+ if (bindingAddress.isAnyLocalAddress()) {
+ Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
+ while(ifaces.hasMoreElements()) {
+ NetworkInterface iface = ifaces.nextElement();
+ SERVER_BIND_IPS.addAll(Collections.list(iface.getInetAddresses()));
+ }
+ } else {
+ SERVER_BIND_IPS.add(bindingAddress);
+ }
+ } catch (SocketException e) {
+ LOG.error("Could not obtain the list of local IPs", e);
+ } catch (UnknownHostException e) {
+ LOG.error("Failed to get the binding address of the RHQ server.", e);
+ }
+
+ }
+
+ /**
+ * This is the default initial context factory that is returned when no other is
+ * configured using the environment variables.
+ * <p>
+ * It uses {@link NamingContextFactory} as the underlying mechanism - the same
+ * as the default configuration in JBoss 4.
+ */
+ private static final InitialContextFactory DEFAULT_FACTORY = new InitialContextFactory() {
+ public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
+ return createSecureWrapper(new NamingContextFactory(), environment).getInitialContext(environment);
+ }
+ };
+
+ /**
+ * Create a InitialContext factory. If the environment does not override the factory class it will use the
+ * default context factory.
+ *
+ * @param environment The environment
+ * @return An initial context factory
+ * @throws NamingException If an error occurs loading the factory class.
+ */
+ public InitialContextFactory createInitialContextFactory(Hashtable<?, ?> environment) throws NamingException {
+ final String factoryClassName = (String) environment.get(Context.INITIAL_CONTEXT_FACTORY);
+ if (factoryClassName == null) {
+ return DEFAULT_FACTORY;
+ }
+ final ClassLoader classLoader = getContextClassLoader();
+ try {
+ final Class<?> factoryClass = Class.forName(factoryClassName, true, classLoader);
+ InitialContextFactory configuredFactory = (InitialContextFactory) factoryClass.newInstance();
+ return createSecureWrapper(configuredFactory, environment);
+ } catch (Exception e) {
+ throw new NamingException("Failed instantiate InitialContextFactory " + factoryClassName
+ + " from classloader " + classLoader);
+ }
+ }
+
+ private ClassLoader getContextClassLoader() {
+ return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ }
+
+ private static InitialContextFactory createSecureWrapper(InitialContextFactory factory, Hashtable<?, ?> environment) {
+ String providerUrl = (String) environment.get(Context.PROVIDER_URL);
+
+ if (providerUrl == null) {
+ return new AccessCheckingInitialContextFactoryDecorator(factory, CHECKED_SCHEMES);
+ } else {
+ try {
+ URI uri = new URI(providerUrl);
+ InetAddress providerHost = InetAddress.getByName(uri.getHost());
+
+ //check if we are accessing the RHQ server through some remoting
+ //interface.
+ //I just can't find where to read the magic number 1099 from.
+ //it is defined in the jboss config files, but in the code
+ //it seems hardcoded - see JDBCLoginModule.
+ if (uri.getPort() == 1099 && SERVER_BIND_IPS.contains(providerHost)) {
+ return new AccessCheckingInitialContextFactoryDecorator(factory, CHECKED_SCHEMES);
+ } else {
+ return new URLPreferringInitialContextFactoryDecorator(factory);
+ }
+ } catch (URISyntaxException e) {
+ return new AccessCheckingInitialContextFactoryDecorator(factory, CHECKED_SCHEMES);
+ } catch (UnknownHostException e) {
+ //let the factory deal with the unknown host...
+ //this most probably shouldn't be secured because localhost addresses
+ //should be resolvable.
+ return new URLPreferringInitialContextFactoryDecorator(factory);
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryDecorator.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryDecorator.java
new file mode 100644
index 0000000..b23935f
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AccessCheckingInitialContextFactoryDecorator.java
@@ -0,0 +1,60 @@
+/*
+ * 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.jndi;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+
+/**
+ * A decorator of an {@link InitialContextFactory} that adds the security checking
+ * machinery to the returned initial contexts.
+ *
+ * @author Lukas Krejci
+ */
+public class AccessCheckingInitialContextFactoryDecorator extends URLPreferringInitialContextFactoryDecorator {
+
+ private final String[] checkedSchemes;
+
+ /**
+ * @param factory the factory to wrap
+ * @param checkedSchemes the list of JNDI name schemes to check for permissions
+ * @see AccessCheckingContextDecorator
+ */
+ public AccessCheckingInitialContextFactoryDecorator(InitialContextFactory factory, String... checkedSchemes) {
+ super(factory);
+ this.checkedSchemes = checkedSchemes;
+ }
+
+ /**
+ * @param environment the environment variables for the return {@link Context} to use
+ *
+ * @return the initial context returned by the decorated factory wrapped in
+ * {@link URLPreferringContext} and {@link AccessCheckingContextDecorator} in that
+ * order.
+ */
+ @Override
+ public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
+ return new AccessCheckingContextDecorator(super.getInitialContext(environment), checkedSchemes);
+ }
+
+}
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AllowRhqServerInternalsAccessPermission.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AllowRhqServerInternalsAccessPermission.java
new file mode 100644
index 0000000..aa807d6
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/AllowRhqServerInternalsAccessPermission.java
@@ -0,0 +1,36 @@
+/*
+ * 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.jndi;
+
+import java.security.BasicPermission;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class AllowRhqServerInternalsAccessPermission extends BasicPermission {
+
+ private static final long serialVersionUID = 1L;
+
+ public AllowRhqServerInternalsAccessPermission() {
+ super("org.rhq.allow.server.internals.access");
+ }
+}
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java
new file mode 100644
index 0000000..b291c3e
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringContext.java
@@ -0,0 +1,104 @@
+/*
+ * 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.jndi;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+import javax.naming.spi.NamingManager;
+
+/**
+ * This is a modification of the default {@link InitialContext} class that
+ * ignores the initial context factory builder when constructing the default
+ * context to use in lookups etc.
+ * <p>
+ * This is important because RHQ server has its own initial context factory
+ * builder that creates factories that in turn create contexts. If the default
+ * {@link InitialContext} implementation was used, we'd end up with a stack overflow
+ * error caused by the callchain loop when the {@link InitialContext} would ask
+ * the builder for a factory that would create another context that would ask the
+ * builder for the factory, etc. ad infinitum.
+ * <p>
+ * This class prevents that by acting exactly like the InitialContext would if
+ * the initial context factory builder wasn't installed. This enables the callers
+ * to still use the standard InitialContext when doing lookups etc. This standard
+ * initial context will ask our initial context factory builder which will then
+ * in chain create this {@link URLPreferringContext} that behaves like the original
+ * InitialContext would if the builder wasn't there.
+ *
+ * @author Lukas Krejci
+ */
+public class URLPreferringContext extends InitialContext {
+
+ public URLPreferringContext(InitialContextFactory defaultContextFactory) throws NamingException {
+ super(true);
+ this.defaultInitCtx = defaultContextFactory.getInitialContext(null);
+ this.gotDefault = true;
+ init(null);
+ }
+
+ public URLPreferringContext(Hashtable<?, ?> environment, InitialContextFactory defaultContextFactory) throws NamingException {
+ super(true);
+ this.defaultInitCtx = defaultContextFactory.getInitialContext(environment);
+ this.gotDefault = true;
+ init(environment);
+ }
+
+ @Override
+ protected Context getURLOrDefaultInitCtx(Name name) throws NamingException {
+ if (name.size() > 0) {
+ String first = name.get(0);
+ String scheme = getURLScheme(first);
+ if (scheme != null) {
+ Context ctx = NamingManager.getURLContext(scheme, myProps);
+ if (ctx != null) {
+ return ctx;
+ }
+ }
+ }
+ return getDefaultInitCtx();
+ }
+
+ @Override
+ protected Context getURLOrDefaultInitCtx(String name) throws NamingException {
+ String scheme = getURLScheme(name);
+ if (scheme != null) {
+ Context ctx = NamingManager.getURLContext(scheme, myProps);
+ if (ctx != null) {
+ return ctx;
+ }
+ }
+ return getDefaultInitCtx();
+ }
+
+ //copied from InitialContext
+ private static String getURLScheme(String str) {
+ int colon_posn = str.indexOf(':');
+ int slash_posn = str.indexOf('/');
+
+ if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))
+ return str.substring(0, colon_posn);
+ return null;
+ }
+}
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java
new file mode 100644
index 0000000..6c311c7
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/URLPreferringInitialContextFactoryDecorator.java
@@ -0,0 +1,54 @@
+/*
+ * 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.jndi;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+
+/**
+ * A decorator of an {@link InitialContextFactory} that returns an {@link URLPreferringContext}
+ * backed by the wrapped initial context factory.
+ * <p>
+ * This is to support contexts that don't need to be secured, yet we need to make sure to
+ * break the call-chain loop caused by the {@link InitialContext} asking the RHQ's {@link AccessCheckingInitialContextFactoryBuilder} for
+ * default contexts.
+ *
+ * @author Lukas Krejci
+ */
+public class URLPreferringInitialContextFactoryDecorator implements InitialContextFactory {
+
+ private final InitialContextFactory factory;
+
+ public URLPreferringInitialContextFactoryDecorator(InitialContextFactory factory) {
+ this.factory = factory;
+ }
+
+ public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
+ return new URLPreferringContext(environment, getFactory());
+ }
+
+ protected InitialContextFactory getFactory() {
+ return factory;
+ }
+}
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstaller.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstaller.java
new file mode 100644
index 0000000..d938c50
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstaller.java
@@ -0,0 +1,45 @@
+/*
+ * 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.jndi.mbean;
+
+import javax.naming.spi.NamingManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.jndi.AccessCheckingInitialContextFactoryBuilder;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public class AccessCheckingInitialContextFactoryBuilderInstaller implements AccessCheckingInitialContextFactoryBuilderInstallerMBean {
+ private static final Log LOG = LogFactory.getLog(AccessCheckingInitialContextFactoryBuilder.class);
+
+ public void start() throws Exception {
+ LOG.info("Installing RHQ's access permission checking initial context factory builder");
+
+ NamingManager.setInitialContextFactoryBuilder(new AccessCheckingInitialContextFactoryBuilder());
+ }
+
+ public void stop() throws Exception {
+ }
+}
diff --git a/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstallerMBean.java b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstallerMBean.java
new file mode 100644
index 0000000..87d19ab
--- /dev/null
+++ b/modules/enterprise/server/container-lib/src/main/java/org/rhq/jndi/mbean/AccessCheckingInitialContextFactoryBuilderInstallerMBean.java
@@ -0,0 +1,32 @@
+/*
+ * 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.jndi.mbean;
+
+/**
+ *
+ *
+ * @author Lukas Krejci
+ */
+public interface AccessCheckingInitialContextFactoryBuilderInstallerMBean {
+
+ void start() throws Exception;
+
+ void stop() throws Exception;
+}
diff --git a/modules/enterprise/server/container/src/main/resources/jbossas/server/default/conf/jboss-service.xml b/modules/enterprise/server/container/src/main/resources/jbossas/server/default/conf/jboss-service.xml
index 859b552..f231f15 100644
--- a/modules/enterprise/server/container/src/main/resources/jbossas/server/default/conf/jboss-service.xml
+++ b/modules/enterprise/server/container/src/main/resources/jbossas/server/default/conf/jboss-service.xml
@@ -225,6 +225,13 @@
<!-- JNDI -->
<!-- ==================================================================== -->
+ <!-- This installs a custom initial context factory builder into the JVM
+ that will ensure that all the default InitialContexts are going to check
+ for the permission to access the RHQ internals. -->
+ <mbean code="org.rhq.jndi.mbean.AccessCheckingInitialContextFactoryBuilderInstaller"
+ name="org.rhq:service=AccessCheckingInitialContextFactoryBuilderInstaller">
+ </mbean>
+
<!-- A simple mbean wrapper around the jndi Naming object. This
only handles an in memory instance. The NamingService uses this
as the JNDI store and exposes it remotely.
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index db286a1..a876809 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -78,6 +78,13 @@
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-container-lib</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
<dependency>
<groupId>com.googlecode.java-diff-utils</groupId>
<artifactId>diffutils</artifactId>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SessionManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SessionManager.java
index b4a19b7..ecf2f6f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SessionManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SessionManager.java
@@ -25,8 +25,8 @@ import java.util.Map;
import java.util.Random;
import org.rhq.core.domain.auth.Subject;
-import org.rhq.enterprise.server.security.AllowEjbAccessPermission;
import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.jndi.AllowRhqServerInternalsAccessPermission;
/**
* This is the JON Server's own session ID generator. It is outside any container-provided session mechanism. Its sole
@@ -45,7 +45,7 @@ import org.rhq.enterprise.server.util.LookupUtil;
*/
public final class SessionManager {
- private static final AllowEjbAccessPermission ACCESS_PERMISSION = new AllowEjbAccessPermission();
+ private static final AllowRhqServerInternalsAccessPermission ACCESS_PERMISSION = new AllowRhqServerInternalsAccessPermission();
/**
* Our source for random session IDs.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessInterceptor.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessInterceptor.java
deleted file mode 100644
index 350453fb..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessInterceptor.java
+++ /dev/null
@@ -1,46 +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.enterprise.server.security;
-
-import java.security.Permission;
-
-import javax.interceptor.AroundInvoke;
-import javax.interceptor.InvocationContext;
-
-/**
- *
- *
- * @author Lukas Krejci
- */
-public class AllowEjbAccessInterceptor {
-
- private static final Permission PERM = new AllowEjbAccessPermission();
-
- @AroundInvoke
- public Object intercept(InvocationContext invocationContext) throws Exception {
- //check that the caller has permissions to access the EJBs.
- //normal code does, only alert CLI scripts that try to circumvent our
- //manager proxies don't.
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) sm.checkPermission(PERM);
-
- return invocationContext.proceed();
- }
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessPermission.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessPermission.java
deleted file mode 100644
index 67f418d..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/security/AllowEjbAccessPermission.java
+++ /dev/null
@@ -1,36 +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.enterprise.server.security;
-
-import java.security.BasicPermission;
-
-/**
- *
- *
- * @author Lukas Krejci
- */
-public class AllowEjbAccessPermission extends BasicPermission {
-
- private static final long serialVersionUID = 1L;
-
- public AllowEjbAccessPermission() {
- super("rhq.allow.ejb.access");
- }
-}
diff --git a/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml b/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml
index caa7513..8222948 100644
--- a/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml
+++ b/modules/enterprise/server/jar/src/main/resources/META-INF/ejb-jar.xml
@@ -9,12 +9,6 @@
<assembly-descriptor>
- <!-- This interceptor checks that the alert CLI scripts don't try to circumvent our access objects by accessing the local SLSB beans directly. -->
- <interceptor-binding>
- <ejb-name>*</ejb-name>
- <interceptor-class>org.rhq.enterprise.server.security.AllowEjbAccessInterceptor</interceptor-class>
- </interceptor-binding>
-
<!-- all our EJB3 SLSBs can define custom @RequiredPermissions annotations for authorization checks-->
<interceptor-binding>
<ejb-name>*</ejb-name>
diff --git a/modules/enterprise/server/jar/src/test/resources/embedded-jboss-beans.xml b/modules/enterprise/server/jar/src/test/resources/embedded-jboss-beans.xml
index 05edefa..85e2fb3 100644
--- a/modules/enterprise/server/jar/src/test/resources/embedded-jboss-beans.xml
+++ b/modules/enterprise/server/jar/src/test/resources/embedded-jboss-beans.xml
@@ -4,6 +4,14 @@
xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
xmlns="urn:jboss:bean-deployer:2.0">
+ <!-- This installs a custom initial context factory builder into the JVM
+ that will ensure that all the default InitialContexts are going to check
+ for the permission to access the RHQ internals. -->
+ <bean class="org.rhq.jndi.mbean.AccessCheckingInitialContextFactoryBuilderInstaller"
+ name="AccessCheckingInitialContextFactoryBuilderInstaller">
+ </bean>
+
+
<bean name="Naming" class="org.jnp.server.SingletonNamingServer"/>
<bean name="InitialContextProperties" class="java.util.Hashtable">
@@ -20,7 +28,7 @@
</entry>
</map>
</parameter>
- </constructor>
+ </constructor>
</bean>
<bean name="java:comp/Initializer" class="org.jboss.ejb3.embedded.JavaCompInitializer">
commit 35fcafbd977ca41cb2cbff7be81787543c5224e8
Author: John Sanda <jsanda(a)redhat.com>
Date: Mon Dec 12 13:39:37 2011 -0500
[BZ 760263] Adding check to avoid generating empty content zip file
When the server requests drift content from the agent, it is possible
that the requested files may not exist. DriftFilesSender now checks to
make sure that there is actually content before making the request to
zip it up and send it to the server.
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 d8d2b46..4181472 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,22 +1,16 @@
package org.rhq.core.pc.drift;
-import java.io.BufferedInputStream;
-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 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;
+
public class DriftFilesSender implements Runnable {
private Log log = LogFactory.getLog(DriftFilesSender.class);
@@ -54,6 +48,10 @@ public class DriftFilesSender implements Runnable {
@Override
public void run() {
try {
+ if (log.isInfoEnabled()) {
+ log.info("Preparing to send content to server for " + defToString());
+ }
+
File changeSet = changeSetMgr.findChangeSet(resourceId, headers.getDriftDefinitionName());
File contentDir = new File(changeSet.getParentFile(), "content");
contentDir.mkdir();
@@ -63,11 +61,25 @@ public class DriftFilesSender implements Runnable {
if (file == null || !file.exists()) {
log.warn("Unable to find file for " + driftFile);
} else {
+ if (log.isDebugEnabled()) {
+ log.debug("Copying " + file.getPath() + " to " + contentDir.getPath());
+ }
StreamUtil.copy(new BufferedInputStream(new FileInputStream(file)), new BufferedOutputStream(
new FileOutputStream(new File(contentDir, driftFile.getHashId()))), true);
}
}
- driftClient.sendChangeSetContentToServer(resourceId, headers.getDriftDefinitionName(), contentDir);
+
+ File[] content = contentDir.listFiles();
+ if (content == null || content.length == 0) {
+ if (log.isDebugEnabled()) {
+ log.debug("Could not find any of the requested content for " + defToString());
+ }
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("Sending " + content.length + " files to the server for " + defToString());
+ }
+ driftClient.sendChangeSetContentToServer(resourceId, headers.getDriftDefinitionName(), contentDir);
+ }
} catch (IOException e) {
log.error("Failed to send drift files.", e);
}
@@ -87,4 +99,9 @@ public class DriftFilesSender implements Runnable {
reader.close();
}
}
+
+ private String defToString() {
+ return "[resourceId: " + resourceId + ", driftDefinitionId: " + headers.getDriftDefinitionId() +
+ ", driftDefinitionName: " + headers.getDriftDefinitionName() + "]";
+ }
}
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftClientTestStub.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftClientTestStub.java
index 209ba61..0f0c26a 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftClientTestStub.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftClientTestStub.java
@@ -1,9 +1,9 @@
package org.rhq.core.pc.drift;
-import java.io.File;
-
import org.rhq.core.domain.drift.DriftDefinition;
+import java.io.File;
+
class DriftClientTestStub implements DriftClient {
private File basedir;
@@ -14,6 +14,8 @@ class DriftClientTestStub implements DriftClient {
private int reportMissingBaseDirInvocationCount;
+ private int sendChangeSetContentInvocationCount;
+
@Override
public void sendChangeSetToServer(DriftDetectionSummary detectionSummary) {
++sendChangeSetInvocationCount;
@@ -28,6 +30,11 @@ class DriftClientTestStub implements DriftClient {
@Override
public void sendChangeSetContentToServer(int resourceId, String driftDefinitionName, File contentDir) {
+ ++sendChangeSetContentInvocationCount;
+ }
+
+ public int getSendChangeSetContentInvocationCount() {
+ return sendChangeSetContentInvocationCount;
}
@Override
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
index 5fd6528..77db6b2 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftFilesSenderTest.java
@@ -19,18 +19,17 @@
package org.rhq.core.pc.drift;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
import org.rhq.common.drift.ChangeSetWriter;
import org.rhq.common.drift.Headers;
import org.rhq.core.domain.drift.DriftChangeSetCategory;
import org.rhq.core.domain.drift.DriftFile;
import org.rhq.core.domain.drift.JPADriftFile;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
import static org.rhq.common.drift.FileEntry.addedFileEntry;
import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
@@ -39,7 +38,7 @@ import static org.testng.Assert.assertTrue;
public class DriftFilesSenderTest extends DriftTest {
- DriftClient driftClient;
+ DriftClientTestStub driftClient;
DriftFilesSender sender;
@@ -161,6 +160,31 @@ public class DriftFilesSenderTest extends DriftTest {
assertFileCopiedToContentDir(contentDir, server2ConfHash);
}
+ @Test
+ public void doNotSendEmptyZipFileToServer() throws Exception {
+ String driftDefName = "empty_content_test";
+
+ File confDir = mkdir(resourceDir, "conf");
+ File serverConf = createRandomFile(confDir, "server.conf");
+
+ String serverConfHash = sha256(serverConf);
+
+ Headers headers = createHeaders(driftDefName, COVERAGE);
+
+ ChangeSetWriter writer = changeSetMgr.getChangeSetWriter(resourceId(), headers);
+ writer.write(addedFileEntry("conf/server.conf", serverConfHash));
+ writer.close();
+
+ serverConf.delete();
+
+ sender.setDriftFiles(driftFiles(serverConfHash));
+ sender.setHeaders(headers);
+ sender.run();
+
+ assertEquals(driftClient.getSendChangeSetContentInvocationCount(), 0,
+ "Do not call DriftClient to send content to server when there is no content to send.");
+ }
+
/**
* This method only verifies that a file having a particular hash or SHA-256 has been
* copied to the specified content directory.
commit 48a945ccd90e18205f216f42729c3043dc12189d
Author: Fusayuki Minamoto <fminamot(a)redhat.com>
Date: Mon Dec 12 14:29:22 2011 +0100
Updated Japanese translations.
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 71e3530..67d4a7f 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
@@ -24,23 +24,22 @@ common_button_create_child = 子を作成
common_button_delete = 削除
common_button_delete_all = すべてを削除
common_button_disable = 無効
-##common_button_dump_sysInfo_to_log = Dump system info to log file
common_button_edit = 編集
common_button_enable = 有効
-##common_button_execute = Execute
+common_button_execute = 実行
common_button_finish = 完了
-##common_button_fixedWidth = Fixed Width
+common_button_fixedWidth = 固定幅
common_button_import = インポート
common_button_new = 新規
common_button_next = 次へ
common_button_ok = OK
common_button_previous = 前へ
-##common_button_purge = Purge
+common_button_purge = パージ
common_button_purgeAll = すべてをパージ
common_button_refresh = リフレッシュ
common_button_reset = リセット
common_button_save = 保存
-##common_button_scaleToFit = Scale To Fit
+common_button_scaleToFit = 適合させるスケール
common_button_schedule = スケジュール
common_button_search = 検索
common_button_set = 設定
@@ -62,8 +61,8 @@ common_label_ago = 前
common_label_all = すべての
common_label_all_resources = すべてのリソース
common_label_day = 日
-##common_label_error = Error
-##common_label_filters = Filters
+common_label_error = エラー
+common_label_filters = フィルター
common_label_hour = 時間
common_label_item = 項目
common_label_items = 項目
@@ -79,20 +78,20 @@ common_label_users = ユーザー
common_label_week = 週
common_label_yesterday = 昨日
common_msg_areYouSure = よろしいですか?
-##common_msg_asyncTimeout = {0}. This occurred because the server is taking a long time to complete this request. Please be aware that the server may still be processing your request and it may complete shortly. You can check the server logs to see if any abnormal errors occurred.
+common_msg_asyncTimeout = {0}. これが発生したのはサーバーがこのリクエストを完了するのに長時間経過したからです。サーバーがそのリクエストをまだ処理中で短時間で完了可能かどうか注意してください。サーバーログを調べることで異常なエラーが発生したかどうかがわかります。
common_msg_changeAutoDetected = 変更が自動検出されました
-common_msg_deleteConfirm = を削除してもよろしいですか # selected {0}?
+common_msg_deleteConfirm = 選択された {0} を削除してもよろしいですか
common_msg_emphasizedNotePrefix = 注意:
common_msg_loading = ロード中...
common_msg_noItemsToShow = 表示する項目はありません
-##common_msg_notYetImplemented = Not Yet Implemented
+common_msg_notYetImplemented = 実装されていません
common_msg_see_more = 詳細...
common_msg_step_x_of_y = ステップ {1} 中 {0} 番め
-##common_severity_debug = Debug
+common_severity_debug = デバッグ
common_severity_error = エラー
-##common_severity_fatal = Fatal
+common_severity_fatal = 致命的
common_severity_info = 情報
-##common_severity_warn = Warn
+common_severity_warn = 警告
common_status_canceled = キャンセル
common_status_deferred = 延期
common_status_failed = 失敗
@@ -103,6 +102,7 @@ common_status_success = 成功
common_status_timedOut = タイムアウト
common_status_unknown = 未知
common_title_add_column = カラム追加
+common_title_add_graph_to_view = モニタービューへのグラフの追加
common_title_add_portlet = ポートレット追加
common_title_address = アドレス
common_title_alerts = アラート
@@ -115,7 +115,7 @@ common_title_background = バックグラウンド
common_title_bundle = バンドル
common_title_bundles = バンドル
common_title_category = カテゴリ
-common_title_change_refresh_time = インターバルのリフレッシュ
+common_title_change_refresh_time = リフレッシュ間隔
common_title_columns = カラム
common_title_compare_metrics = メトリックスの比較
common_title_compatibleGroups = 互換グループ
@@ -124,19 +124,20 @@ common_title_component_errors = コンポーネントエラー
common_title_config_update_status = 更新状態
common_title_configuration = 構成
common_title_count = 数
+common_title_createTime = 作成時刻
common_title_custom = カスタム
common_title_dashboard_name = ダッシュボード名
common_title_dateCreated = 作成日
common_title_dateRange = 日付の範囲
common_title_default = デフォルト
-##common_title_definition = Definition
+common_title_definition = 定義
common_title_definitions = 定義
common_title_description = 説明
common_title_details = 詳細
common_title_display = 表示
common_title_display_name = 表示名
common_title_duration = 期間
-##common_title_edit = Edit?
+common_title_edit = 編集?
common_title_edit_mode = 編集モード
common_title_enabled = 有効?
common_title_end = 終了
@@ -149,9 +150,10 @@ common_title_help = ヘルプ
common_title_host = ホスト
common_title_id = ID
common_title_id_parent = 親のID
+common_title_interval = 間隔
common_title_inventory = インベントリ
common_title_inventorySummary = インベントリサマリ
-##common_title_kind = Kind
+common_title_kind = 種類
common_title_lastUpdated = 最終更新
common_title_lastUpdatedBy = 最終更新(による)
common_title_ldapGroups = LDAPグループ
@@ -170,7 +172,7 @@ common_title_operation = オペレーション
common_title_operation_status = オペレーションの状態
common_title_operations = オペレーション
common_title_operations_range = オペレーションの範囲
-common_title_over = Over
+##common_title_over = Over
common_title_password = パスワード
common_title_path = パス
common_title_permissions = パーミッション
@@ -182,7 +184,7 @@ common_title_providers = プロバイダ
common_title_recent_alerts = 最近のアラート
common_title_recent_bundle_deployments = 最近のバンドルのデプロイ
common_title_recent_configuration_updates = 最近の構成の更新
-##common_title_recent_drifts = Recent Drift
+common_title_recent_drifts = 最近のドリフト
common_title_recent_event_counts = 最近のイベント数
common_title_recent_measurements = 最近の測定
common_title_recent_oob_metrics = 最近の境界外のメトリックス
@@ -390,12 +392,12 @@ view_aboutBox_homepage = ホームページ
view_aboutBox_jbossByRedHat = JBoss by Red Hat
view_aboutBox_title = {0}について
view_aboutBox_version = バージョン:
-##view_adminConfig_agentPlugins = Agent Plugins
-##view_adminConfig_alertDefTemplates = Alert Definition Templates
+view_adminConfig_agentPlugins = エージェントプラグイン
+view_adminConfig_alertDefTemplates = エージェント定義テンプレート
view_adminConfig_downloads = ダウンロード
-##view_adminConfig_driftDefTemplates = Drift Definition Templates
-##view_adminConfig_metricTemplates = Metric Collection Templates
-##view_adminConfig_serverPlugins = Server Plugins
+view_adminConfig_driftDefTemplates = ドリフト定義テンプレート
+view_adminConfig_metricTemplates = メトリック収集テンプレート
+view_adminConfig_serverPlugins = サーバープラグイン
view_adminConfig_systemSettings = システム設定
view_adminContent_contentSources = コンテントソース
view_adminRoles_assignedGroups = 割り当てられたリソースグループ
@@ -423,7 +425,7 @@ view_adminRoles_permissions_permDesc_manageBundles = (誰でも閲覧可能な)
view_adminRoles_permissions_permDesc_manageInventory = すべてのリソースについて、以下に示すように、すべてのリソース権限を持ちます。つまり、グループの作成、更新、削除、そして自動検出された、または手動で検出されたリソースのインポートができます
view_adminRoles_permissions_permDesc_manageRepositories = (自分自身のリポジトリを作成可能な)ユーザーのリポジトリの作成、更新、削除が可能です。
view_adminRoles_permissions_permDesc_manageSecurity = (誰でも閲覧可能な)ユーザーとロールの作成、更新、削除
-##view_adminRoles_permissions_permDesc_manageSettings = RHQサーバー構成の修正と任意のサーバー関連の機能の実行ができます
+## view_adminRoles_permissions_permDesc_manageSettings = RHQサーバー構成の修正と任意のサーバー関連の機能の実行ができます
view_adminRoles_permissions_permReadDesc_configure = リソース構成とリソース構成リビジョン履歴の閲覧
view_adminRoles_permissions_permReadDesc_control = 利用可能オペレーションとオペレーション実行履歴の(暗黙的な)閲覧
view_adminRoles_permissions_permReadDesc_createChildResources = (暗黙的な)子リソースの作成履歴の閲覧
@@ -431,7 +433,7 @@ view_adminRoles_permissions_permReadDesc_deleteChildResources = (暗黙的な)
view_adminRoles_permissions_permReadDesc_inventory = リソースプロパティ(名前、説明、バージョンなど)、コネクション設定、コネクション設定履歴の(暗黙的な)閲覧
view_adminRoles_permissions_permReadDesc_manageAlerts = アラート定義とアラート履歴の(暗黙的な)閲覧
view_adminRoles_permissions_permReadDesc_manageContent = (暗黙的な)インストールされて利用可能なパッケージ。パッケージインストール履歴の閲覧。
-##view_adminRoles_permissions_permReadDesc_manageDrift = (IMPLIED) view drift definitions and drift history
+view_adminRoles_permissions_permReadDesc_manageDrift = (暗黙的な) ドリフト定義とドリフト履歴の閲覧
view_adminRoles_permissions_permReadDesc_manageEvents = (暗黙的な)イベントの閲覧
view_adminRoles_permissions_permReadDesc_manageMeasurements = メトリックデータと収集スケジュールの(暗黙的な)閲覧
view_adminRoles_permissions_permWriteDesc_configure = リソース構成の更新。リソース構成リビジョン履歴の削除。
@@ -441,7 +443,7 @@ view_adminRoles_permissions_permWriteDesc_deleteChildResources = リソースの
view_adminRoles_permissions_permWriteDesc_inventory = リソースの名前、バージョン、説明、コネクション設定の更新。コネクション設定の履歴の削除。
view_adminRoles_permissions_permWriteDesc_manageAlerts = アラート定義の作成、更新、削除。アラート履歴の確認と削除
view_adminRoles_permissions_permWriteDesc_manageContent = コンテントソースへの登録。パッケージのインストールとアンインストール。
-##view_adminRoles_permissions_permWriteDesc_manageDrift = create, update, and delete drift definitions; and manage drift instances
+view_adminRoles_permissions_permWriteDesc_manageDrift = ドリフト定義の作成、更新、削除、そして、ドリフトインスタンスの管理
view_adminRoles_permissions_permWriteDesc_manageEvents = イベントの削除
view_adminRoles_permissions_permWriteDesc_manageMeasurements = メトリック収集スケジュールの更新
view_adminRoles_permissions_perm_configure = 構成
@@ -452,7 +454,7 @@ view_adminRoles_permissions_perm_inventory = インベントリ
view_adminRoles_permissions_perm_manageAlerts = アラートの管理
view_adminRoles_permissions_perm_manageBundles = バンドルの管理
view_adminRoles_permissions_perm_manageContent = コンテント管理
-##view_adminRoles_permissions_perm_manageDrift = Manage Drift
+view_adminRoles_permissions_perm_manageDrift = ドリフト管理
view_adminRoles_permissions_perm_manageEvents = イベント管理
view_adminRoles_permissions_perm_manageInventory = インベントリの管理
view_adminRoles_permissions_perm_manageMeasurements = 測定の管理
@@ -469,20 +471,20 @@ view_adminRoles_roleDeleteFailed = ロール [{0}] の削除に失敗しまし
view_adminRoles_roleDeleted = ロール [{0}] が削除されました
view_adminRoles_roleUpdateFailed = ロール [{0}] の更新に失敗しました.
view_adminRoles_roleUpdated = ロール [{0}] が更新されました
-##view_adminTemplates_definedBy = Defined By
-##view_adminTemplates_disabledTemplates = Disabled Templates
+view_adminTemplates_definedBy = 定義
+view_adminTemplates_disabledTemplates = 無効化されたテンプレート
view_adminTemplates_editAlertTemplate = アラートテンプレートの編集
-##view_adminTemplates_editTemplates = Edit Templates
-##view_adminTemplates_enabledTemplates = Enabled Templates
+view_adminTemplates_editTemplates = テンプレートの編集
+view_adminTemplates_enabledTemplates = 有効化されたテンプレート
view_adminTemplates_platformServices = プラットフォームサービス
view_adminTemplates_platforms = プラットフォーム
-##view_adminTemplates_pluginTemplates = Plugin Templates
+view_adminTemplates_pluginTemplates = プラグインテンプレート
view_adminTemplates_prompt_disabledAlertTemplates = このリソースタイプに関して作成されたけれど無効にされたアラートテンプレートの数
view_adminTemplates_prompt_disabledMetricTemplates = このリソースタイプに関してデフォルトで無効にされたメトリックスケジュールの数
view_adminTemplates_prompt_enabledAlertTemplates = このリソースタイプに関して有効にされたアラートテンプレートの数
view_adminTemplates_prompt_enabledMetricTemplates = このリソースタイプに関してデフォルトで有効にされたメトリックスケジュールの数
view_adminTemplates_servers = サービス
-##view_adminTemplates_userTemplates = User Templates
+view_adminTemplates_userTemplates = ユーザーテンプレート
view_adminTopology_affinityGroups = アフィニティグループ
view_adminTopology_agents = エージェント
view_adminTopology_partitionEvents = イベントの分類
@@ -494,106 +496,102 @@ view_admin_configuration = 構成
view_admin_content = コンテント
view_admin_downloads_agentDownload = エージェントのダウンロード
view_admin_downloads_agent_buildNumber = エージェントビルド
-##view_admin_downloads_agent_help = <p> これはRHQ Agentの更新バイナリJARファイルです。このJARファイルの目的はユーザーがエージェントがまだ存在しないマシン上に新しいエージェントをインストールできるようにすることと、すでにインストール済みのエージェントを更新できるようにするためです。詳細は、このエージェントダウンロードJARで次のように--helpコマンドラインオプションをつけて実行してください。<br/> <b>java -jar <agent-download.jar> --help</b> </p> <h3>エージェントのインストール</h3> <p> <b>java -jar <agent-download.jar> --install[=<新しいエージェントディレクトリ>]</b><br/> このコマンドは新しいエージェントをインストールします。もし新しいディレクトリを指定しなければ、デフォルトは"."となります。</p> <h3>エージェントの更新</h3> <p> <b>java -jar <agent-download.jar> --update[=<古いエージェントディレクトリ>]</b><br/> これはすでにインストールされた既存のエージェントを更新します。もし古い、既存のエージェントがインストールされたディレクトリを指定しなかったなら、"rhq-agent"が仮定されます。</p>
+## view_admin_downloads_agent_help = <p> これはRHQ Agentの更新バイナリJARファイルです。このJARファイルの目的はユーザーがエージェントがまだ存在しないマシン上に新しいエージェントをインストールできるようにすることと、すでにインストール済みのエージェントを更新できるようにするためです。詳細は、このエージェントダウンロードJARで次のように--helpコマンドラインオプションをつけて実行してください。<br/> <b>java -jar <agent-download.jar> --help</b> </p> <h3>エージェントのインストール</h3> <p> <b>java -jar <agent-download.jar> --install[=<新しいエージェントディレクトリ>]</b><br/> このコマンドは新しいエージェントをインストールします。もし新しいディレクトリを指定しなければ、デフォルトは"."となります。</p> <h3>エージェントの更新</h3> <p> <b>java -jar <agent-download.jar> --update[=<古いエージェントディレクトリ>]</b><br/> これはすでにインストールされた既存のエージェントを更新します。もし古い、既存のエージェントがインストールされたディレクトリを指定しなかったなら、"rhq-agent"が仮定されます。</p>
view_admin_downloads_agent_link_label = リンク
view_admin_downloads_agent_link_value = エージェント {0} ({1}) のダウンロード
view_admin_downloads_agent_loadError = エージェントバージョン情報が取得できません
view_admin_downloads_agent_md5 = エージェント MD5
view_admin_downloads_agent_version = エージェントバージョン
view_admin_downloads_bundleDownload = バンドルデプロイヤのダウンロード
-##view_admin_downloads_bundle_help = <p> これはバンドルデプロイヤツールで、開発者とRHQバンドルによって使われます。このスタンドアロンツールを使うとバンドルやコンソールからのレシピをテストできるようにします。</p>
+## view_admin_downloads_bundle_help = <p> これはバンドルデプロイヤツールで、開発者とRHQバンドルによって使われます。このスタンドアロンツールを使うとバンドルやコンソールからのレシピをテストできるようにします。</p>
view_admin_downloads_bundle_link_label = リンク
view_admin_downloads_bundle_link_value = バンドルデプロイヤー {0} をダウンロード
view_admin_downloads_bundle_loadError = バンドルデプロイヤー情報が取得できません
-##view_admin_downloads_cliAlertScriptsDownload = CLI Alert Scripts Download
-##view_admin_downloads_cliAlertScripts_help = CLI alert scripts are pre-canned scripts that can be used for creating scripted alert notifications. The scripts will usually require some tweaking before they can be used as a notification on a particular alert definition.
-##view_admin_downloads_cliAlertScripts_loadError = Cannot get info on available CLI alert scripts for download
-##view_admin_downloads_cliAlertScripts_none = No CLI alert scripts are available for download
view_admin_downloads_cliDownload = コマンドラインクライアントのダウンロード
view_admin_downloads_cli_buildNumber = CLIビルド
-##view_admin_downloads_cli_help = <p> これはコマンドラインツールで、CLIとして知られているものです。コンソールから実行するスタンドアロンツールで、RHQサーバーに対してコマンドラインインタフェースを提供します。自動化されたタスクを実行するためにCLIやrunスクリプトを介してコマンドを呼び出すことが可能です。CLIのインストール方法と使い方についての詳細情報はドキュメントをご覧ください。</p>
+## view_admin_downloads_cli_help = <p> これはコマンドラインツールで、CLIとして知られているものです。コンソールから実行するスタンドアロンツールで、RHQサーバーに対してコマンドラインインタフェースを提供します。自動化されたタスクを実行するためにCLIやrunスクリプトを介してコマンドを呼び出すことが可能です。CLIのインストール方法と使い方についての詳細情報はドキュメントをご覧ください。</p>
view_admin_downloads_cli_link_label = リンク
view_admin_downloads_cli_link_value = CLI {0} ({1}) をダウンロード
view_admin_downloads_cli_loadError = CLIバージョン情報が取得できません
view_admin_downloads_cli_md5 = CLI MD5
view_admin_downloads_cli_version = CLIバージョン
view_admin_downloads_connectorsDownload = コネクタのダウンロード
-##view_admin_downloads_connectors_help = コネクターは製品がRHQによって管理可能であるために必要となるソフトウェアです。RHQエージェントが通信できるように、管理製品にコネクターをインストールします。詳細はドキュメントをご覧ください。
+## view_admin_downloads_connectors_help = コネクターは製品がRHQによって管理可能であるために必要となるソフトウェアです。RHQエージェントが通信できるように、管理製品にコネクターをインストールします。詳細はドキュメントをご覧ください。
view_admin_downloads_connectors_loadError = コネクター情報を取得できません
view_admin_downloads_connectors_none = ダウンロードのためのコネクターが見つかりません
-##view_admin_landing = このセクションにおいて、RHQグローバル設定が管理されます。これはセキュリティ構成、プラグイン設定、RHQサーバーとエージェントの管理を含みます。
+## view_admin_landing = このセクションにおいて、RHQグローバル設定が管理されます。これはセキュリティ構成、プラグイン設定、RHQサーバーとエージェントの管理を含みます。
view_admin_measTemplates_updateExisting_title = 既存スケジュールの更新
view_admin_measTemplates_updateExisting_tooltip = このボックスをチェックすると、このタイプのすべてのリソースを対象に選択したメトリックスの収集スケジュールを更新します。もしこれがチェックされていなければ、テンプレートスケジュールが将来的にインベントリに追加されるこのタイプの新規リソースに適用されるだけです。
-##view_admin_plugins_agent = Agent
-##view_admin_plugins_agentDeleteConfirm = <b>Warning!</b><br/>\nThe following agent plugins are about to be deleted:<br/>\n{0}<br/>\nAre you sure you want to delete these?
-##view_admin_plugins_agentDisableConfirm = <b>Warning!</b><br/>\nThe following agent plugins are about to be disabled:<br/>\n{0}<br/>\nAre you sure you want to disable these?
-##view_admin_plugins_deletedAgentPlugins = Deleted agent plugins: {0}
-##view_admin_plugins_deletedAgentPluginsFailure = Failed to delete agent plugins.
-##view_admin_plugins_deployed = Deployed?
-##view_admin_plugins_disabledAgentPlugins = Disabled agent plugins: {0}
-##view_admin_plugins_disabledAgentPluginsFailure = Failed to disable agent plugins.
-##view_admin_plugins_disabledServerPlugins = Disabled server plugins: {0}
-##view_admin_plugins_disabledServerPluginsFailure = Failed to disable server plugins.
-##view_admin_plugins_enabledAgentPlugins = Enabled agent plugins: {0}
-##view_admin_plugins_enabledAgentPluginsFailure = Failed to enable agent plugins.
-##view_admin_plugins_enabledServerPlugins = Enabled server plugins: {0}
-##view_admin_plugins_enabledServerPluginsFailure = Failed to enable server plugins.
-##view_admin_plugins_hideDeleted = Hide Deleted
-##view_admin_plugins_hideUndeployed = Hide Undeployed
-##view_admin_plugins_loadFailure = Failed to load plugin data
-##view_admin_plugins_purgedAgentPlugins = Preparing to purge agent plugins {0}. This may take a few minutes since all type definitions from the plugins must first be purged from the system. The plugins will still be visible on this page until they have been purged. Please note that you must not re-install the plugin while the purge is running, otherwise failures will occur. Therefore, please wait before attempting to re-install the plugin into the system until this purge is complete.
-##view_admin_plugins_purgedAgentPluginsFailure = Failed to purge agent plugins.
-##view_admin_plugins_purgedServerPlugins = Purged server plugins: {0}.
-##view_admin_plugins_purgedServerPluginsFailure = Failed to purge server plugins.
-##view_admin_plugins_restartMasterPC = Restart Master Plugin Container
-##view_admin_plugins_restartMasterPCComplete = Master plugin container has been restarted.
-##view_admin_plugins_restartMasterPCFailure = Failed to restart the master plugin container
-##view_admin_plugins_restartMasterPCStarted = Restarting the master plugin container...
-##view_admin_plugins_scan = Scan For Updates
-##view_admin_plugins_scanComplete = Finished scanning for updated plugins
-##view_admin_plugins_scanFailure = Failed to scan for updated plugins.
+view_admin_plugins_agent = エージェント
+view_admin_plugins_agentDeleteConfirm = <b>警告!</b><br/>\n次のエージェントプラグインは削除されようとしています:<br/>\n{0}<br/>\n本当にこれらを削除してもよろしいですか?
+view_admin_plugins_agentDisableConfirm = <b>警告!</b><br/>\n次のエージェントプラグインは無効にされようとしています:<br/>\n{0}<br/>\n本当にこれらを無効にしてもよろしいですか?
+view_admin_plugins_deletedAgentPlugins = 削除されたエージェントプラグイン: {0}
+view_admin_plugins_deletedAgentPluginsFailure = エージェントプラグインの削除に失敗しました
+view_admin_plugins_deployed = デプロイしましたか?
+view_admin_plugins_disabledAgentPlugins = 無効化されたエージェントプラグイン: {0}
+view_admin_plugins_disabledAgentPluginsFailure = エージェントプラグインを無効化するのに失敗しました
+view_admin_plugins_disabledServerPlugins = 無効化されたサーバープラグイン: {0}
+view_admin_plugins_disabledServerPluginsFailure = サーバープラグインを無効化するのに失敗しました
+view_admin_plugins_enabledAgentPlugins = 有効化されたエージェントプラグイン: {0}
+view_admin_plugins_enabledAgentPluginsFailure = エージェントプラグインを有効化するのに失敗しました
+view_admin_plugins_enabledServerPlugins = 有効化されたサーバープラグイン: {0}
+view_admin_plugins_enabledServerPluginsFailure = サーバープラグインの有効化に失敗しました
+view_admin_plugins_hideDeleted = 削除済みを隠す
+view_admin_plugins_hideUndeployed = アンデプロイを隠す
+view_admin_plugins_loadFailure = プラグインデータをロードするのに失敗しました
+view_admin_plugins_purgedAgentPlugins = エージェントプラグイン {0} をパージするための準備をしています。これは数分かかるかもしれません。なぜなら、そのプラグインからのすべてのタイプ定義は最初にシステムからパージされなければならないからです。それらのプラグインはパージされるまでの間このページで見え続けます。パージが実行中はそのプラグインを再インストールしてはいけないことに留意してください。さもなければ、失敗することでしょう。したがって、このパージが完了するまでシステムへプラグインの再インストールをお待ちください。
+view_admin_plugins_purgedAgentPluginsFailure = エージェントプラグインのパージに失敗しました
+view_admin_plugins_purgedServerPlugins = パージされたサーバープラグイン: {0}.
+view_admin_plugins_purgedServerPluginsFailure = サーバープラグインのパージに失敗しました
+view_admin_plugins_restartMasterPC = マスタープラグインコンテナの再起動
+view_admin_plugins_restartMasterPCComplete = マスタープラグインコンテナが再起動されました
+view_admin_plugins_restartMasterPCFailure = マスタープラグインコンテナの再起動に失敗しました
+view_admin_plugins_restartMasterPCStarted = マスタープラグインコンテナの再起動中...
+view_admin_plugins_scan = 更新のためのスキャン
+view_admin_plugins_scanComplete = 更新されたプラグインのためのスキャンを完了しました
+view_admin_plugins_scanFailure = 更新されたプラグインのためのスキャンが失敗しました
view_admin_plugins_server = サーバー
-##view_admin_plugins_serverConfig = Plugin Configuration
-##view_admin_plugins_serverConfig_badSettings = Please enter valid settings
-##view_admin_plugins_serverConfig_saveFailed = Failed to save the settings
-##view_admin_plugins_serverConfig_settingsSaved = The settings have been saved.
-##view_admin_plugins_serverControls = Controls
-##view_admin_plugins_serverControls_badParams = Please enter valid parameters
-##view_admin_plugins_serverControls_clickForError = Click for the error message
-##view_admin_plugins_serverControls_invokeFailure = Failed to invoke the control
-##view_admin_plugins_serverControls_name = Control
-##view_admin_plugins_serverControls_parameters = Parameters
-##view_admin_plugins_serverControls_results = Results
-##view_admin_plugins_serverDisableConfirm = <b>Warning!</b><br/>\nThe following server plugins are about to be disabled:<br/>\n{0}<br/>\nAre you sure you want to disable these?
-##view_admin_plugins_serverScheduleJobs = Scheduled Jobs
-##view_admin_plugins_serverUndeployConfirm = <b>Warning!</b><br/>\nThe following server plugins are about to be undeployed:<br/>\n{0}<br/>\nAre you sure you want to undeploy these?
-##view_admin_plugins_showDeleted = Show Deleted
-##view_admin_plugins_showUndeployed = Show Undeployed
-##view_admin_plugins_undeploy = Undeploy
-##view_admin_plugins_undeployedServerPlugins = Undeployed server plugins: {0}
-##view_admin_plugins_undeployedServerPluginsFailure = Failed to undeploy server plugins.
-##view_admin_plugins_upload = Upload Plugin
+view_admin_plugins_serverConfig = プラグイン構成
+view_admin_plugins_serverConfig_badSettings = 正しい設定を入力してください
+view_admin_plugins_serverConfig_saveFailed = 設定の保存に失敗しました
+view_admin_plugins_serverConfig_settingsSaved = 設定が保存されました
+view_admin_plugins_serverControls = コントロール
+view_admin_plugins_serverControls_badParams = 正しいパラメーターを入力してください
+view_admin_plugins_serverControls_clickForError = エラーメッセージをクリックしてください
+view_admin_plugins_serverControls_invokeFailure = コントロールの呼び出しに失敗しました
+view_admin_plugins_serverControls_name = コントロール
+view_admin_plugins_serverControls_parameters = パラメーター
+view_admin_plugins_serverControls_results = 結果
+view_admin_plugins_serverDisableConfirm = <b>警告!</b><br/>\n次のサーバープラグインは無効にされようとしています:<br/>\n{0}<br/>\n本当にこれらを無効にしてもよろしいですか?
+view_admin_plugins_serverScheduleJobs = スケジュールされたジョブ
+view_admin_plugins_serverUndeployConfirm = <b>警告!</b><br/>\n次のサーバープラグインはアンデプロイされようとしています:<br/>\n{0}<br/>\n本当にこれらをアンデプロイにしてもよろしいですか?
+view_admin_plugins_showDeleted = 削除済みを表示
+view_admin_plugins_showUndeployed = アンデプロイを表示
+view_admin_plugins_undeploy = アンデプロイ
+view_admin_plugins_undeployedServerPlugins = アンデプロイ済みのサーバープラグイン: {0}
+view_admin_plugins_undeployedServerPluginsFailure = サーバープラグインのアンデプロイに失敗しました
+view_admin_plugins_upload = プラグインのアップロード
view_admin_security = セキュリティ
-##view_admin_systemSettings_ActiveDriftServerPlugin_desc = The drift server plugin that manages the persistence of drift-related entities and content.
-##view_admin_systemSettings_ActiveDriftServerPlugin_name = Active Drift Server Plugin
+view_admin_systemSettings_ActiveDriftServerPlugin_desc = ドリフト関連のエンティティとコンテントの永続性を管理するドリフトサーバープラグイン
+view_admin_systemSettings_ActiveDriftServerPlugin_name = アクティブドリフトサーバープラグイン
view_admin_systemSettings_AgentMaxQuietTimeAllowed_desc = もしエージェントから何も受信しないでこの時間が経過したならば、そのエージェントはダウンしたものと見なされます。この値は分単位で指定されます。
view_admin_systemSettings_AgentMaxQuietTimeAllowed_name = 許容される最大無通信時間
view_admin_systemSettings_AlertPurge_desc = データベースから除去される前のアラートヒストリの保持時間。これは日単位で指定されます。
-view_admin_systemSettings_AlertPurge_name = 次より古いアラートを削除
+view_admin_systemSettings_AlertPurge_name = 古いアラートを削除
view_admin_systemSettings_AvailabilityPurge_desc = データベースから除去される前の可用性データの保持時間。これは日単位で指定されます。
-view_admin_systemSettings_AvailabilityPurge_name = 次より古い可用性データの削除
+view_admin_systemSettings_AvailabilityPurge_name = 古い可用性データの削除
view_admin_systemSettings_BaseURL_desc = サーバーGUIへのURL。主にアラートE-メール通知の使われます。
view_admin_systemSettings_BaseURL_name = GUIコンソールURL
view_admin_systemSettings_BaselineDataSet_desc = ベースラインを決定するために使われる過去の測定データの量。これは日単位で指定されます。
view_admin_systemSettings_BaselineDataSet_name = ベースラインデータセット
-view_admin_systemSettings_BaselineFrequency_desc = ベースラインの自動景作の頻度が計算されます。もし0なら、ベースラインの自動景作は無効にされます。これは日単位で指定されます。
+view_admin_systemSettings_BaselineFrequency_desc = ベースラインの自動計算の頻度が計算されます。もし0なら、ベースラインの自動計算は無効にされます。これは日単位で指定されます。
view_admin_systemSettings_BaselineFrequency_name = ベースライン計算の頻度
view_admin_systemSettings_DataMaintenance_desc = データベースの保守が実行される頻度(例えば、Postgresを使っているのであればであればバキュームなど)。これは時間単位で指定されます。
view_admin_systemSettings_DataMaintenance_name = データベース保守期間
-view_admin_systemSettings_DataReindex_desc = もし有効であれば、データベーステーブルは定期的にインデックスが再生成されます。
-view_admin_systemSettings_DataReindex_name = データテーブルの夜間でのインデックス再生成
-##view_admin_systemSettings_DriftFilePurge_desc = How old unused and orphaned drift files must be before being purged from backend storage. This is specified in days.
-##view_admin_systemSettings_DriftFilePurge_name = Delete Unused Drift Files Older Than
+view_admin_systemSettings_DataReindex_desc = もし有効であれば、データベーステーブルは定期的にインデックスが再作成されます。
+view_admin_systemSettings_DataReindex_name = データテーブルの夜間でのインデックス再作成
+view_admin_systemSettings_DriftFilePurge_desc = バックエンドからパージされる対象となる未使用かつ親がいないドリフトファイルの経過時間。これは日数で指定されます。
+view_admin_systemSettings_DriftFilePurge_name = 未使用ドリフトファイルの削除
view_admin_systemSettings_EnableAgentAutoUpdate_desc = サーバーがエージェントが自動更新することを許すかどうかを決定します。もしこれが無効にされているのであれば、サーバーからエージェントのディストリビューションをダウンロードすることはできません。
view_admin_systemSettings_EnableAgentAutoUpdate_name = エージェントの自動更新を有効にする
view_admin_systemSettings_EnableDebugMode_desc = 有効であれば、サーバーはデバッグモードに入ります
@@ -601,8 +599,8 @@ view_admin_systemSettings_EnableDebugMode_name = デバッグモードを有効
view_admin_systemSettings_EnableExperimentalFeatures_desc = 有効であれば、現在の製品に含まれる任意の実験的機能が利用可能になります
view_admin_systemSettings_EnableExperimentalFeatures_name = 実験的機能を有効にする
view_admin_systemSettings_EventPurge_desc = データベースから除去される前のイベントデータの保持時間。これは日単位で指定されます。
-view_admin_systemSettings_EventPurge_name = 次より古いイベント削除
-view_admin_systemSettings_JAASProvider_desc = ユーザーIDを欠点するのにLDAPが使われるべきですか?
+view_admin_systemSettings_EventPurge_name = 古いイベント削除
+view_admin_systemSettings_JAASProvider_desc = ユーザーIDを決定するのにLDAPが使われるべきですか?
view_admin_systemSettings_JAASProvider_name = LDAPの有効化
view_admin_systemSettings_LDAPBaseDN_desc = ユーザ認証の間にユーザー名とパスワードを検索するディレクトリツリーのベース。例: ou=People,dc=redhat,dc=com
view_admin_systemSettings_LDAPBaseDN_name = サーチベース
@@ -623,17 +621,15 @@ view_admin_systemSettings_LDAPProtocol_name = SSL
view_admin_systemSettings_LDAPUrl_desc = LDAPサーバーへのURL
view_admin_systemSettings_LDAPUrl_name = LDAP URL
view_admin_systemSettings_RtDataPurge_desc = データベースから除去される前の応答時間の保持時間。これは日単位で指定されます。
-view_admin_systemSettings_RtDataPurge_name = 次より古い応答時間の削除
+view_admin_systemSettings_RtDataPurge_name = 古い応答時間の削除
view_admin_systemSettings_TraitPurge_desc = データベースから除去される前の測定トレイトデータの保持時間。これは日単位で指定されます。
-view_admin_systemSettings_TraitPurge_name = 次より古い測定トレイトの削除
+view_admin_systemSettings_TraitPurge_name = 古い測定トレイトの削除
view_admin_systemSettings_cannotLoadServerDetails = サーバー詳細をロードできません
view_admin_systemSettings_cannotLoadSettings = 現在のシステム設定を取得できません
-##view_admin_systemSettings_dumpToLogFailed = Writing of system info to server log file failed
-##view_admin_systemSettings_dumpedToLog = System info was successfully written to server log file
view_admin_systemSettings_fixBeforeSaving = 保存前に無効な値を修正してください
view_admin_systemSettings_group_baseline = 自動ベースライン構成プロパティ
view_admin_systemSettings_group_dataMgr = データマネージャー構成プロパティ
-##view_admin_systemSettings_group_drift = Drift Server Configuration Settings
+view_admin_systemSettings_group_drift = ドリフトサーバー構成設定
view_admin_systemSettings_group_general = 全体構成プロパティ
view_admin_systemSettings_group_ldap = LDAP構成プロパティ
view_admin_systemSettings_saveFailure = システム設定の保存に失敗しました
@@ -661,26 +657,26 @@ view_alert_common_tab_conditions_text = 条件
view_alert_common_tab_conditions_type_availability = アベイラビリティの変化
view_alert_common_tab_conditions_type_availability_down = 下降
view_alert_common_tab_conditions_type_availability_up = 上昇
-##view_alert_common_tab_conditions_type_drift = Drift Detection
-##view_alert_common_tab_conditions_type_drift_configpaths = Drift Detection for files that match "{0}" and for drift definition [{1}]
-##view_alert_common_tab_conditions_type_drift_onlyconfig = Drift Detection for drift definition [{0}]
-##view_alert_common_tab_conditions_type_drift_onlypaths = Drift Detection for files that match "{0}"
+view_alert_common_tab_conditions_type_drift = ドリフトの検出
+view_alert_common_tab_conditions_type_drift_configpaths = "{0}" に一致するファイルとドリフト定義 [{1}] のためのドリフトの検出
+view_alert_common_tab_conditions_type_drift_onlyconfig = ドリフト定義 [{0}] のためのドリフト検出
+view_alert_common_tab_conditions_type_drift_onlypaths = "{0}" に一致するファイルのためのドリフト検出
view_alert_common_tab_conditions_type_event = イベントの検出
view_alert_common_tab_conditions_type_event_matching = イベントソースが一致
view_alert_common_tab_conditions_type_metric_baseline = メトリック値のベースライン
view_alert_common_tab_conditions_type_metric_baseline_verb = of
view_alert_common_tab_conditions_type_metric_calltime_change = 呼び出し時間の変化
-view_alert_common_tab_conditions_type_metric_calltime_change_verb = by at least
+##view_alert_common_tab_conditions_type_metric_calltime_change_verb = by at least
view_alert_common_tab_conditions_type_metric_calltime_delta_grows = 上昇
view_alert_common_tab_conditions_type_metric_calltime_delta_other = 変化
view_alert_common_tab_conditions_type_metric_calltime_delta_shrinks = 縮小
view_alert_common_tab_conditions_type_metric_calltime_destination = 呼び出しの宛先が一致
view_alert_common_tab_conditions_type_metric_calltime_threshold = 呼び出し時間の閾値
view_alert_common_tab_conditions_type_metric_change = メトリック値の変換
-##view_alert_common_tab_conditions_type_metric_range_inside_exclusive = Metric Value Range: [{0}] between [{1}] and [{2}], exclusive
-##view_alert_common_tab_conditions_type_metric_range_inside_inclusive = Metric Value Range: [{0}] between [{1}] and [{2}], inclusive
-##view_alert_common_tab_conditions_type_metric_range_outside_exclusive = Metric Value Range: [{0}] outside [{1}] and [{2}], exclusive
-##view_alert_common_tab_conditions_type_metric_range_outside_inclusive = Metric Value Range: [{0}] outside [{1}] and [{2}], inclusive
+view_alert_common_tab_conditions_type_metric_range_inside_exclusive = メトリック値の範囲 [{0}] : [{1}] と [{2}] の間 (境界値を含まない)
+view_alert_common_tab_conditions_type_metric_range_inside_inclusive = メトリック値の範囲 [{0}] : [{1}] と [{2}] の間 (境界値を含む)
+view_alert_common_tab_conditions_type_metric_range_outside_exclusive = メトリック値の範囲 [{0}] : [{1}] と [{2}] の外側(境界値を含まない)
+view_alert_common_tab_conditions_type_metric_range_outside_inclusive = メトリック値の範囲 [{0}] : [{1}] と [{2}] の外側(境界値を含む)
view_alert_common_tab_conditions_type_metric_threshold = メトリック値の閾値
view_alert_common_tab_conditions_type_metric_trait_change = トレイトの変化
view_alert_common_tab_conditions_type_operation = オペレーションの実行
@@ -714,25 +710,25 @@ view_alert_common_tab_notifications_message = メッセージ
view_alert_common_tab_notifications_sender = センダー
view_alert_common_tab_notifications_status = ステータス
view_alert_common_tab_recovery = リカバリ
-view_alert_definition_condition_editor_avilability_option_down = 下降する
-view_alert_definition_condition_editor_avilability_option_up = 上昇する
+view_alert_definition_condition_editor_avilability_option_down = 停止
+view_alert_definition_condition_editor_avilability_option_up = 起動
view_alert_definition_condition_editor_avilability_tooltip = 条件のトリガーとなるアベイラビリティ状態の変化を指定します
view_alert_definition_condition_editor_avilability_value = アベイラビリティ
view_alert_definition_condition_editor_common_avg = 平均
view_alert_definition_condition_editor_common_max = 最大
view_alert_definition_condition_editor_common_min = 最小
view_alert_definition_condition_editor_delete_confirm = 選択されたアラート定義を削除しますか?
-##view_alert_definition_condition_editor_drift_configname_regex = Drift Definition Name
-##view_alert_definition_condition_editor_drift_configname_regex_tooltip = If specified, this is the drift definition name that was responsible for the drift that was detected. This can optionally be a regular expression if you wish to match multiple drift definition names.
-##view_alert_definition_condition_editor_drift_pathname_regex = Pathname Regular Expression
-##view_alert_definition_condition_editor_drift_pathname_regex_tooltip = If specified, this is a regular expression that must match the pathnames of those files that drifted.
-##view_alert_definition_condition_editor_drift_tooltip = This condition is triggered when drift has been detected.
+view_alert_definition_condition_editor_drift_configname_regex = ドリフト定義名
+view_alert_definition_condition_editor_drift_configname_regex_tooltip = もし指定されたなら、これは検出されたドリフトのための責任を持ったドリフト定義名です。これは複数のドリフト定義名に一致させたいのならオプションとして正規表現にすることもできます。
+view_alert_definition_condition_editor_drift_pathname_regex = パス名正規表現
+view_alert_definition_condition_editor_drift_pathname_regex_tooltip = もし指定されたなら、これはドリフトされたファイルのパス名に一致しなければならない正規表現になります。
+view_alert_definition_condition_editor_drift_tooltip = この条件はドリフトが検出されたときがトリガーになります。
view_alert_definition_condition_editor_event_regex = 正規表現
view_alert_definition_condition_editor_event_regex_tooltip = もし指定されたなら、これは正規表現であり、この条件を引き起こすために収集されたイベントメッセージに一致しなければなりません。
view_alert_definition_condition_editor_event_severity = イベント重大度
view_alert_definition_condition_editor_event_tooltip = この条件を引き起こすためにイベントメッセージが報告される必要があるイベント重大度を指定します。もしオプションとなる正規表現を指定したなら、イベントメッセージはその条件が引き起こされるためにイベントメッセージも正規表現に一致しなければなりません。
view_alert_definition_condition_editor_metric_baseline_percentage = ベースラインパーセンテージ
-view_alert_definition_condition_editor_metric_baseline_percentage_tooltip = 選択された比較子(comparator)を使用して選択されたベースライン値のパーセンテージを比較するときに収集されたメトリック値はこの条件を引き起こします。
+view_alert_definition_condition_editor_metric_baseline_percentage_tooltip = 選択された比較演算子を使用して選択されたベースライン値のパーセンテージを比較するときに収集されたメトリック値はこの条件を引き起こします。
view_alert_definition_condition_editor_metric_baseline_tooltip = 条件を引き起こすために違反されることが必要となるベースライン値を指定します。指定する値は、与えられたベースライン値のパーセンテージになります。
view_alert_definition_condition_editor_metric_baseline_value = ベースライン
view_alert_definition_condition_editor_metric_calltime_change_percentage = パーセンテージの変化
@@ -753,19 +749,19 @@ view_alert_definition_condition_editor_metric_calltime_threshold_value = 呼び
view_alert_definition_condition_editor_metric_calltime_threshold_value_tooltip = 選択された比較子(comparator)を使って比較するとき条件が引き起こされるメトリックの閾値
view_alert_definition_condition_editor_metric_change_tooltip = 条件を引き起こすために変更しなければならない値を持つメトリックを指定します
view_alert_definition_condition_editor_metric_common_definition_not_found = メトリック定義が見つかるべきです - 何かがおかしいです
-##view_alert_definition_condition_editor_metric_nometrics = When using the ALL conjunction, you cannot use the same metric in multiple conditions and this alert uses all available metrics in currently existing conditions.
-view_alert_definition_condition_editor_metric_range_comparator = コンパレータ
-##view_alert_definition_condition_editor_metric_range_comparator_inside_exclusive = Inside, exclusive
-##view_alert_definition_condition_editor_metric_range_comparator_inside_inclusive = Inside, inclusive
-##view_alert_definition_condition_editor_metric_range_comparator_outside_exclusive = Outside, exclusive
-##view_alert_definition_condition_editor_metric_range_comparator_outside_inclusive = Outside, inclusive
-##view_alert_definition_condition_editor_metric_range_comparator_tooltip = Determines if a metric value should trigger this condition when inside the range or outside of it.
-##view_alert_definition_condition_editor_metric_range_hivalue = High Value
-##view_alert_definition_condition_editor_metric_range_hivalue_tooltip = The high threshold value of the range.
-##view_alert_definition_condition_editor_metric_range_lovalue = Low Value
-##view_alert_definition_condition_editor_metric_range_lovalue_tooltip = The high threshold value of the range.
-##view_alert_definition_condition_editor_metric_range_tooltip = Compares a metric value to a given low-high value range.
-view_alert_definition_condition_editor_metric_threshold_comparator = コンパレータ
+view_alert_definition_condition_editor_metric_nometrics = すべてを連結して使うとき、複数条件内に同じメトリックを使うことはできません。この警告は現在の条件内でのすべての利用可能なメトリックスを使います。
+view_alert_definition_condition_editor_metric_range_comparator = 比較演算子
+view_alert_definition_condition_editor_metric_range_comparator_inside_exclusive = 内部で、境界値を含まない
+view_alert_definition_condition_editor_metric_range_comparator_inside_inclusive = 内部で、境界値を含む
+view_alert_definition_condition_editor_metric_range_comparator_outside_exclusive = 外部で、 境界値を含まない
+view_alert_definition_condition_editor_metric_range_comparator_outside_inclusive = 外部で、 境界値を含む
+view_alert_definition_condition_editor_metric_range_comparator_tooltip = メトリック値が、範囲内か範囲外のとき、この条件のトリガーになるかどうかを決定します。
+view_alert_definition_condition_editor_metric_range_hivalue = 高値
+view_alert_definition_condition_editor_metric_range_hivalue_tooltip = 範囲での高値の閾値
+view_alert_definition_condition_editor_metric_range_lovalue = 低値
+view_alert_definition_condition_editor_metric_range_lovalue_tooltip = 範囲における低値の閾値
+view_alert_definition_condition_editor_metric_range_tooltip = メトリック値と与えられた値の範囲(低値から高値)を比較します。
+view_alert_definition_condition_editor_metric_threshold_comparator = 比較演算子
view_alert_definition_condition_editor_metric_threshold_comparator_equal = 等しい
view_alert_definition_condition_editor_metric_threshold_comparator_greater = より大きい
view_alert_definition_condition_editor_metric_threshold_comparator_less = より少ない
@@ -776,18 +772,18 @@ view_alert_definition_condition_editor_metric_threshold_value = メトリック
view_alert_definition_condition_editor_metric_threshold_value_tooltip = メトリックの閾値は、選択されたコンパレータを使って比較されたときの条件のトリガーになります
view_alert_definition_condition_editor_metric_trait_change_tooltip = 条件を引き起こすために変更しなければならない値を持つトレイとを指定します
view_alert_definition_condition_editor_metric_trait_change_value = トレイト
-##view_alert_definition_condition_editor_metricswarning = You cannot have multiple conditions that use the same metric when using the ALL conjunction. This alert definition has multiple conditions that use the metric [{0}].
+view_alert_definition_condition_editor_metricswarning = すべての連結を使うときは同じメトリックを使う複数の条件を指定することはできません。この警告定義はそのメトリック [{0}] を使う複数の条件を持ちます。
view_alert_definition_condition_editor_operation_status = オペレーションステータス
view_alert_definition_condition_editor_operation_tooltip = 条件を引き起こすために選択されたが実行されるとき発生しなければならない結果を指定します
view_alert_definition_condition_editor_option_availability = アベイラビリティの変化
-##view_alert_definition_condition_editor_option_drift = Drift Detection
+view_alert_definition_condition_editor_option_drift = ドリフトの検出
view_alert_definition_condition_editor_option_event = イベントの検出
view_alert_definition_condition_editor_option_label = 条件タイプ
view_alert_definition_condition_editor_option_metric_baseline = 測定ベースラインの閾値
view_alert_definition_condition_editor_option_metric_calltime_change = 呼び出し時間の変化
view_alert_definition_condition_editor_option_metric_calltime_threshold = 呼び出し時間の閾値
view_alert_definition_condition_editor_option_metric_change = 測定値の変化
-##view_alert_definition_condition_editor_option_metric_range = Measurement Value Range
+view_alert_definition_condition_editor_option_metric_range = 測定値の範囲
view_alert_definition_condition_editor_option_metric_threshold = 測定絶対値の閾値
view_alert_definition_condition_editor_option_metric_trait_change = トレイト値の変化
view_alert_definition_condition_editor_option_operation = オペレーションの実行
@@ -826,7 +822,7 @@ view_alert_definition_notification_operation_editor_mode_this = このリソー
view_alert_definition_notification_operation_editor_mode_title = リソース選択モード
view_alert_definition_notification_operation_editor_mode_unknown = 未知のオプション - これはバグです
view_alert_definition_notification_operation_editor_operations_loadFailed = 利用可能なオペレーションのリストをロードするのに失敗しました
-view_alert_definition_notification_operation_editor_operations_no_parameters = この操作は一つもパラメータを取りません
+view_alert_definition_notification_operation_editor_operations_no_parameters = この操作は一つもパラメーターを取りません
view_alert_definition_notification_operation_editor_relative_ancestor = 検索を開始
view_alert_definition_notification_operation_editor_relative_ancestor_loadFailed = タイプの祖先を取得できません
view_alert_definition_notification_operation_editor_relative_ancestor_root = ルートの祖先タイプ
@@ -914,23 +910,27 @@ view_autoDiscoveryQ_field_inventoryStatus = インベントリステータス
view_autoDiscoveryQ_field_parentId = 親ID
view_autoDiscoveryQ_ignore = 無視
view_autoDiscoveryQ_ignoreFailure = リソースを無視するのに失敗しました
+view_autoDiscoveryQ_ignoreInProgress = 選択されたリソースを無視している途中です...
view_autoDiscoveryQ_ignoreSuccessful = 選択したリソースを無視するのに成功しました
view_autoDiscoveryQ_ignored = 無視済み
view_autoDiscoveryQ_importFailure = リソースのインポートに失敗しました
+view_autoDiscoveryQ_importInProgress = 選択されたリソースをインポート中です...
view_autoDiscoveryQ_importSuccessful = 選択したリソースのインポートに成功しました。
view_autoDiscoveryQ_loadFailure = インベントリディスカバリキューをロードするのに失敗しました
view_autoDiscoveryQ_newAndIgnored = 新規かつ無視済み
view_autoDiscoveryQ_noperm = (自動ディスカバリキューを閲覧する権限がありません)
+view_autoDiscoveryQ_selectAll = すべてを選択
view_autoDiscoveryQ_showStatus = 表示
view_autoDiscoveryQ_title = 自動リカバリキュー
view_autoDiscoveryQ_unignore = 無視解除
view_autoDiscoveryQ_unignoreFailure = リソースを無視解除のに失敗しました
+view_autoDiscoveryQ_unignoreInProgress = 選択されたリソースの無視を解除中です...
view_autoDiscoveryQ_unignoreSuccessful = 選択したリソースの無視解除に成功しました
view_autoDiscoveryQ_uninventoried = インベントリ登録をしない
view_bundleVersion_loadFailure = バンドルバージョンデータをロードするのに失敗しました
view_bundle_bundle = バンドル
-view_bundle_bundleDeployment = バンドルデプロイ
-view_bundle_bundleDeployments = バンドルデプロイ
+view_bundle_bundleDeployment = バンドルデプロイメント
+view_bundle_bundleDeployments = バンドルデプロイメント
view_bundle_bundleDestinations = バンドル宛先
view_bundle_bundleFiles = バンドルファイル
view_bundle_bundleType = バンドルタイプ
@@ -954,7 +954,7 @@ view_bundle_createWizard_noBundleTypesSupported = バンドルタイプは一つ
view_bundle_createWizard_provideBundleDistro = バンドル配布の提供
view_bundle_createWizard_recipeOption = レシピ
view_bundle_createWizard_title = バンドル作成
-view_bundle_createWizard_uploadInProgress = アップロード中です... この操作は大きいファイルの場合には数分かかることもありません
+view_bundle_createWizard_uploadInProgress = アップロード中です... この操作は大きいファイルの場合には数分かかることもあります
view_bundle_createWizard_uploadOption = アップロード
view_bundle_createWizard_uploadStepName = バンドルファイルのアップロード
view_bundle_createWizard_urlOption = URL
@@ -985,12 +985,17 @@ view_bundle_deployWizard_error_6 = デプロイメントの作成に失敗しま
view_bundle_deployWizard_error_7 = デプロイメント名の取得に失敗しました
view_bundle_deployWizard_error_8 = ドロップダウンから正しいリソースグループを選択しなければなりません
view_bundle_deployWizard_error_9 = 次ページでの新しい宛先の削除に失敗しました
+view_bundle_deployWizard_error_noBundleConfig = バンドルターゲット情報の取得に失敗しました。選択したグループはバンドルデプロイメントのターゲットに成り得る正当な互換グループですか?
view_bundle_deployWizard_getConfigSkip = このバンドルバージョンには構成は必要ありません
view_bundle_deployWizard_getConfigStep = デプロイメント構成の設定
view_bundle_deployWizard_getDestStep = 新しい宛先
view_bundle_deployWizard_getDest_deployDir = ルートデプロイディレクトリ (宛先プラットフォーム上での)
+view_bundle_deployWizard_getDest_deployDir_help = そのバンドルがデプロイされるディレクトリ。このディレクトリはすべてのリソースに関するすべてのデプロイ用として同じものが使われますが、宛先の基本ディレクトリの場所に対する相対ディレクトリになります。このことは、異なるターゲットリソースについて基本ディレクトリの配置がどこにあるかということに依存して、その絶対ディレクトリは異なるターゲットリソースによって異なるパスになる可能性があることを意味しています。
view_bundle_deployWizard_getDest_desc = 宛先の説明
+view_bundle_deployWizard_getDest_destBaseDirName = 基本の配置
+view_bundle_deployWizard_getDest_group_help = メンバーがすべてのバンドルデプロイのための宛先ターゲットとなるようなグループ。バンドルデプロイをサポートするリソースを含む互換グループのみが選択可能です。
view_bundle_deployWizard_getDest_name = 宛先名
+view_bundle_deployWizard_getDest_name_help = 宛先名。それはリソースの特定のグループと特定のバンドルのリソースに関する宛先ディレクトリを識別します。
view_bundle_deployWizard_getInfoStep = デプロイ情報の提供
view_bundle_deployWizard_getInfo_clean = クリーンデプロイですか? (宛先プラットフォーム上でのデプロイディレクトリを掃除する)
view_bundle_deployWizard_getInfo_deploymentDesc = デプロイの説明
@@ -1019,6 +1024,7 @@ view_bundle_deploy_loadBundleFailure = バンドルの検索に失敗しまし
view_bundle_deploy_loadDeployFailure = バンドルデプロイのロードに失敗しました
view_bundle_deploy_loadFailure = バンドルデプロイのロードに失敗しました
view_bundle_deploy_name = デプロイ名
+view_bundle_deploy_operatingSystem = オペレーティングシステム
view_bundle_deploy_selectARow = インストールの詳細を表示するために行を選択してください
view_bundle_deploy_tagUpdateFailure = バンドルデプロイタブの更新に失敗しました
view_bundle_deploy_tagUpdateSuccessful = バンドルデプロイタグの更新に成功しました
@@ -1026,6 +1032,7 @@ view_bundle_deploy_time = デプロイ名
view_bundle_deployed = デプロイ
view_bundle_deployments = デプロイ
view_bundle_dest_backToBundle = バンドルへ戻る
+view_bundle_dest_baseDirName = 基本の配置
view_bundle_dest_created = 作成された
view_bundle_dest_deleteConfirm = このバンドル宛先を削除してもよろしいですか? これはデータベースから削除するだけです。つまり、リモートマシンのこの宛先にデプロイされたすべてのバンドルの内容は残り続けます
view_bundle_dest_deleteFailure = バンドル宛先 [{0}] の削除に失敗しました
@@ -1128,7 +1135,7 @@ view_configurationDetails_configNotUpdatedDueToNoChange = 構成は更新され
view_configurationDetails_error_updateFailure = 構成の更新に失敗しました
view_configurationDetails_messageConcise = 構成は更新されました - 現在のバージョンは {0} です
view_configurationDetails_messageDetailed = リソース [{1}] の構成はバージョン {0} へ更新されました
-##view_configurationDetails_noConfigurationFetched = No configuration was retrieved. This means that either the plugin failed to load the configuration or that configuration collection is merely switched off in the connection settings.
+view_configurationDetails_noConfigurationFetched = 構成が取り出せませんでした。これはプラグインが構成をロードできなかったか、または構成コレクションが接続設定において単にスイッチがオフにされているかのいずれかを意味します。
view_configurationDetails_noPermission = このリソースの構成を編集する権限がありません
view_configurationDetails_somePropertiesInvalid = 次の構成プロパティは不正な値: {0} です。この値は構成が保存される前に訂正されなければなりません。
view_configurationHistoryDetails_error_loadFailure = 構成履歴をロードできません
@@ -1151,11 +1158,11 @@ view_connectionSettingsDetails_messageConcise_updateSuccess = コネクション
view_connectionSettingsDetails_messageDetailed_updateSuccess = リソース [{0} のためのコネクション設定が更新されました
view_connectionSettingsDetails_noPermission = このリソースのコネクション設定を編集する権限がありません
view_connectionSettingsDetails_somePropertiesInvalid = 次のコネクション設定は不正な値: {0} です。設定を保存する前に訂正しなければなりません。
-#view_core_loggedInAs = Logged in as {0}
+view_core_loggedInAs = {0} としてログイン
view_core_loggedOut = ログアウト
view_core_noRecentAlerts = レポートすべき最近のアラートは存在しません
view_core_recentAlerts = [{0}] 個の最近のアラートがありました - 最近のアラートレポートへクリックしてください
-##view_core_serverUnreachable = The server is unreachable and may be down
+view_core_serverUnreachable = サーバーに到達できません。ダウンしている可能性があります。
view_core_uncaught = グローバルにキャッチされない例外
view_dashboardManager_deleteFail = ダッシュボードの削除に失敗しました
view_dashboardManager_deleted = ダッシュボード {0} の削除に成功しました
@@ -1164,7 +1171,7 @@ view_dashboardManager_saved = ダッシュボード {0} をサーバーへ保存
view_dashboardManager_success = ダッシュボードを保存しました
view_dashboard_favorites_error1 = 好みのリソースをロードするのに失敗しました
view_dashboardsManager_error1 = 新しいダッシュボードを追加するのに失敗しました
-##view_dashboardsManager_message_title_details = <h1>RHQへようこそ</h1>\n<p>RHQプロジェクトは抽象化されたプラグインベースのシステム管理スイートで、複数のプロダクトやプラットフォームに対してコア機能を横断的に適用できる拡張可能で、統合化されたシステム管理を提供します。このプロジェクトはレイヤ化されたモジュールによって設計されていて、デプロイのための柔軟なアーキテクチャを提供します。それは企業全体に対する監査と履歴の管理を提供するコアとなるユーザーインタフェースを導入します。サーバー/エージェントアーキテクチャはリモートでの管理と特定プロダクトのサポートを実現するプラグインを提供します。 </p>\n <p>このデフォルトのダッシュボードは上の「編集モード」ボタンをすることで編集可能です。</p>
+## view_dashboardsManager_message_title_details = <h1>RHQへようこそ</h1>\n<p>RHQプロジェクトは抽象化されたプラグインベースのシステム管理スイートで、複数のプロダクトやプラットフォームに対してコア機能を横断的に適用できる拡張可能で、統合化されたシステム管理を提供します。このプロジェクトはレイヤ化されたモジュールによって設計されていて、デプロイのための柔軟なアーキテクチャを提供します。それは企業全体に対する監査と履歴の管理を提供するコアとなるユーザーインタフェースを導入します。サーバー/エージェントアーキテクチャはリモートでの管理と特定プロダクトのサポートを実現するプラグインを提供します。 </p>\n <p>このデフォルトのダッシュボードは上の「編集モード」ボタンをすることで編集可能です。</p>
view_dashboards_confirm1 = 削除してもよろしいですか
view_dashboards_portlets_refresh_fail1 = 自動リフレッシュするポートレットのリフレッシュ間隔の更新に失敗しました
view_dashboards_portlets_refresh_fail2 = 自動リフレッシュするポートレットのリロードの無効化に失敗しました
@@ -1174,85 +1181,76 @@ view_dashboards_portlets_refresh_one_min = 1 分
view_dashboards_portlets_refresh_success1 = ポートレットの自動リフレッシュ間隔を更新しました
view_dashboards_portlets_refresh_success2 = 自動リフレッシュするポートレットのリロードを停止しています
view_dashboards_title = ダッシュボード
-##view_drift_button_detectNow = Detect Now
-##view_drift_button_pinToDef = Pin to Definition
-##view_drift_button_pinToDef_confirm = Pinning will set this snapshot as snapshot 0 for the definition. All other existing snapshots will be removed from the definition. The definition will be be marked as pinned and subsequent drift will always be reported against the pinned snapshot. Pin this snapshot to the definition?
-##view_drift_button_pinToTemplate = Pin to Template
-##view_drift_button_pinToTemplate_confirm = After pinning, this snapshot will be set to the initial snapshot for all definitions created using the template. If pinned to an existing template then the template''s existing definitions will be pinned to the new initial snapshot and their existing snapshots will be removed. Continue to template selection?
-##view_drift_carousel_sizeFilterLabel = Snapshot Display Max
-##view_drift_carousel_startFilterLabel = Snapshot Start
-##view_drift_category_fileAdded = File Added
-##view_drift_category_fileChanged = File Changed
-##view_drift_category_fileNew = Newly Detected
-##view_drift_category_fileRemoved = File Removed
-##view_drift_confirm_deleteAllDefs = Delete all drift detection definitions?
-##view_drift_confirm_deleteDefs = Delete the selected drift detection definition(s)?
-##view_drift_confirm_deleteTemplate = Warning! Deleting this template will also cause all attached drift definitions to be deleted as well. Those attached definitions along with all of their snapshots will be permanently removed from the system. Detached definitions will not be removed. Are you sure you want to continue?
-##view_drift_failure_deleteDefs = Failed to delete some or all drift detection definitions.
-##view_drift_failure_deleteTemplates = Failed to delete some or all of the drift templates
-##view_drift_failure_detectNow = Failed to submit drift detection run request
-##view_drift_failure_load = Failed to fetch drift instances
-##view_drift_failure_pinToDef = Failed to pin snapshot to definition
-##view_drift_success_defUpdated = Drift detection definition updated and will affect the next detection run as applicable.
-##view_drift_success_delete = Successfully deleted {0} drift instances
-##view_drift_success_deleteDefs = Successfully deleted {0} drift detection definitions
-##view_drift_success_deleteTemplate = Successfully deleted {0} drift templates
-##view_drift_success_detectNow = Successfully submitted drift detection run request
-##view_drift_success_pinToDef = Successfully pinned snapshot {0} to drift definition.
-##view_drift_success_templateUpdated = Drift template updated and changes pushed to attached definitions.
-##view_drift_table_attached = Attached?
-##view_drift_table_baseDir = Base Directory
-##view_drift_table_driftHandlingMode = Drift Handling
-##view_drift_table_driftHandlingMode_normal = normal
-##view_drift_table_driftHandlingMode_plannedChanges = planned changes
-##view_drift_table_hover_defNotPinned = The drift definition is not pinned Click to view the initial snapshot.
-##view_drift_table_hover_defPinned = The drift definition is pinned to its initial snapshot. Click to view the initial snapshot.
-##view_drift_table_hover_edit = Click to view or edit the drift definition or template properties.
-##view_drift_table_hover_outOfCompliance_drift = There is drift
-##view_drift_table_hover_outOfCompliance_noBaseDir = The base directory does not exist
-##view_drift_table_hover_templateNotPinned = The drift template is not pinned to a snapshot.
-##view_drift_table_hover_templatePinned = The drift template is pinned to a snapshot. Click to view the pinned snapshot.
-##view_drift_table_newFile = New File
-##view_drift_table_oldFile = Old File
-##view_drift_table_pinned = Pinned?
-##view_drift_table_resourceDef = Resource Drift Detection Definition
-##view_drift_table_resourceHistory = Resource Drift History
-##view_drift_table_snapshot = Snapshot
-##view_drift_table_snapshotTime = Snapshot Time
-##view_drift_table_template = Template
-##view_drift_table_title_initialSnapshot = Initial Snapshot for Definition [{0}] : Pinned = [{1}]
-##view_drift_table_title_snapshot = Snapshot [{0}] for Definition [{1}]
-##view_drift_table_title_templateSnapshot = Pinned Snapshot for Template [{0}]
-##view_drift_wizard_addDef_failure = Failed to add new drift detection definition [{0}]
-##view_drift_wizard_addDef_infoStepHelp = Each drift detection definition describes a set of files for which drift monitoring will be performed. The definition can be enabled and disabled, defines the detection run interval, and specifies a base directory and optional file filters. For each resource type offering drift detection there will be one or more predefined templates to use as a starting definition, which can then be edited.
-##view_drift_wizard_addDef_infoStepName = Select the Template for the new Drift Detection Definition
-##view_drift_wizard_addDef_success = Successfully added new drift detection definition [{0}]. Agent(s) will be updated.
-##view_drift_wizard_addDef_templatePrompt = Drift Definition Templates
-##view_drift_wizard_addDef_title = Add Drift Detection Definition for Resource of Type [{0}]
-##view_drift_wizard_addDef_windowTitle = Add Drift Detection Definition Wizard
-##view_drift_wizard_addTemplate_failure = Failed to add new drift detection template [{0}]
-##view_drift_wizard_addTemplate_infoStepHelp = Each drift template is derived from an existing template. This provides a quick way to build new templates that are similar to existing templates, or originate with plugin defined templates. Like a drift definition, the template describes a set of files for which drift monitoring will be performed. Depending on the situation a definition derived from the template may or may not be allowed to alter the file set, or change other settings. Template names must be unique within a resource type.
-##view_drift_wizard_addTemplate_infoStepName = Select the Starting Template
-##view_drift_wizard_addTemplate_success = Successfully added new drift template [{0}].
-##view_drift_wizard_addTemplate_title = Add Drift Definition Template for Type [{0}]
-##view_drift_wizard_addTemplate_windowTitle = Add Drift Definition Template Wizard
-##view_drift_wizard_pinTemplate_confirmNotPinned = Once pinned each current and future drift definition for the template will have its initial snapshot set to the template''s pinned snapshot. Existing definitions for this template will be reset to the new initial snapshot, and all exsiting snapshots will be removed. Continue pinning the template to the snapshot?
-##view_drift_wizard_pinTemplate_confirmPinned = Warning! This template is already pinned. The template can be re-pinned to this new snapshot. Once re-pinned each current and future drift definition for the template will have its initial snapshot set to the template''s pinned snapshot. Existing definitions for this template will be reset to the new initial snapshot, and all exsiting snapshots will be removed. Continue re-pinning the template with this new snapshot?
-##view_drift_wizard_pinTemplate_duplicate_name_error = Template name must be unique
-##view_drift_wizard_pinTemplate_failure = Failed to pin snapshot to drift template [{0}]
-##view_drift_wizard_pinTemplate_infoStepExistingTemplate = Pin to ExistingTemplate
-##view_drift_wizard_pinTemplate_infoStepHelp = Select the template to pin. Once pinned each current and future drift definition for that template will have its initial snapshot set to the template''s pinned snapshot. And the definition itself will be marked as pinned. This is used to detect drift from an expected file set. Note that existing definitions for this template will be reset to the new initial snapshot, and all exsiting snapshots will be removed.
-##view_drift_wizard_pinTemplate_infoStepName = Select the Template to be Pinned
-##view_drift_wizard_pinTemplate_infoStepNewTemplate = Pin to New Template (derived from the snapshot''s Drift Definition)
-##view_drift_wizard_pinTemplate_infoStepRadioHelp = The snapshot can be pinned to a new or existing drift template. The ''New Template" option allows the user to promote a trusted definition and snapshot, at the resource level, to the type level. The new template can then be applied to members of the type. The new template is initially a copy of the snapshot''s drift definition but can then be edited in the next step. The name should be changed and must be a unique drift template name for the type. The "Existing Template" option allows the user to pin, or re-pin, an existing template with the selected snapshot. To be valid, the existing template must monitor the same directories as the snapshot''s definition. The selection box displays only valid existing templates. If there are no valid existing templates this option can not be selected.
-##view_drift_wizard_pinTemplate_infoStepRadioTitle = Template Selection
-##view_drift_wizard_pinTemplate_infoStepSelectBlocked = There are no existing templates that monitor the same directories as the snapshot''s definition. Select the "New Template" option to continue.
-##view_drift_wizard_pinTemplate_infoStepSelectTitle = Existing Templates
-##view_drift_wizard_pinTemplate_success = Successfully pinned the drift template [{0}].
-##view_drift_wizard_pinTemplate_title = Pin Snapshot [{0}] of Definition [{1}] to a Drift Template for type [{2}]
-##view_drift_wizard_pinTemplate_windowTitle = Pin Drift Definition Template Wizard
+view_drift_button_detectNow = すぐに検出
+view_drift_button_pinToDef = 定義としてピン留め
+view_drift_button_pinToDef_confirm = ピン留めはこのスナップショットを定義のスナップショット 0 として設定します。その他すべてのスナップショットはその定義から削除されます。その定義はピン留めされたとマークされ、以後のドリフトは常にそのピン留めされたスナップショットに対して報告されます。このスナップショットをその定義にピン留めしますか?
+view_drift_button_pinToTemplate = テンプレートとしてピン留め
+view_drift_button_pinToTemplate_confirm = ピン留めした後は、このスナップショットはそのテンプレートを使って作成されたすべての定義のために初期スナップショットに設定されます。もし既存テンプレートにピン留めされるなら、テンプレートの既存の定義は新規の初期スナップショットに対してピン留めされ、それら既存のスナップショットは削除されます。選択したものをテンプレートにするために継続しますか?
+view_drift_carousel_sizeFilterLabel = スナップショットの最大表示数
+view_drift_carousel_startFilterLabel = スナップショット開始
+view_drift_category_fileAdded = 追加ファイル
+view_drift_category_fileChanged = 変更ファイル
+view_drift_category_fileNew = 新規に検出されたファイル
+view_drift_category_fileRemoved = 削除ファイル
+view_drift_delete_defConfirm = 選択されたドリフトの検出定義を削除しますか?
+view_drift_delete_defConfirmAll = すべてのドリフト検出定義を削除しますか?
+view_drift_failure_deleteDefs = いくつか、あるいはすべてのドリフト検出定義の削除に失敗しました
+view_drift_failure_detectNow = ドリフト検出実行リクエストの送信に失敗しました
+view_drift_failure_load = ドリフトインスタンスの取り出しに失敗しました
+view_drift_failure_pinToDef = 定義へのスナップショットのピン留めに失敗しました
+view_drift_success_defUpdated = ドリフト検出定義が更新されました。これは規定通りに次回の検出実行に影響があるでしょう。
+view_drift_success_delete = ドリフトインスタンス {0} の削除が成功しました
+view_drift_success_deleteDefs = ドリフト定義 {0} の削除が成功しました
+view_drift_success_detectNow = ドリフト検出実行リクエストの送信に成功しました
+view_drift_success_pinToDef = ドリフト定義へのスナップショット {0} のピン留めに成功しました
+view_drift_table_baseDir = 基本ディレクトリ
+view_drift_table_driftHandlingMode = ドリフト処理
+view_drift_table_driftHandlingMode_normal = 通常
+view_drift_table_driftHandlingMode_plannedChanges = 計画変更
+view_drift_table_hover_defNotPinned = そのドリフト定義はピン留めされていません。クリックして初期スナップショットを見てください。
+view_drift_table_hover_defPinned = そのドリフト定義は初期スナップショットへピン留めされています。クリックして初期スナップショットを見てください。
+view_drift_table_hover_edit = クリックしてそのドリフト定義またはテンプレートプロパティを閲覧する、または編集してください
+view_drift_table_hover_templateNotPinned = そのドリフトテンプレートはどのスナップショットにもピン留めされていません
+view_drift_table_hover_templatePinned = そのドリフトテンプレートはあるスナップショットにピン留めされています。クリックしてピン留めされたスナップショットを見てください
+view_drift_table_newFile = 新ファイル
+view_drift_table_oldFile = 旧ファイル
+view_drift_table_pinned = ピン留め?
+view_drift_table_resourceDef = リソースドリフト検出定義
+view_drift_table_resourceHistory = リソースドリフト履歴
+view_drift_table_snapshot = スナップショット
+view_drift_table_snapshotTime = スナップショット時間
+view_drift_table_title_initialSnapshot = 定義 [{0}] のための初期スナップショット: ピン留め = [{1}]
+view_drift_table_title_snapshot = 定義 [{1}] のためのスナップショット [{0}]
+view_drift_table_title_templateSnapshot = テンプレート [{0}] のためのピン留めされたスナップショット
+view_drift_wizard_addDef_failure = ドリフト検出定義 [{0}] の新規追加に失敗しました
+view_drift_wizard_addDef_infoStepHelp = 各ドリフト検出定義はドリフトモニタリングが実行される一式のファイルを記述します。その定義は有効または無効にしたり、検出の実行間隔を定義したり、基本ディレクトリとファイルフィルタ(オプション)を指定することができます。ドリフト検出を提供するリソースタイプごとに、開始する定義として使用するための一つ以上の既定のテンプレートが存在します。
+view_drift_wizard_addDef_infoStepName = その新規ドリフト検出定義のテンプレートを選択してください
+view_drift_wizard_addDef_success = 新規ドリフト検出定義 [{0}] の追加に成功しました。エージェントは更新されます。
+view_drift_wizard_addDef_templatePrompt = ドリフト定義テンプレート
+view_drift_wizard_addDef_title = タイプのリソース [{0}] のためのドリフト検出定義を追加してください
+view_drift_wizard_addDef_windowTitle = ドリフト検出定義ウィザードの追加
+view_drift_wizard_addTemplate_failure = 新規ドリフト検出テンプレート [{0}] の追加に失敗しました
+view_drift_wizard_addTemplate_infoStepHelp = 各ドリフトテンプレートは既存のテンプレートから派生して作成できます。これは既存テンプレートに類似したものや、プラグインが定義したテンプレートから新規テンプレートを構築する素早い方法を提供します。ドリフト定義のように、そのテンプレートはドリフトを監視を実行する一式のファイルを記述します。状況によっては、そのテンプレートから導出された定義はそのファイルセットの変更や、他の設定の変更を許したり、許さなかったりします。テンプレート名は一つのリソースタイプ内でユニークでなければなりません。
+view_drift_wizard_addTemplate_infoStepName = 開始テンプレートの選択
+view_drift_wizard_addTemplate_success = 新規ドリフトテンプレート [{0}] の追加に成功しました
+view_drift_wizard_addTemplate_title = タイプ [{0}] のドリフト定義テンプレートを追加してください
+view_drift_wizard_addTemplate_windowTitle = ドリフト定義テンプレート定義テンプレートウィザードの追加
+view_drift_wizard_pinTemplate_confirmNotPinned = そのテンプレートのための現在と将来の各ドリフト定義がいったんピン留めされると、そのテンプレートはその初期スナップショットがテンプレートのピン留めされたスナップショットとして設定されるようにします。このテンプレートの既存の定義は新規の初期スナップショットへリセットされます。このテンプレートの既存定義は新規初期スナップショットへリセットされ、すべての既存スナップショットは削除されます。そのスナップショットへのテンプレートのピン留めを続けますか?
+view_drift_wizard_pinTemplate_confirmPinned = 警告! このテンプレートはすでにピン留めされています。そのテンプレートはこの新規スナップショットに再度ピン留めすることが可能です。そのテンプレートのための現在と将来の各ドリフト定義がいったんピン留めされると、そのテンプレートは初期スナップショットがそのテンプレートが持つピン留めされたスナップショットとして設定されるようにします。このテンプレートの既存定義は新規初期スナップショットへリセットされ、すべての既存スナップショットは削除されます。この新規スナップショットを持つテンプレートのピン留めを続けますか?
+view_drift_wizard_pinTemplate_failure = ドリフトテンプレート [{0}] へのスナップショットをピン留めするのに失敗しました
+view_drift_wizard_pinTemplate_infoStepExistingTemplate = 現在のテンプレートへのピン留め
+view_drift_wizard_pinTemplate_infoStepHelp = ピン留めをするテンプレートを選択してください。そのテンプレートのための現在と将来の各ドリフト定義がいったんピン留めされると、そのテンプレートは初期スナップショットがそのテンプレートが持つピン留めされたスナップショットとして設定された持つようになりまするようにします。そしてその定義自身はピン留めされたものとしてマークされます。これは期待されるファイルセットからドリフトを検出するのに使われます。このテンプレートのための既存定義は新規の初期スナップショットにリセットされ、すべての既存スナップショットは削除されることに注意してください。
+view_drift_wizard_pinTemplate_infoStepName = ピン留めされるテンプレートの選択
+view_drift_wizard_pinTemplate_infoStepNewTemplate = 新規テンプレートへのピン留め (スナップショットのドリフト定義から導出されたもの)
+view_drift_wizard_pinTemplate_infoStepRadioHelp = そのスナップショットは新規または既存のドリフトテンプレートにピン留めすることが可能です。その''新規テンプレート''オプションは、ユーザーの手によって信頼する定義やスナップショットを、リソースレベルやタイプレベルで、テンプレート化できるようにします。その新規テンプレートは、次に、そのタイプのメンバーに対して適用できます。その新規テンプレートは初期時はスナップショットのドリフト定義のコピーですが、次のステップで編集することができます。その名前は変更すべきで、そのタイプのユニークなドリフトテンプレート名でなければなりません。''既存テンプレート''オプションは、ユーザーが選択したスナップショットを持つ既存テンプレートに対して、ピン留めまたは再度ピン留めができるようにします。正しく設定するには、その既存テンプレートは同じディレクトリをそのスナップショット定義として監視できなければなりません。セレクションボックスは正当な既存のテンプレートだけを表示します。もし正当でない既存テンプレートが存在したとしてもこのオプションでは選択されません。
+view_drift_wizard_pinTemplate_infoStepRadioTitle = テンプレートの選択
+view_drift_wizard_pinTemplate_infoStepSelectBlocked = 既存テンプレートでスナップショットの定義と同じディレクトリを監視するものは存在しません。継続するに''新規テンプレート''オプションを選択してください。
+view_drift_wizard_pinTemplate_infoStepSelectTitle = 既存テンプレート
+view_drift_wizard_pinTemplate_success = ドリフトテンプレート [{0}] のピン留めに成功しました
+view_drift_wizard_pinTemplate_title = タイプ [{2}] のドリフトテンプレートへの定義 [{1}] のスナップショット [{0}] をピン留め
+view_drift_wizard_pinTemplate_windowTitle = ドリフト定義テンプレートウィザードのピン留め
view_dynagroup_children = 動的グループの子
-view_dynagroup_compatible = Compatible
+view_dynagroup_compatible = 互換
view_dynagroup_definitionAlreadyExists = すでにこの名前のグループ定義が存在します
view_dynagroup_definitionCreated = グループ定義名 [{0}] の作成に成功しました
view_dynagroup_definitionLoadFailure = グループ定義のロードに失敗しました
@@ -1299,6 +1297,7 @@ view_dynagroup_exprBuilder_resource_greatGreatGrandparent = 曾祖父母の親
view_dynagroup_exprBuilder_resource_parent = 親
view_dynagroup_exprBuilder_resource_resource = リソース
view_dynagroup_exprBuilder_resource_tooltip = リソースのレベルを望みのものに選択してください。例えば、"親"を選択すると、親リソースが式の残りの部分に一致するようなリソースを発見できます。
+view_dynagroup_exprBuilder_savedExpression = 保存された式
view_dynagroup_exprBuilder_title = 式ビルダー
view_dynagroup_exprBuilder_unset = 設定解除
view_dynagroup_exprBuilder_unset_tooltip = 設定解除はデータベース内のnull値を持つ値をのすべてを発見します。これはデータベースストアと問い合わせデータの理由により"="オペレータを使うことは可能ではありません。
@@ -1336,17 +1335,16 @@ view_dynagroup_template_platforms = インベントリ内のプラットフォ
view_dynagroup_template_uniqueResourceTypes = インベントリ内のユニークリソースタイプ
view_groupConfigEdit_member = メンバー
view_groupConfigEdit_noListProps = グループ構成に現在サポートされていないプロパティのリスト
-##view_groupConfigEdit_saveReminder = You changed some settings - do not forget to save those changes or they will be lost.\n
+view_groupConfigEdit_saveReminder = 設定が変更されています - これらの変更を保存するのを忘れないでください。さもないと失われます。
view_groupConfigEdit_setAll = すべての値を設定:
view_groupConfigEdit_tooltip_1 = メンバー値の違い - 編集するためにアイコンをクリックします
view_groupConfigEdit_unset = 設定解除
view_groupConfigEdit_valsDiff = メンバー値の違い
view_groupConfigEdit_valsDiffForProp = プロパティ [{0}] のためのメンバー値
-view_groupCreateWizard_createFailure = リソースグループの作成に失敗しました [{0}] : {1}
+## view_groupCreateWizard_createFailure = リソースグループの作成に失敗しました
view_groupCreateWizard_createStepName = グループ設定
-##view_groupCreateWizard_createStep_group_exists = Group with name [{0}] already exists
view_groupCreateWizard_createStep_recursive = 再帰
-##view_groupCreateWizard_createSuccessful_concise = 新規のリソースグループを作成しました。[{0}]
+## view_groupCreateWizard_createSuccessful_concise = 新規のリソースグループを作成しました。
view_groupCreateWizard_createSuccessful_full = [{2}] メンバーリソースを含む 名前 [{1}] の新規 [{0}] リソースグループを作成しました。
view_groupCreateWizard_membersStepName = メンバーの選択
view_groupCreateWizard_title = グループ作成
@@ -1399,7 +1397,7 @@ view_group_pluginConfig_table_title = グループコネクション設定履歴
view_group_pluginConfig_table_viewMemberHistory = メンバー履歴の閲覧
view_group_pluginConfig_table_viewSettings = 設定の閲覧
view_group_pluginConfig_view_groupProperties = グループプロパティ
-view_group_pluginConfig_view_noperm = コネクション設定を見る権限がありません
+view_group_pluginConfig_view_noperm = コネクション設定の閲覧権限がありません
view_group_resConfig_edit_invalid = 次の構成プロパティは不正な値を含むのでその構成を保存する前に修正されなければなりません: [{0}]
view_group_resConfig_edit_loadFail = [{0}] のためのメンバーリソース構成を取り出すのに失敗しました
view_group_resConfig_edit_noperm = このグループ構成を編集する権限がありません
@@ -1410,7 +1408,7 @@ view_group_resConfig_edit_saveTooltip = すべてのグループメンバーの
view_group_resConfig_edit_valid = すべての構成プロパティは正しい値ですので、その構成は保存可能です
view_group_resConfig_members_fetchFailure = グループ [{0}] のメンバーのためのリソース構成更新履歴の取得に失敗しました
view_group_resConfig_members_fetchFailureConfig = [{0}] のためのメンバーリソース構成設定の取り出しに失敗しました
-view_group_resConfig_members_fetchFailureConfigInProgress = グループリソース構成の更新が現在進行中です。グループ設定を見る前に更新が終了するのをお待ちください
+view_group_resConfig_members_fetchFailureConfigInProgress = グループリソース構成の更新が現在進行中です。グループ設定を閲覧する前に更新が終了するのをお待ちください
view_group_resConfig_members_statusDetails = ステータスの詳細
view_group_resConfig_members_statusFailure = この構成の更新は未知の理由で失敗しました。
view_group_resConfig_members_statusInprogress = この構成の更新はまだ進行中です
@@ -1431,7 +1429,7 @@ view_group_resConfig_table_title = グループリソース構成履歴
view_group_resConfig_table_viewMemberHistory = メンバー履歴の閲覧
view_group_resConfig_table_viewSettings = 閲覧設定
view_group_resConfig_view_groupProperties = グループプロパティ
-view_group_resConfig_view_noperm = リソース構成設定を見るための権限はありません
+view_group_resConfig_view_noperm = リソース構成設定を閲覧するための権限はありません
view_group_summary_compatible = 互換性
view_group_summary_descUpdateFailure = ID [{0}] を持つリソースグループの説明を変更できませんでした
view_group_summary_descUpdateSuccessful = このリソースグループの説明を変更しました
@@ -1475,10 +1473,10 @@ view_inventory_groups_loadFailed = グループ合成データのロードに失
view_inventory_mixed = 混成
view_inventory_platforms = プラットフォーム
view_inventory_problemGroups = 問題グループ
-view_inventory_resource_loadFailed = ID [{0}] をT持つリソースは存在しないか、アクセスできません
+view_inventory_resource_loadFailed = ID [{0}] を持つリソースは存在しないか、アクセスできません
view_inventory_resources_deleteConfirm = 選択されたリソースを削除したいですか?
view_inventory_resources_deleteFailed = 選択されたリソースの削除に失敗しました
-##view_inventory_resources_deleteSuccessful = A request to perform the resource deletion has been submitted successfully to the agent(s).
+view_inventory_resources_deleteSuccessful = そのリソースを削除するリクエストは(複数の)エージェントに正しく送信されました。
view_inventory_resources_loadFailed = リソース合成データのロードに失敗しました
view_inventory_resources_members = メンバーリソース
view_inventory_resources_uninventoryConfirm = 選択したリソースをアンインベントリしてもよろしいですか? もし選択したリソースがまだ存在しているなら、そのエージェントの次回のディスカバリスキャンの間にそれは再発見されます。
@@ -1489,7 +1487,7 @@ view_inventory_servers = サーバー
view_inventory_services = サービス
view_inventory_summary_agent_error1 = エージェント管理リソースIDの発見に失敗しました
view_inventory_summary_agent_error2 = エージェントリソースIDのpingに失敗しました
-view_inventory_summary_agent_error3 = このエージェントのための詳細を見る権限がありません
+view_inventory_summary_agent_error3 = このエージェントのための詳細を閲覧する権限がありません
view_inventory_summary_agent_fullEnpoint = フルエンドポイント
view_inventory_summary_agent_fullEnpoint_err1 = !このリソースに関連するリモートエンドポイントはありません!
view_inventory_summary_agent_last_title = 最後に受信したアベイラビリティリポート
@@ -1507,7 +1505,7 @@ view_login_prompt = ログインしてください
view_login_registerLater = (キャンセル - 登録を後で完成させてください)
view_login_registerLdapSuccess = 新しいLDAPユーザーの登録に成功しました
view_login_registerUser = ユーザの登録
-##view_login_welcomeMsg = RHQへようこそ! <br/><br/> 登録を完成させるために次のフィールドを入力/更新してください。<br/> "OK"をクリックしたら、ログインします。<br/><br/>
+## view_login_welcomeMsg = RHQへようこそ! <br/><br/> 登録を完成させるために次のフィールドを入力/更新してください。<br/> "OK"をクリックしたら、ログインします。<br/><br/>
view_measureRange_last = 時間の範囲 - 直前
view_measureRange_simple = シンプル...
view_measureRange_start = 時間の範囲 - 開始
@@ -1535,7 +1533,7 @@ view_operationHistoryDetails_dateSubmitted = 発行日
view_operationHistoryDetails_error_fetchFailure = オペレーション履歴のロードに失敗
view_operationHistoryDetails_noResults = このオペレーションは値を返しません
view_operationHistoryDetails_operation = オペレーション
-view_operationHistoryDetails_parameters = パラメータ
+view_operationHistoryDetails_parameters = パラメーター
view_operationHistoryDetails_requestor = 要求者
view_operationHistoryDetails_results = 結果
view_operationHistoryDetails_status = ステータス
@@ -1545,11 +1543,11 @@ view_operationHistoryList_notYetStarted = まだ開始していません
view_operationHistoryList_title = オペレーション履歴
view_operationScheduleDetails_enterParametersBelow = 以下にパラメーターを入力してください...
view_operationScheduleDetails_fieldDefault_description = 説明を見るとためオペレーションを選択してください
-view_operationScheduleDetails_fieldDefault_parameters = パラメーターを見るためオペレーションを選択してください
+view_operationScheduleDetails_fieldDefault_parameters = パラメーターを見るためにオペレーションを選択してください
view_operationScheduleDetails_fieldHelp_description = このスケジュールされたオペレーションのための任意の説明 (例、夜間保守のためのアプリサーバー再起動)
-##view_operationScheduleDetails_fieldHelp_timeout = 時間間隔 - もし指定されていて、その間隔がスケジュールされたオペレーション実行が完了する前に経過してしまったならば、RHQサーバーはそのオペレーションをタイムアウトにし、それを失敗させることを検討します。注意:通常はすでに開始させられた根本の管理リソースオペレーションをアボートすることは不可能です。
+## view_operationScheduleDetails_fieldHelp_timeout = 時間間隔 - もし指定されていて、その間隔がスケジュールされたオペレーション実行が完了する前に経過してしまったならば、RHQサーバーはそのオペレーションをタイムアウトにし、それを失敗させることを検討します。注意:通常はすでに開始させられた根本の管理リソースオペレーションをアボートすることは不可能です。
view_operationScheduleDetails_field_description = 説明
-view_operationScheduleDetails_field_parameters = パラメータ
+view_operationScheduleDetails_field_parameters = パラメーター
view_operationScheduleDetails_field_timeout = タイムアウト
view_operationScheduleDetails_noParameters = このオペレーションはパラメーターを取りません
view_operationScheduleDetails_operationSchedule = オペレーションスケジュール
@@ -1668,7 +1666,6 @@ view_reportsTop_title = レポート
view_reports_alertDefinitions = アラート定義
view_reports_alertDefinitions_parentHover = クリックすると親のアラート定義へ行きます
view_reports_alertDefinitions_resTypeLoadError = テンプレートリソースタイプを取得できません - アラートテンプレートの閲覧ができません
-##view_reports_driftCompliance = Drift Compliance
view_reports_inventorySummary_failFetch = インベントリサマリーの取得に失敗しました
view_reports_platforms = プラットフォーム利用率
view_reports_subsystems = サブシステム
@@ -1708,22 +1705,22 @@ view_resource_monitor_graphs_lookupFailed = グラフのためのリソースの
view_resource_monitor_graphs_noneAvailable = 利用できるグラフはありません
view_resource_monitor_schedules_title = リソースメトリック収集スケジュール
view_resource_monitor_table_avg = 平均
-view_resource_monitor_table_last = 最後
+view_resource_monitor_table_last = 最新
view_resource_monitor_table_max = 最大
view_resource_monitor_table_min = 最小
view_resource_title_component_errors_tooltip = 管理コンポーネントエラーの表示。詳細はクリックしてください
view_resource_title_tagUpdateFailed = リソースタグの更新に失敗しました
view_searchBar_defaultPattern = パターンを名前を付けてください
-##view_searchBar_instructional_failSuggest = Failed to generate suggestions, see server log for possible errors
-view_searchBar_instructional_noSuggest = No matches, enter a different pattern
-##view_searchBar_instructional_refresh = Failed to retrieve saved searches, please refresh page
-##view_searchBar_savedSearch_delete = Successfully deleted saved search [{0}]
-##view_searchBar_savedSearch_failDelete = Failed to delete saved search with name [{0}]
-##view_searchBar_savedSearch_failFind = Failed to find saved search with name [{0}]
-##view_searchBar_savedSearch_failRename = Failed to rename saved search with name [{0}]
-##view_searchBar_savedSearch_failSave = Failed to create saved search with name [{0}]
-##view_searchBar_savedSearch_rename = Successfully renamed saved search to [{0}]
-##view_searchBar_savedSearch_save = Successfully created saved search [{0}]
+view_searchBar_instructional_failSuggest = サジェッションの作成に失敗しました。可能性のあるエラーをサーバーログから調べてください。
+view_searchBar_instructional_noSuggest = 一件も一致しませんでした。異なるパターンを入力してください。
+view_searchBar_instructional_refresh = 保存済みの検索の取り出しに失敗しました。ページをリフレッシュしてください。
+view_searchBar_savedSearch_delete = 保存済みの検索 [{0}] を削除するのに失敗しました
+view_searchBar_savedSearch_failDelete = [{0}]という名前の保存済み検索を削除するのに失敗しました
+view_searchBar_savedSearch_failFind = [{0}]という名前の保存済み検索を検索するのに失敗しました
+view_searchBar_savedSearch_failRename = [{0}]という名前の保存済みの検索の名前を変更するのに失敗しました
+view_searchBar_savedSearch_failSave = [{0}]という名前の保存済みの検索を作成するのに失敗しました
+view_searchBar_savedSearch_rename = 保存済み検索の名前を [{0}] へ変更するのに成功しました
+view_searchBar_savedSearch_save = [{0}] という名前の保存済み検索を作成するのに成功しました
view_searchGUI_loginStatus = ログインステータスが確定できません。サーバーの状態を調べてください
view_selector_assigned = 割り当てられた {0}
view_selector_available = 利用可能な {0}
@@ -1752,6 +1749,7 @@ view_tableSection_error_noId = テーブル [{0}] のレコードがで 'id' 属
view_table_drawFail = テーブル [{0}] の描画に失敗しました.
view_table_matchingRows = 一致した行: {0} (選択済み: {1})
view_table_totalRows = 合計行: {0} (選択済み: {1})
+view_table_totalRowsUnknown = 行の合計: ?
view_tabs_common_activity = アクティビティ
view_tabs_common_agent = エージェント
view_tabs_common_availability = アベイラビリティ
@@ -1764,7 +1762,7 @@ view_tabs_common_content = コンテント
view_tabs_common_current = 現在
view_tabs_common_dashboard = ダッシュボード
view_tabs_common_deployed = デプロイ済み
-##view_tabs_common_drift = Drift
+view_tabs_common_drift = ドリフト
view_tabs_common_events = イベント
view_tabs_common_graphs = グラフ
view_tabs_common_group_members = グループメンバー
@@ -1921,7 +1919,7 @@ widget_resourceFactoryWizard_infoStepName = リソース情報
widget_resourceFactoryWizard_infoStep_loadFail = アーキテクチャーを利用可能にするのに失敗しました
widget_resourceFactoryWizard_namePrompt = 新規リソース名
widget_resourceFactoryWizard_templatePrompt = コネクション設定テンプレート
-##widget_resourceFactoryWizard_timeoutHelp = xxxxxxx
+## widget_resourceFactoryWizard_timeoutHelp = タイムアウト間隔。もし指定されたならば(RHQエージェント上での)子のリソース作成のためのデフォルトタイムアウトを上書きします。大きなアプリケーションのデプロイのような長時間かかる作成アクションに特に有用です。通常、前回の試みのときにタイムアウトの失敗だった場合に使われます。
widget_resourceFactoryWizard_uploadFailure = ファイルアップロードの失敗
widget_resourceFactoryWizard_uploadFileStepName = リソースコンテントファイルのアップロード
widget_resourceFactoryWizard_uploadInProgress = アップロードは処理中です... 大きなファイルを配布するには数分かかることもあります。
commit 0753aae5cab0a3abd3997d093dad1d4866091619
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Fri Dec 9 16:37:56 2011 -0500
[BZ 754693] ensure load of lazy references and update LDAP role relationship purge.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java
index ec3e998..6413b89 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java
@@ -22,7 +22,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -183,18 +182,27 @@ public class RoleManagerBean implements RoleManagerLocal, RoleManagerRemote {
for (int roleId : doomedRoleIds) {
Role doomedRole = entityManager.find(Role.class, roleId);
+ //remove attached Subjects
Set<Subject> subjectsToUnhook = new HashSet<Subject>(doomedRole.getSubjects()); // avoid concurrent mod exception
for (Subject doomedSubjectRelationship : subjectsToUnhook) {
doomedRole.removeSubject(doomedSubjectRelationship);
entityManager.merge(doomedSubjectRelationship);
}
+ //remove attached ResourceGroups
Set<ResourceGroup> groupsToUnhook = new HashSet<ResourceGroup>(doomedRole.getResourceGroups()); // avoid concurrent mod exception
for (ResourceGroup doomedResourceGroupRelationship : groupsToUnhook) {
doomedRole.removeResourceGroup(doomedResourceGroupRelationship);
entityManager.merge(doomedResourceGroupRelationship);
}
+ //remove attached LDAP Subjects
+ Set<Subject> ldapSubjectsToUnhook = new HashSet<Subject>(doomedRole.getLdapSubjects()); // avoid concurrent mod exception
+ for (Subject doomedLdapSubjectRelationship : ldapSubjectsToUnhook) {
+ doomedRole.removeLdapSubject(doomedLdapSubjectRelationship);
+ entityManager.merge(doomedLdapSubjectRelationship);
+ }
+
doomedRole = entityManager.merge(doomedRole);
if (doomedRole.getFsystem()) {
@@ -202,7 +210,13 @@ public class RoleManagerBean implements RoleManagerLocal, RoleManagerRemote {
}
alertNotificationManager.cleanseAlertNotificationByRole(doomedRole.getId());
- entityManager.remove(doomedRole); // there should not be any cascading - this does not touch subjects/groups
+ // Fetch the lazy Sets on the Role to be returned.
+ //[BZ 754693:] we must fetch the lazy sets of LDAP Groups here for correct cascade removal
+ doomedRole.getResourceGroups().size();
+ doomedRole.getSubjects().size();
+ doomedRole.getLdapGroups().size();
+
+ entityManager.remove(doomedRole);
}
}
@@ -432,8 +446,8 @@ public class RoleManagerBean implements RoleManagerLocal, RoleManagerRemote {
}
for (LdapGroup ldapGroup : newLdapGroups) {
- LdapGroup attachedLdapGroup = (ldapGroup.getId() != 0) ?
- entityManager.find(LdapGroup.class, ldapGroup.getId()) : null;
+ LdapGroup attachedLdapGroup = (ldapGroup.getId() != 0) ? entityManager.find(LdapGroup.class,
+ ldapGroup.getId()) : null;
if (attachedLdapGroup == null) {
ldapGroup.setRole(attachedRole);
entityManager.persist(ldapGroup);
@@ -669,8 +683,8 @@ public class RoleManagerBean implements RoleManagerLocal, RoleManagerRemote {
+ "], but subject was not found");
}
if (doomedSubject.getFsystem() || (authorizationManager.isSystemSuperuser(doomedSubject))) {
- throw new PermissionException("You cannot remove user[" + doomedSubject.getName()
- + "] from role[" + roleId + "] - roles are fixed for this user");
+ throw new PermissionException("You cannot remove user[" + doomedSubject.getName() + "] from role["
+ + roleId + "] - roles are fixed for this user");
}
role.removeSubject(doomedSubject);
}
@@ -768,7 +782,7 @@ public class RoleManagerBean implements RoleManagerLocal, RoleManagerRemote {
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
CriteriaQueryRunner<Role> queryRunner = new CriteriaQueryRunner<Role>(criteria, generator, entityManager);
- @SuppressWarnings({"UnnecessaryLocalVariable"})
+ @SuppressWarnings({ "UnnecessaryLocalVariable" })
PageList<Role> roles = queryRunner.execute();
return roles;
commit cfe30b134dd06cca8d22c0eacdc994a6021a73f4
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri Dec 9 14:21:28 2011 -0500
[Bug 755580 - Unable to add 2nd file-system drift]
The drift definition name and description are no longer preset to the
template name and description. The user will now need to enter a
name. This should help prevent duplicate names, or mistakenly using the
template's name. Also, the exception thrown on duplicate naming has
been updated to indicate that that may in fact be the problem.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftAddDefinitionWizardInfoStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftAddDefinitionWizardInfoStep.java
index c7ad7ed..c2139c1 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftAddDefinitionWizardInfoStep.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftAddDefinitionWizardInfoStep.java
@@ -36,6 +36,7 @@ import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
+import org.rhq.core.domain.drift.DriftConfigurationDefinition;
import org.rhq.core.domain.drift.DriftDefinitionTemplate;
import org.rhq.enterprise.gui.coregui.client.components.wizard.AbstractWizardStep;
import org.rhq.enterprise.gui.coregui.client.util.FormUtility;
@@ -130,7 +131,11 @@ public class DriftAddDefinitionWizardInfoStep extends AbstractWizardStep {
DriftDefinitionTemplate selectedTemplate = templatesMap.get(key);
wizard.setSelectedTemplate(selectedTemplate);
- wizard.setNewStartingConfiguration(selectedTemplate.createConfiguration());
+ Configuration startingConfig = selectedTemplate.createConfiguration();
+ // don't propogate the template name or desc to the def, force the user to enter a name, and optionally, a def
+ startingConfig.remove(DriftConfigurationDefinition.PROP_NAME);
+ startingConfig.remove(DriftConfigurationDefinition.PROP_DESCRIPTION);
+ wizard.setNewStartingConfiguration(startingConfig);
String description = selectedTemplate.getDescription();
description = (null == description) ? MSG.common_val_none() : description;
form.getItem("Description").setValue(description);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerBean.java
index 6af05d9..c06f7a4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftManagerBean.java
@@ -589,12 +589,13 @@ public class DriftManagerBean implements DriftManagerLocal, DriftManagerRemote {
}
try {
- AgentClient agent = agentManager.getAgentClient(subjectManager.getOverlord(), driftDef.getResource().getId());
+ AgentClient agent = agentManager.getAgentClient(subjectManager.getOverlord(), driftDef.getResource()
+ .getId());
DriftAgentService driftService = agent.getDriftAgentService();
driftService.pinSnapshot(driftDef.getResource().getId(), driftDef.getName(), snapshot);
} catch (Exception e) {
- log.warn("Unable to notify agent that DriftDefinition[driftDefinitionId: " + driftDefId +
- ", driftDefinitionName: " + driftDef.getName() + "] has been pinned. The agent may be down.", e);
+ log.warn("Unable to notify agent that DriftDefinition[driftDefinitionId: " + driftDefId
+ + ", driftDefinitionName: " + driftDef.getName() + "] has been pinned. The agent may be down.", e);
}
}
@@ -745,7 +746,7 @@ public class DriftManagerBean implements DriftManagerLocal, DriftManagerRemote {
break;
} else {
throw new IllegalArgumentException(
- "You cannot change an existing drift definition's base directory or includes/excludes filters.");
+ "A new definition must have a unique name. An existing definition cannot update it's base directory or includes/excludes filters.");
}
}
}
commit 5938a790c0aeb32865f4b115e721de22220ca100
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri Dec 9 14:05:05 2011 -0500
[Bug 765592 - drift diff is different depending on order in which files are selected]
Fixed, the new changes will now always get the "+" prefixes and the older
will get the "-" prefixes.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java
index f941c6f..b3de83f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java
@@ -267,11 +267,18 @@ public class DriftCarouselView extends BookmarkableCarousel implements DetailsVi
public void executeAction(Object actionValue) {
- String id1 = selectedRecords.get(0).getAttribute(DriftDataSource.ATTR_ID);
- String id2 = selectedRecords.get(1).getAttribute(DriftDataSource.ATTR_ID);
- final String path = selectedRecords.get(0).getAttribute(DriftDataSource.ATTR_PATH);
-
- GWTServiceLookup.getDriftService().generateUnifiedDiffByIds(id1, id2,
+ Record record1 = selectedRecords.get(0);
+ Record record2 = selectedRecords.get(1);
+ final String path = record1.getAttribute(DriftDataSource.ATTR_PATH);
+ String id1 = record1.getAttribute(DriftDataSource.ATTR_ID);
+ String id2 = record2.getAttribute(DriftDataSource.ATTR_ID);
+ // regardless of selection order, compare the same way, showing newest changes with '+' signs
+ int version1 = record1.getAttributeAsInt(DriftDataSource.ATTR_CHANGESET_VERSION);
+ int version2 = record2.getAttributeAsInt(DriftDataSource.ATTR_CHANGESET_VERSION);
+ String diffOldId = (version1 < version2) ? id1 : id2;
+ String diffNewId = (version1 < version2) ? id2 : id1;
+
+ GWTServiceLookup.getDriftService().generateUnifiedDiffByIds(diffOldId, diffNewId,
new AsyncCallback<FileDiffReport>() {
@Override
public void onFailure(Throwable caught) {
commit 84c83f8760f6f37f7b7eed1b5e27346691901c11
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri Dec 9 14:03:21 2011 -0500
[Bug 755673 - Adding new drift: includes/excludes - Path property required?]
It's now optional. It will be set to "." by default in the GUI. But even
if omitted will again get set to "." at the lower levels.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftConfigurationDefinition.java b/modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftConfigurationDefinition.java
index 9829480..2b21f03 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftConfigurationDefinition.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftConfigurationDefinition.java
@@ -519,8 +519,8 @@ public class DriftConfigurationDefinition implements Serializable {
private static PropertyDefinitionSimple createIncludePath(boolean readOnly) {
String name = PROP_PATH;
- String description = "A file system path that can be a directory or a file. The path is assumed to be relative to the base directory of the drift definition.";
- boolean required = true;
+ String description = "A file system directory path that is relative to (a sub-directory of) the base directory of the drift definition. The default is '.', the base directory itself.";
+ boolean required = false;
PropertySimpleType type = PropertySimpleType.STRING;
PropertyDefinitionSimple pd = new PropertyDefinitionSimple(name, description, required, type);
@@ -529,6 +529,7 @@ public class DriftConfigurationDefinition implements Serializable {
pd.setSummary(true);
pd.setOrder(0);
pd.setAllowCustomEnumeratedValue(false);
+ pd.setDefaultValue(".");
RegexConstraint constraint = new RegexConstraint();
constraint.setDetails(PROP_FILTER_PATH_REGEX_PATTERN);
@@ -539,7 +540,7 @@ public class DriftConfigurationDefinition implements Serializable {
private static PropertyDefinitionSimple createIncludePattern(boolean readOnly) {
String name = PROP_PATTERN;
- String description = "Pathname pattern that must match for the items in the directory path to be included. '*' matches zero or more characters, '?' matches one character. For example, '*.txt' (no quotes) will match text files in the filter's path directory. '**/*.txt' will match text files in any subdirectory below the filter's path directory";
+ String description = "Pathname pattern that must match for the items in the directory path to be included. '*' matches zero or more characters, '?' matches one character. For example, '*.txt' (no quotes) will match text files in the filter's path directory. '**/*.txt' will match text files in any subdirectory below the filter's path directory.";
boolean required = false;
PropertySimpleType type = PropertySimpleType.STRING;
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftDefinition.java b/modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftDefinition.java
index a104843..92015ab 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftDefinition.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftDefinition.java
@@ -149,7 +149,7 @@ public class DriftDefinition implements Serializable {
name = (null != name) ? name.trim() : name;
if (null == name || "".equals(name)) {
- throw new IllegalArgumentException("Drift congig name can not be null or empty");
+ throw new IllegalArgumentException("Drift definition name can not be null or empty");
}
this.name = name;
@@ -534,7 +534,7 @@ public class DriftDefinition implements Serializable {
List<Filter> filters = new ArrayList<Filter>();
for (Property property : filtersListProperty.getList()) {
PropertyMap filter = (PropertyMap) property;
- filters.add(new Filter(filter.getSimpleValue(DriftConfigurationDefinition.PROP_PATH, ""), filter
+ filters.add(new Filter(filter.getSimpleValue(DriftConfigurationDefinition.PROP_PATH, "."), filter
.getSimpleValue(DriftConfigurationDefinition.PROP_PATTERN, "")));
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/drift/Filter.java b/modules/core/domain/src/main/java/org/rhq/core/domain/drift/Filter.java
index 96797ca..b57eb32 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/drift/Filter.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/drift/Filter.java
@@ -42,7 +42,7 @@ public class Filter implements Serializable {
public void setPath(String path) {
if (path == null) {
- this.path = "";
+ this.path = ".";
} else {
this.path = path;
}
commit e8db9a190cdf7a1e070bbc077a4d025e30835a24
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Dec 8 16:02:39 2011 -0500
Add 2.117 to remove an obsolete drift table that may exist after upgrades.
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index 85a5526..3350cdd 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -15,7 +15,7 @@
<description>Database schema setup, upgrade and other utilities</description>
<properties>
- <db.schema.version>2.116</db.schema.version>
+ <db.schema.version>2.117</db.schema.version>
<rhq.ds.type-mapping>${rhq.test.ds.type-mapping}</rhq.ds.type-mapping>
<rhq.ds.db-name>${rhq.test.ds.db-name}</rhq.ds.db-name>
<rhq.ds.connection-url>${rhq.test.ds.connection-url}</rhq.ds.connection-url>
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 92ebef7..9e3bbd6 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -3823,7 +3823,12 @@
</schemaSpec>
<!-- JON 3.0 RELEASE uses DB Schema 2.116 -->
-
+
+ <schemaSpec version="2.117">
+ <!-- Remove an obsolete drift table that may be hanging around -->
+ <schema-dropTable table="RHQ_DRIFT_TEMPLATE_MAP" />
+ </schemaSpec>
+
</dbupgrade>
</target>
</project>
commit dedfe6ad8738d1be1c5a411943e4e48d4410ffd2
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Dec 8 15:28:14 2011 -0500
[Bug 753866 - DB Upgrade needs more work for existing drift records]
More work to support 4.1 and 4.2 upgrades for drift.
- In the java template map upgrade task
- add logic to generate the rhq_drift_def_template records
- add logic to generate rhq_drift_set records for each initial changeset
- Move some logic from 2.115 to 2.116 to make 2.115 match the
schema produced by a 4.2 dbsetup (fresh db). Note that prior to
an upgrade 4.2 databases must (for now at least) be manually set
to schema version 2.115. They are errantly set to 2.114 in the 4.2
release.
diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DriftTemplateMapDatabaseUpgradeTask.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DriftTemplateMapDatabaseUpgradeTask.java
index d060a2a..95d9ef7 100644
--- a/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DriftTemplateMapDatabaseUpgradeTask.java
+++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DriftTemplateMapDatabaseUpgradeTask.java
@@ -20,6 +20,7 @@ package org.rhq.core.db.upgrade;
import java.sql.Connection;
import java.sql.SQLException;
+import java.util.List;
import mazz.i18n.Logger;
@@ -39,6 +40,8 @@ public class DriftTemplateMapDatabaseUpgradeTask implements DatabaseUpgradeTask
public void execute(DatabaseType databaseType, Connection connection) throws SQLException {
+ // First generate a drift def template for each of the existing mappings
+
String sql = "" //
+ " insert into RHQ_DRIFT_DEF_TEMPLATE (" //
+ " ID," //
@@ -61,5 +64,53 @@ public class DriftTemplateMapDatabaseUpgradeTask implements DatabaseUpgradeTask
LOG.debug(DbUtilsI18NResourceKeys.EXECUTING_SQL, sql);
databaseType.executeSql(connection, sql);
+
+ // Second, assign one of the new templates to each of the existing definitions. Note that in the
+ // upgrade scenario we are guaranteed to only have 1 template for the given resource type so the
+ // select below is safe to return a single value.
+ sql = "" //
+ + " update RHQ_DRIFT_DEFINITION dd set DRIFT_DEF_TEMPLATE_ID =" //
+ + " ( select dt.ID" //
+ + " from RHQ_DRIFT_DEF_TEMPLATE dt" //
+ + " join RHQ_RESOURCE_TYPE rt on dt.RESOURCE_TYPE_ID = rt.ID" //
+ + " join RHQ_RESOURCE res on rt.ID = res.RESOURCE_TYPE_ID" //
+ + " and dd.RESOURCE_ID = res.ID" //
+ + " )" //
+ + " where dd.DRIFT_DEF_TEMPLATE_ID is null";
+
+ LOG.debug(DbUtilsI18NResourceKeys.EXECUTING_SQL, sql);
+
+ databaseType.executeSql(connection, sql);
+
+ // third, for each initial snapshot, create the newly required rhq_drift_set and map the drift to it
+ sql = "select cs.ID from RHQ_DRIFT_CHANGE_SET cs where cs.VERSION = 0";
+ LOG.debug(DbUtilsI18NResourceKeys.EXECUTING_SQL, sql);
+
+ List<Object[]> rows = databaseType.executeSelectSql(connection, sql);
+
+ sql = "insert into RHQ_DRIFT_SET ( ID ) values ( "
+ + databaseType.getSequenceInsertValue(connection, "RHQ_DRIFT_SET_ID_SEQ") + " )";
+
+ for (Object[] row : rows) {
+ int csId = ((Number) row[0]).intValue();
+
+ // insert the new drift set row
+ LOG.debug(DbUtilsI18NResourceKeys.EXECUTING_SQL, sql);
+
+ databaseType.executeSql(connection, sql);
+ int setId = databaseType.getSequenceValue(connection, "RHQ_DRIFT_SET", "ID");
+
+ // update the drift records for the initial change set to refer to the drift set
+ String updateSql = "update RHQ_DRIFT set DRIFT_SET_ID = " + setId + " where DRIFT_CHANGE_SET_ID = " + csId;
+ LOG.debug(DbUtilsI18NResourceKeys.EXECUTING_SQL, updateSql);
+
+ databaseType.executeSql(connection, updateSql);
+
+ // update the change set to refer to the drift set
+ updateSql = "update RHQ_DRIFT_CHANGE_SET set DRIFT_SET_ID = " + setId + " where ID = " + csId;
+ LOG.debug(DbUtilsI18NResourceKeys.EXECUTING_SQL, updateSql);
+
+ databaseType.executeSql(connection, updateSql);
+ }
}
}
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 8f10a3b..92ebef7 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -3629,7 +3629,9 @@
<!-- RHQ 4.1 RELEASE uses DB Schema 2.114 -->
<!-- RHQ 4.2 RELEASE uses DB Schema 2.114
- Note, the 4.1 to 4.2 upgrade is broken because most ofthe changes in 2.115 should have gone into 4.2.
+ Note, the 4.1 to 4.2 upgrade is broken because a 4.2 dbsetup actually creates a 2.115 schema. So,
+ for 4.2 dbs to upgrade to 4.3 the schema version must first be corrected and set the schema
+ version to 2.115.
-->
<schemaSpec version="2.115">
@@ -3686,22 +3688,15 @@
</statement>
</schema-directSQL>
- <!-- increase size from 128 to 512 -->
- <schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="NAME" columnType="VARCHAR2" precision="512" />
-
<!-- add new columns -->
<schema-addColumn table="RHQ_DRIFT_DEFINITION" column="DESCRIPTION" columnType="VARCHAR2" precision="512" />
<schema-addColumn table="RHQ_DRIFT_DEFINITION" column="DRIFT_HANDLING_MODE" columnType="VARCHAR2" precision="20" />
<schema-addColumn table="RHQ_DRIFT_DEFINITION" column="IS_PINNED" columnType="BOOLEAN"/>
<schema-addColumn table="RHQ_DRIFT_DEFINITION" column="IS_ATTACHED" columnType="BOOLEAN"/>
- <schema-addColumn table="RHQ_DRIFT_DEFINITION" column="COMPLIANCE_STATUS" columnType="INTEGER"/>
<schema-addColumn table="RHQ_DRIFT_DEFINITION" column="DRIFT_DEF_TEMPLATE_ID" columnType="INTEGER"/>
<!-- initialize new required columns -->
<schema-directSQL>
- <statement desc="RHQ_DRIFT_DEFINITION: set compliance_status column (in compliance)">
- UPDATE RHQ_DRIFT_DEFINITION SET COMPLIANCE_STATUS = 0
- </statement>
<statement targetDBVendor="postgresql" desc="RHQ_DRIFT_DEFINITION: set is_pinned column (false)">
UPDATE RHQ_DRIFT_DEFINITION SET IS_PINNED = FALSE
</statement>
@@ -3719,8 +3714,7 @@
</statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="IS_PINNED" nullable="FALSE"/>
- <schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="IS_ATTACHED" nullable="FALSE"/>
- <schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="COMPLIANCE_STATUS" nullable="FALSE"/>
+ <schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="IS_ATTACHED" nullable="FALSE"/>
<schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="DRIFT_HANDLING_MODE" nullable="FALSE" />
<!-- add new FK -->
@@ -3771,8 +3765,8 @@
<!-- Add new drift_handling_mode column -->
<schema-addColumn table="RHQ_DRIFT_CHANGE_SET" column="DRIFT_HANDLING_MODE" columnType="VARCHAR2" precision="20" />
<schema-directSQL>
- <statement desc="RHQ_DRIFT_DEFINITION: set drift_handling_mode column (normal)">
- UPDATE RHQ_DRIFT_DEFINITION SET DRIFT_HANDLING_MODE = 'normal'
+ <statement desc="RHQ_DRIFT_CHANGE_SET: set drift_handling_mode column (normal)">
+ UPDATE RHQ_DRIFT_CHANGE_SET SET DRIFT_HANDLING_MODE = 'normal'
</statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_DRIFT_CHANGE_SET" column="DRIFT_HANDLING_MODE" nullable="FALSE" />
@@ -3805,11 +3799,31 @@
</schemaSpec>
+<!-- RHQ 4.2 RELEASE uses DB Schema 2.114, which is incorrect, it should have been 2.115. So, for the
+ upgrade to work for an RHQ 4.2 install the schema version must be set to 2.115 prior to the upgrade.
+
+ The 4.2 upgrade should start with 2.116.
+-->
<schemaSpec version="2.116">
+ <!-- RHQ_DRIFT_DEFINITION changes -->
+ <schema-addColumn table="RHQ_DRIFT_DEFINITION" column="COMPLIANCE_STATUS" columnType="INTEGER"/>
+ <schema-directSQL>
+ <statement desc="RHQ_DRIFT_DEFINITION: set compliance_status column (in compliance)">
+ UPDATE RHQ_DRIFT_DEFINITION SET COMPLIANCE_STATUS = 0
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="COMPLIANCE_STATUS" nullable="FALSE"/>
+
+ <schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="NAME" columnType="VARCHAR2" precision="512" />
+
+
+ <!-- RHQ_PRD_VER changes -->
<!-- Increase the max length of a product version from 50 to 100. -->
<schema-alterColumn table="RHQ_PRD_VER" column="VERSION" columnType="VARCHAR2" precision="100" />
</schemaSpec>
+<!-- JON 3.0 RELEASE uses DB Schema 2.116 -->
+
</dbupgrade>
</target>
</project>
commit 37acc1c7cc76cc8a069936d66f0182640ffb569d
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Dec 8 15:22:04 2011 -0500
Change the getSequenceValue() method for postgres db type so that it
actually works.
diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/PostgresqlDatabaseType.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/PostgresqlDatabaseType.java
index 53555ed..4d376f3 100644
--- a/modules/core/dbutils/src/main/java/org/rhq/core/db/PostgresqlDatabaseType.java
+++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/PostgresqlDatabaseType.java
@@ -64,7 +64,7 @@ public abstract class PostgresqlDatabaseType extends DatabaseType {
* @see DatabaseType#getSequenceValue(Connection, String, String)
*/
public int getSequenceValue(Connection conn, String table, String key) throws SQLException {
- String query = "SELECT last_value FROM " + table + "_" + key + "_seq";
+ String query = "SELECT currval('" + table + "_" + key + "_seq')";
PreparedStatement selectPS = null;
ResultSet rs = null;
commit 518ccccdc4ad05353de809068c289c1fc64a5384
Author: John Sanda <jsanda(a)redhat.com>
Date: Thu Dec 8 13:39:47 2011 -0500
[BZ 761320] Only update the detection schedule if drift detection runs
With this commit we no longer update the detection schedule's next scan
time if detection does not run. Drift detection might not run for a few
different reasons - the definition could be disabled, it it earlier than
the next scheduled run, or the server has not acknowledged the previous
change set sent by the agent.
Some additional debug logging has also been added to output when the
next scheduled run is supposed to happen.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
index 71ddf44..21341c4 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
@@ -19,26 +19,8 @@
package org.rhq.core.pc.drift;
-import static org.rhq.common.drift.FileEntry.addedFileEntry;
-import static org.rhq.common.drift.FileEntry.changedFileEntry;
-import static org.rhq.common.drift.FileEntry.removedFileEntry;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.DRIFT;
-import static org.rhq.core.util.file.FileUtil.copyFile;
-import static org.rhq.core.util.file.FileUtil.forEachFile;
-
-import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.rhq.common.drift.ChangeSetReader;
import org.rhq.common.drift.ChangeSetWriter;
import org.rhq.common.drift.FileEntry;
@@ -49,6 +31,17 @@ import org.rhq.core.domain.drift.Filter;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.file.FileVisitor;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.*;
+
+import static org.rhq.common.drift.FileEntry.*;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.DRIFT;
+import static org.rhq.core.util.file.FileUtil.copyFile;
+import static org.rhq.core.util.file.FileUtil.forEachFile;
+
public class DriftDetector implements Runnable {
private Log log = LogFactory.getLog(DriftDetector.class);
@@ -76,14 +69,17 @@ public class DriftDetector implements Runnable {
public void run() {
log.debug("Starting drift detection...");
long startTime = System.currentTimeMillis();
+ boolean updateSchedule = true;
+ DriftDetectionSchedule schedule = null;
try {
if (log.isDebugEnabled()) {
log.debug("Fetching next schedule from " + scheduleQueue);
}
- DriftDetectionSchedule schedule = scheduleQueue.getNextSchedule();
+ schedule = scheduleQueue.getNextSchedule();
if (schedule == null) {
log.debug("No schedules are in the queue.");
+ updateSchedule = false;
return;
}
@@ -93,17 +89,26 @@ public class DriftDetector implements Runnable {
}
if (schedule.getNextScan() > (System.currentTimeMillis() + 100L)) {
- log.debug("Skipping " + schedule + " because it is too early to do the next detection.");
+ if (log.isDebugEnabled()) {
+ log.debug("Skipping " + schedule + " because it is too early to do the next detection.");
+ }
+ updateSchedule = false;
return;
}
if (!schedule.getDriftDefinition().isEnabled()) {
- log.debug("Skipping " + schedule + " because the drift definition is disabled.");
+ if (log.isDebugEnabled()) {
+ log.debug("Skipping " + schedule + " because the drift definition is disabled.");
+ }
+ updateSchedule = false;
return;
}
if (previousSnapshotExists(schedule)) {
- log.debug("Skipping " + schedule + " because server has not yet acked previous change set");
+ if (log.isDebugEnabled()) {
+ log.debug("Skipping " + schedule + " because server has not yet acked previous change set");
+ }
+ updateSchedule = false;
return;
}
@@ -140,7 +145,7 @@ public class DriftDetector implements Runnable {
} finally {
try {
- scheduleQueue.deactivateSchedule();
+ scheduleQueue.deactivateSchedule(updateSchedule);
long endTime = System.currentTimeMillis();
log.debug("Finished drift detection in " + (endTime - startTime) + " ms");
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ScheduleQueue.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ScheduleQueue.java
index 35960ad..13f078d 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ScheduleQueue.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ScheduleQueue.java
@@ -35,7 +35,7 @@ public interface ScheduleQueue {
* at the head of the queue to become active. If there is no active schedule this
* method simply does nothing and returns.
*/
- void deactivateSchedule();
+ void deactivateSchedule(boolean updateSchedule);
/**
* Adds a schedule to the queue for processing by the drift detector
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ScheduleQueueImpl.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ScheduleQueueImpl.java
index cbc50b8..d008f36 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ScheduleQueueImpl.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/ScheduleQueueImpl.java
@@ -1,15 +1,14 @@
package org.rhq.core.pc.drift;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.PriorityQueue;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.drift.DriftDefinition;
import org.rhq.core.domain.drift.DriftDefinitionComparator;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
public class ScheduleQueueImpl implements ScheduleQueue {
private static final Runnable NO_OP = new Runnable() {
@@ -26,6 +25,8 @@ public class ScheduleQueueImpl implements ScheduleQueue {
private Runnable deactivationTask;
+ private Log log = LogFactory.getLog(ScheduleQueueImpl.class);
+
@Override
public DriftDetectionSchedule getNextSchedule() {
try {
@@ -66,16 +67,28 @@ public class ScheduleQueueImpl implements ScheduleQueue {
}
@Override
- public void deactivateSchedule() {
+ public void deactivateSchedule(boolean updateSchedule) {
try {
lock.writeLock().lock();
if (deactivationTask != null) {
deactivationTask.run();
}
+
if (activeSchedule == null) {
return;
}
- activeSchedule.updateShedule();
+
+ if (updateSchedule) {
+ activeSchedule.updateShedule();
+ }
+
+ if (log.isDebugEnabled()) {
+ SimpleDateFormat formatter = new SimpleDateFormat();
+ formatter.applyPattern("hh:mm:ss:SSS a");
+ log.debug("The next drift detection run for " + activeSchedule + " is set for " +
+ formatter.format(new Date(activeSchedule.getNextScan())));
+ }
+
queue.offer(activeSchedule);
activeSchedule = null;
} finally {
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftDetectorTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftDetectorTest.java
index 4a2b333..08373ec 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftDetectorTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftDetectorTest.java
@@ -19,22 +19,12 @@
package org.rhq.core.pc.drift;
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptyList;
-import static org.apache.commons.io.FileUtils.copyFile;
-import static org.apache.commons.io.FileUtils.deleteDirectory;
-import static org.apache.commons.io.FileUtils.touch;
-import static org.rhq.common.drift.FileEntry.addedFileEntry;
-import static org.rhq.common.drift.FileEntry.changedFileEntry;
-import static org.rhq.common.drift.FileEntry.removedFileEntry;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.DRIFT;
-import static org.rhq.test.AssertUtils.assertCollectionMatchesNoOrder;
-import static org.rhq.test.AssertUtils.assertPropertiesMatch;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
+import org.rhq.common.drift.*;
+import org.rhq.core.domain.drift.DriftDefinition;
+import org.rhq.core.system.OperatingSystemType;
+import org.rhq.core.system.SystemInfoFactory;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
import java.io.BufferedReader;
import java.io.File;
@@ -43,18 +33,15 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import org.rhq.common.drift.ChangeSetReader;
-import org.rhq.common.drift.ChangeSetReaderImpl;
-import org.rhq.common.drift.ChangeSetWriter;
-import org.rhq.common.drift.ChangeSetWriterImpl;
-import org.rhq.common.drift.FileEntry;
-import org.rhq.common.drift.Headers;
-import org.rhq.core.domain.drift.DriftDefinition;
-import org.rhq.core.system.OperatingSystemType;
-import org.rhq.core.system.SystemInfoFactory;
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static org.apache.commons.io.FileUtils.*;
+import static org.rhq.common.drift.FileEntry.*;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.DRIFT;
+import static org.rhq.test.AssertUtils.assertCollectionMatchesNoOrder;
+import static org.rhq.test.AssertUtils.assertPropertiesMatch;
+import static org.testng.Assert.*;
public class DriftDetectorTest extends DriftTest {
@@ -168,6 +155,30 @@ public class DriftDetectorTest extends DriftTest {
changeSet);
}
+ @Test
+ public void updateScheduleAfterGeneratingCoverageChangeSet() throws Exception {
+ DriftDefinition driftDef = driftDefinition("update-schedule-after-coverage-changeset",
+ resourceDir.getAbsolutePath());
+ DriftDetectionSchedule schedule = new DriftDetectionSchedule(resourceId(), driftDef);
+
+ File confDir = mkdir(resourceDir, "conf");
+ File serverConf = createRandomFile(confDir, "server.conf");
+
+ long currentTime = System.currentTimeMillis();
+
+ scheduleQueue.addSchedule(schedule);
+ detector.run();
+
+ assertTrue(schedule.getNextScan() >= (currentTime + driftDef.getInterval()),
+ "Failed to update schedule. next scan is " + schedule.getNextScan() + " and should be greater than " +
+ (currentTime + driftDef.getInterval()));
+ }
+
+ @Test
+ public void updateScheduleAfterGeneratingDriftChangeSet() throws Exception {
+
+ }
+
@SuppressWarnings("unchecked")
@Test
public void doNotUpdateSnapshotOrGenerateDriftChangeSetIfNothingChanges() throws Exception {
@@ -219,12 +230,37 @@ public class DriftDetectorTest extends DriftTest {
DriftDefinition def = driftDefinition("disabled-config-test", resourceDir.getAbsolutePath());
def.setEnabled(false);
+ DriftDetectionSchedule schedule = new DriftDetectionSchedule(resourceId(), def);
+ long nextScan = schedule.getNextScan();
+
File confDir = mkdir(resourceDir, "conf");
File server1Conf = new File(confDir, "server-1.conf");
touch(server1Conf);
- scheduleQueue.addSchedule(new DriftDetectionSchedule(resourceId(), def));
+ scheduleQueue.addSchedule(schedule);
+ detector.run();
+
+ // make sure that the next scan time is not updated
+ assertEquals(schedule.getNextScan(), nextScan, "The next scan time for the drift detection schedule should " +
+ " not get updated if drift detection does not actually run for the definition.");
+ }
+
+ @Test
+ public void doNotUpdateScheduleIfItIsTooEarlyToRunDetection() throws Exception {
+ DriftDefinition driftDef = driftDefinition("schedule-not-ready-test", resourceDir.getAbsolutePath());
+ DriftDetectionSchedule schedule = new DriftDetectionSchedule(resourceId(), driftDef);
+
+ File confDir = mkdir(resourceDir, "conf");
+ File server1Conf = new File(confDir, "server.conf");
+
+ scheduleQueue.addSchedule(schedule);
detector.run();
+
+ long nextScan = schedule.getNextScan();
+ detector.run();
+
+ assertEquals(schedule.getNextScan(), nextScan, "The next scan time for the drift detection schedule should " +
+ " not get updated if drift detection does not actually run for the definition.");
}
@Test
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftManagerTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftManagerTest.java
index 518e8e4..c3e28f5 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftManagerTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/DriftManagerTest.java
@@ -260,7 +260,7 @@ public class DriftManagerTest extends DriftTest {
assertTrue(changeSetDir.exists(), "The change set directory should not be deleted while the schedule is "
+ "still active.");
- driftMgr.getSchedulesQueue().deactivateSchedule();
+ driftMgr.getSchedulesQueue().deactivateSchedule(false);
assertFalse(changeSetDir.exists(), "The change set directory should have been deleted after the schedule is "
+ "deactivated.");
}
commit d7ef96e848f139f231a8c875f8bce655fc463812
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Dec 7 16:22:57 2011 -0500
make sure we can support schema versions that we put inbetween existing versions.
for example, if we have db schema 2.115 and 2.116 and we want something in between, make sure
2.115.1 does what we think.
diff --git a/modules/core/dbutils/src/test/java/org/rhq/core/db/ant/dbupdate/SchemaVersionTest.java b/modules/core/dbutils/src/test/java/org/rhq/core/db/ant/dbupdate/SchemaVersionTest.java
index 393a293..4fdf435 100644
--- a/modules/core/dbutils/src/test/java/org/rhq/core/db/ant/dbupdate/SchemaVersionTest.java
+++ b/modules/core/dbutils/src/test/java/org/rhq/core/db/ant/dbupdate/SchemaVersionTest.java
@@ -19,6 +19,7 @@
package org.rhq.core.db.ant.dbupdate;
import org.testng.annotations.Test;
+
import org.rhq.core.db.ant.dbupgrade.SchemaVersion;
/**
@@ -50,6 +51,7 @@ public class SchemaVersionTest {
* Tests checking between versions.
*/
public void testBetween() {
+ assert new SchemaVersion("2.115.1").between(new SchemaVersion("2.115"), new SchemaVersion("2.116"));
assert new SchemaVersion("2").between(new SchemaVersion("1"), new SchemaVersion("3"));
assert new SchemaVersion("222").between(new SchemaVersion("111"), new SchemaVersion("333"));
assert new SchemaVersion("1.0.2").between(new SchemaVersion("1.0.0"), new SchemaVersion("1.0.3"));
commit 74d3e194811007373811bc1cdc8766b68f23de54
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Dec 7 14:27:05 2011 -0500
[BZ 760721] fix bug where negative values would always get incorrectly normalized to "-" (https://bugzilla.redhat.com/show_bug.cgi?id=760721)
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/IsLongValidator.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/IsLongValidator.java
index cb61cab..2b25e73 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/IsLongValidator.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/IsLongValidator.java
@@ -62,11 +62,16 @@ public class IsLongValidator extends CustomValidator {
}
String baseStringValue = stripOffNegativeSignAndLeadingZeroes(stringValue, isNegative);
- updateInputValue((isNegative) ? "-" : "" + baseStringValue);
+ String normalizedValue;
+ if (isNegative) {
+ normalizedValue = "-" + baseStringValue;
+ } else {
+ normalizedValue = baseStringValue;
+ }
+ updateInputValue(normalizedValue);
// all zeroes, optionally prefixed with negative sign, is valid
- if (baseStringValue.length() == 0) {
- updateInputValue("0");
+ if (baseStringValue.equals("0")) {
return true;
}
@@ -107,7 +112,7 @@ public class IsLongValidator extends CustomValidator {
charsToSkip++;
}
- for (int i = charsToSkip; i < stringValue.length(); i++) {
+ for (int i = charsToSkip; i < stringValue.length() - 1; i++) {
if (stringValue.charAt(i) == '0') {
charsToSkip++;
} else {
commit 6245b0d8756929ada716e3c3c70d2089fc1d5a48
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Dec 7 13:58:12 2011 -0500
[BZ 751418] Finish button is now disabled / grayed out on final step of resource import/create wizards until the config editor reports the config as being valid; note, to achieve this a new method isNextButtonEnabled() was added to the WizardStep interface and a new method updateButtonEnablement() was added to the WizardView class (https://bugzilla.redhat.com/show_bug.cgi?id=751418); also added javadoc to the WizardStep interface
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/AbstractWizard.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/AbstractWizard.java
index 1b9fa0c..2e75a05 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/AbstractWizard.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/AbstractWizard.java
@@ -77,4 +77,6 @@ public abstract class AbstractWizard implements Wizard {
public WizardView getView() {
return view;
}
+
+
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/AbstractWizardStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/AbstractWizardStep.java
index 299d0f2..d0aabaf 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/AbstractWizardStep.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/AbstractWizardStep.java
@@ -28,6 +28,10 @@ public abstract class AbstractWizardStep implements WizardStep {
abstract public String getName();
+ public boolean isNextButtonEnabled() {
+ return true;
+ }
+
public boolean nextPage() {
return true;
}
@@ -35,4 +39,5 @@ public abstract class AbstractWizardStep implements WizardStep {
public boolean previousPage() {
return true;
}
+
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/Wizard.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/Wizard.java
index 8b38b39..ff4dd08 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/Wizard.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/Wizard.java
@@ -46,4 +46,5 @@ public interface Wizard {
* This is called when the cancel button or the wizard window's "X" close button is clicked.
*/
void cancel();
+
}
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/WizardStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/WizardStep.java
index f5005c0..16c7ba0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/WizardStep.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/WizardStep.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
+ * Copyright (C) 2005-2011 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -25,17 +25,53 @@ import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.util.selenium.Locatable;
/**
+ * A step in a {@link Wizard wizard}.
+ *
* @author Greg Hinkle
*/
public interface WizardStep {
Messages MSG = CoreGUI.getMessages();
+ /**
+ * Returns the canvas containing this step's widget content. This method should <b>not</b> add the canvas to the
+ * parent canvas - the wizard framework will take care of that.
+ *
+ * @param parent the parent canvas to which the returned canvas will be added -
+ *
+ * @return the canvas containing this step's widget content
+ */
Canvas getCanvas(Locatable parent);
+ /**
+ * Returns true if this step's Next or Finish button should be enabled, or false if it should be disabled.
+ *
+ * @return true if this step's Next or Finish button should be enabled, or false if it should be disabled
+ */
+ boolean isNextButtonEnabled();
+
+ /**
+ * Called when the user clicks this step's Next or Finish button. If all required data has been entered for the
+ * step and is valid, true should be returned, and the wizard will advance to the next step, otherwise false
+ * should be returned, and the wizard will not advance.
+ *
+ * @return true if all required data has been entered for the step and is valid, or false otherwise
+ */
boolean nextPage();
+ /**
+ * Called when the user clicks this step's Previous button. Should return true if the wizard should go to the
+ * previous step, or false if it should not.
+ *
+ * @return true if the wizard should go to the previous step, or false if it should not.
+ */
boolean previousPage();
+ /**
+ * Returns the title of this step, to be displayed in the wizard modal's title bar.
+ *
+ * @return the title of this step, to be displayed in the wizard modal's title bar
+ */
String getName();
+
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/WizardView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/WizardView.java
index d5fe441..34291f0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/WizardView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/wizard/WizardView.java
@@ -48,6 +48,7 @@ import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableWindow;
* @author Greg Hinkle
*/
public class WizardView extends LocatableVLayout {
+
static private final Messages MSG = CoreGUI.getMessages();
static private final String CANCEL = MSG.common_button_cancel();
@@ -229,7 +230,7 @@ public class WizardView extends LocatableVLayout {
.size())));
stepLabel.setWrap(false);
- WizardStep step = wizardSteps.get(currentStep);
+ final WizardStep step = wizardSteps.get(currentStep);
stepTitleLabel.setContents(step.getName());
@@ -255,7 +256,7 @@ public class WizardView extends LocatableVLayout {
}
currentCanvas = wizardSteps.get(currentStep).getCanvas(this);
- // if null advance to the next step by automatically "clicking" the Next button
+ // if null, advance to the next step by automatically "clicking" the Next button
if (null == currentCanvas) {
if (step.nextPage()) {
wizardSteps.get(currentStep).nextPage();
@@ -282,7 +283,7 @@ public class WizardView extends LocatableVLayout {
cancelButton.setDisabled(false);
previousButton.setDisabled(stepIndex == 0);
- nextButton.setDisabled(false);
+ nextButton.setDisabled(!step.isNextButtonEnabled());
for (IButton button : customButtons) {
button.setDisabled(false);
@@ -356,4 +357,10 @@ public class WizardView extends LocatableVLayout {
public void decrementStep() {
setStep(currentStep - 1);
}
+
+ public void updateButtonEnablement() {
+ WizardStep step = wizard.getSteps().get(currentStep);
+ getNextButton().setDisabled(!step.isNextButtonEnabled());
+ }
+
}
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 932f197..538aa7f 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
@@ -29,6 +29,8 @@ import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.components.configuration.ConfigurationEditor;
+import org.rhq.enterprise.gui.coregui.client.components.configuration.PropertyValueChangeEvent;
+import org.rhq.enterprise.gui.coregui.client.components.configuration.PropertyValueChangeListener;
import org.rhq.enterprise.gui.coregui.client.components.form.DurationItem;
import org.rhq.enterprise.gui.coregui.client.components.form.TimeUnit;
import org.rhq.enterprise.gui.coregui.client.components.wizard.AbstractWizardStep;
@@ -44,14 +46,13 @@ import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
* @author Jay Shaughnessy
* @author Greg Hinkle
*/
-public class ResourceFactoryConfigurationStep extends AbstractWizardStep {
+public class ResourceFactoryConfigurationStep extends AbstractWizardStep implements PropertyValueChangeListener {
- private boolean noConfigurationNeeded = false; // if true, it has been determined the user doesn't have to set any config
private LocatableVLayout vLayout;
private ConfigurationEditor editor;
private Configuration startingConfig;
private DurationItem timeoutItem;
- AbstractResourceFactoryWizard wizard;
+ private AbstractResourceFactoryWizard wizard;
public ResourceFactoryConfigurationStep(AbstractResourceFactoryWizard wizard) {
this.wizard = wizard;
@@ -102,17 +103,19 @@ public class ResourceFactoryConfigurationStep extends AbstractWizardStep {
ConfigurationGWTServiceAsync configurationService = GWTServiceLookup.getConfigurationService();
configurationService.getOptionValuesForConfigDefinition(def,
new AsyncCallback<ConfigurationDefinition>() {
+ public void onSuccess(ConfigurationDefinition result) {
+ createAndAddConfigurationEditor(result);
+ }
public void onFailure(Throwable throwable) {
- editor = new ConfigurationEditor(vLayout.extendLocatorId("Editor"), def, startingConfig);
- editor.setAllPropertiesWritable(true);
- vLayout.addMember(editor, 0);
-
+ createAndAddConfigurationEditor(def);
}
- public void onSuccess(ConfigurationDefinition result) {
- editor = new ConfigurationEditor(vLayout.extendLocatorId("Editor"), result, startingConfig);
+ private void createAndAddConfigurationEditor(ConfigurationDefinition def) {
+ editor = new ConfigurationEditor(vLayout.extendLocatorId("Editor"), def, startingConfig);
editor.setAllPropertiesWritable(true);
+ editor.addPropertyValueChangeListener(ResourceFactoryConfigurationStep.this);
+ wizard.getView().updateButtonEnablement();
vLayout.addMember(editor, 0);
}
});
@@ -122,9 +125,15 @@ public class ResourceFactoryConfigurationStep extends AbstractWizardStep {
return vLayout;
}
+ @Override
+ public boolean isNextButtonEnabled() {
+ return (editor != null) && editor.isValid();
+ }
+
public boolean nextPage() {
- if (noConfigurationNeeded == true || (editor != null && editor.validate())) {
- wizard.setNewResourceConfiguration((noConfigurationNeeded) ? null : editor.getConfiguration());
+ // Finish.
+ if ((editor != null) && editor.isValid()) {
+ wizard.setNewResourceConfiguration(editor.getConfiguration());
wizard.setNewResourceCreateTimeout(timeoutItem.getValueAsInteger());
wizard.execute();
return true;
@@ -136,4 +145,10 @@ public class ResourceFactoryConfigurationStep extends AbstractWizardStep {
public String getName() {
return MSG.widget_resourceFactoryWizard_editConfigStepName();
}
+
+ @Override
+ public void propertyValueChanged(PropertyValueChangeEvent event) {
+ wizard.getView().updateButtonEnablement();
+ }
+
}
\ No newline at end of file
commit b967a205193b3dbb70f507f7a3df74f0474cb06b
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Dec 7 13:50:58 2011 -0500
minor - remove manual boxing
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDataStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDataStep.java
index 9fa7dd2..b1364b0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDataStep.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDataStep.java
@@ -64,7 +64,7 @@ public class BundleUploadDataStep extends AbstractWizardStep {
mainLayout = new LocatableVLayout("BundleCreateUploadData");
}
- mainLayout.setMargin(Integer.valueOf(20));
+ mainLayout.setMargin(20);
mainLayout.setWidth100();
mainLayout.setHeight(10);
commit f736fd47d4d07204a9f9b8b0f98f8f74bc0fe9f2
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Dec 7 13:49:40 2011 -0500
don't prepend RHQ Server resource name with "AS "; include JNP port in RHQ Server resource name; refactor formatServerName() to use a StringBuilder and be more readable
diff --git a/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/JBossASDiscoveryComponent.java b/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/JBossASDiscoveryComponent.java
index 185ecff..62b39b6 100644
--- a/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/JBossASDiscoveryComponent.java
+++ b/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/JBossASDiscoveryComponent.java
@@ -66,7 +66,7 @@ import org.rhq.plugins.jbossas.util.JnpConfig;
import org.rhq.plugins.jmx.JMXDiscoveryComponent;
/**
- * Discovers JBossAS 3.2.x and 4.x server instances.
+ * Discovers instances of JBoss AS 3.2.3 through 4.2.x, and JBoss EAP and SOA-P 4.x.
*
* @author John Mazzitelli
* @author Ian Springer
@@ -296,8 +296,8 @@ public class JBossASDiscoveryComponent implements ResourceDiscoveryComponent, Ma
final JBossProductType productType = installInfo.getProductType();
String description = productType.DESCRIPTION + " " + installInfo.getMajorVersion();
- boolean isInServer = isRhqServer(absoluteConfigPath);
- if (isInServer) {
+ boolean isRhqServer = isRhqServer(absoluteConfigPath);
+ if (isRhqServer) {
description += " hosting the RHQ Server";
// RHQ-633 : We know this is an RHQ Server. Let's auto-configure for tracking its log file, which is not in
@@ -324,13 +324,13 @@ public class JBossASDiscoveryComponent implements ResourceDiscoveryComponent, Ma
}
}
}
- final String PRODUCT_PREFIX = productType.name() + " ";
- String name = PRODUCT_PREFIX
- + formatServerName(bindingAddress, namingPort, discoveryContext.getSystemInformation().getHostname(),
- absoluteConfigPath.getName(), isInServer);
-
- return new DiscoveredResourceDetails(discoveryContext.getResourceType(), key, name, PRODUCT_PREFIX
- + installInfo.getVersion(), description, pluginConfiguration, processInfo);
+
+ String name = formatServerName(bindingAddress, namingPort, discoveryContext.getSystemInformation().getHostname(),
+ absoluteConfigPath.getName(), productType, isRhqServer);
+ String version = productType.name() + " " + installInfo.getVersion();
+
+ return new DiscoveredResourceDetails(discoveryContext.getResourceType(), key, name, version, description,
+ pluginConfiguration, processInfo);
}
/**
@@ -379,7 +379,8 @@ public class JBossASDiscoveryComponent implements ResourceDiscoveryComponent, Ma
try {
installInfo = new JBossInstallationInfo(homeDir);
} catch (IOException e) {
- throw new IllegalStateException(e);
+ throw new IllegalStateException("Failed to determine installation info for JBoss home dir ["
+ + homeDir + "].", e);
}
File configDir = (File) server.getAttribute(configObjectName, "ServerHomeDir");
@@ -405,51 +406,70 @@ public class JBossASDiscoveryComponent implements ResourceDiscoveryComponent, Ma
// Now set default values on any props that are still not set.
setPluginConfigurationDefaults(pluginConfiguration);
- String resourceName = formatServerName(bindAddress, jnpPort, context.getSystemInformation()
- .getHostname(), configName, isRhqServer(configDir));
+ JBossProductType productType = installInfo.getProductType();
+ String name = formatServerName(bindAddress, jnpPort, context.getSystemInformation().getHostname(),
+ configName, productType, isRhqServer(configDir));
+ String description = productType.NAME +
+ " server that the RHQ Plugin Container is running within";
DiscoveredResourceDetails resource = new DiscoveredResourceDetails(context.getResourceType(),
- configDir.getAbsolutePath(), resourceName, version,
- "JBoss AS server that the RHQ Plugin Container is running within", pluginConfiguration, null);
+ configDir.getAbsolutePath(), name, version, description, pluginConfiguration, null);
return resource;
}
} catch (Exception e) {
- /* JBoss MBean doesn't exist - not a JBoss server. */
- if (log.isDebugEnabled())
- log.debug("Not detected to be embedded in a JBoss AS Server", e);
+ // JBoss MBean doesn't exist - not a JBoss server.
+ log.debug("Not detected to be embedded in a JBoss AS Server", e);
}
return null;
}
public String formatServerName(String bindingAddress, String jnpPort, String hostname, String configurationName,
- boolean isRhq) {
+ JBossProductType productType, boolean isRhq) {
+ StringBuilder serverName = new StringBuilder();
+
+ if (!isRhq) {
+ // prefix w/ product name (e.g. "AS" or "EAP")
+ serverName.append(productType.name()).append(' ');
+ }
+
+ String bindingHostname = getBindingHostname(bindingAddress);
+ if (bindingHostname != null) {
+ serverName.append(bindingHostname);
+ } else {
+ serverName.append(hostname);
+ }
+
+ if (jnpPort != null && !jnpPort.equals(CHANGE_ME)) {
+ serverName.append(':').append(jnpPort);
+ }
+ serverName.append(' ');
if (isRhq) {
- return hostname + " RHQ Server";
+ serverName.append("RHQ Server");
} else {
- String hostnameToUse = hostname;
+ serverName.append(configurationName);
+ }
- if (bindingAddress != null) {
- try {
- InetAddress bindAddr = InetAddress.getByName(bindingAddress);
- if (!bindAddr.isAnyLocalAddress()) {
- //if the binding address != 0.0.0.0
- hostnameToUse = bindAddr.getHostName();
- }
- } catch (UnknownHostException e) {
- //this should not happen?
- log.warn("Unknown hostname passed in as the binding address for JBoss AS server discovery: "
- + bindingAddress);
- }
- }
+ return serverName.toString();
+ }
- if (jnpPort != null && !jnpPort.equals(CHANGE_ME)) {
- hostnameToUse += ":" + jnpPort;
+ private String getBindingHostname(String bindingAddress) {
+ String bindingHostname = null;
+ if (bindingAddress != null) {
+ try {
+ InetAddress bindAddr = InetAddress.getByName(bindingAddress);
+ if (!bindAddr.isAnyLocalAddress()) {
+ //if the binding address != 0.0.0.0
+ bindingHostname = bindAddr.getHostName();
+ }
+ } catch (UnknownHostException e) {
+ //this should not happen?
+ log.warn("Unknown hostname passed in as the binding address for JBoss AS instance: "
+ + bindingAddress);
}
-
- return hostnameToUse + " " + configurationName;
}
+ return bindingHostname;
}
private static String getJnpURL(JBossInstanceInfo cmdLine, File installHome, File configDir) {
commit 664dc6e66fc82257d60c51837c495d60f873505f
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Dec 7 13:46:44 2011 -0500
change log messages from INFO to DEBUG to be consistent w/ other plugins
diff --git a/modules/plugins/rhq-agent/src/main/java/org/rhq/plugins/agent/AgentDiscoveryComponent.java b/modules/plugins/rhq-agent/src/main/java/org/rhq/plugins/agent/AgentDiscoveryComponent.java
index 0faecf2..bef2731 100644
--- a/modules/plugins/rhq-agent/src/main/java/org/rhq/plugins/agent/AgentDiscoveryComponent.java
+++ b/modules/plugins/rhq-agent/src/main/java/org/rhq/plugins/agent/AgentDiscoveryComponent.java
@@ -64,7 +64,7 @@ public class AgentDiscoveryComponent implements ResourceDiscoveryComponent, Reso
* @see ResourceDiscoveryComponent#discoverResources(ResourceDiscoveryContext)
*/
public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext context) {
- log.info("Discovering RHQ Agent...");
+ log.debug("Discovering RHQ Agent...");
HashSet<DiscoveredResourceDetails> set = new HashSet<DiscoveredResourceDetails>();
diff --git a/modules/plugins/script/src/main/java/org/rhq/plugins/script/ScriptDiscoveryComponent.java b/modules/plugins/script/src/main/java/org/rhq/plugins/script/ScriptDiscoveryComponent.java
index eb58227..8cbd84e 100644
--- a/modules/plugins/script/src/main/java/org/rhq/plugins/script/ScriptDiscoveryComponent.java
+++ b/modules/plugins/script/src/main/java/org/rhq/plugins/script/ScriptDiscoveryComponent.java
@@ -52,7 +52,7 @@ public class ScriptDiscoveryComponent implements ResourceDiscoveryComponent, Man
private final Log log = LogFactory.getLog(ScriptDiscoveryComponent.class);
public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext context) {
- log.info("Processing discovered management script resources");
+ log.debug("Processing discovered management script resources...");
HashSet<DiscoveredResourceDetails> details = new HashSet<DiscoveredResourceDetails>();
commit 30e90184edd8660d613fe9feffc94368e4c832f5
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Dec 7 15:55:20 2011 +0100
Don't put @Stateless on the (abstract) super class.
Fix some fallout from refactoring the creation of the aggregate.
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 ce4dd43..ea901d1 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
@@ -33,7 +33,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import javax.ejb.Stateless;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
@@ -63,7 +62,6 @@ import org.rhq.enterprise.server.rest.domain.ResourceWithType;
* For the cache and its evicion policies see rhq-cache-service.xml
* @author Heiko W. Rupp
*/
-@Stateless
@javax.annotation.Resource(name="cache",type= TreeCacheMBean.class,mappedName = "RhqCache")
public class AbstractRestBean {
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 5934dbe..99dd6fe 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
@@ -133,7 +133,7 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
res.setMaxTimeStamp(maxTime);
res.setMinTimeStamp(minTime);
*/
- res = fill(list,scheduleId,hideEmpty);
+ fill(res, list,scheduleId,hideEmpty);
}
CacheControl cc = new CacheControl();
@@ -156,10 +156,10 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
return builder.build();
}
- private MetricAggregate fill(List<MeasurementDataNumericHighLowComposite> list,int scheduleId , boolean hideEmpty) {
+ private MetricAggregate fill(MetricAggregate res, List<MeasurementDataNumericHighLowComposite> list, int scheduleId,
+ boolean hideEmpty) {
long minTime=Long.MAX_VALUE;
long maxTime=0;
- MetricAggregate res = new MetricAggregate();
res.setScheduleId(scheduleId);
for (MeasurementDataNumericHighLowComposite c : list) {
@@ -214,8 +214,9 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
dataManager.findDataForContext(caller, EntityContext.forResource(sched.getResource().getId()),definitionId,startTime,endTime,dataPoints);
if (!listList.isEmpty()) {
List<MeasurementDataNumericHighLowComposite> list = listList.get(0);
- MetricAggregate ma = fill(list,scheduleId,hideEmpty);
- resList.add(ma);
+ MetricAggregate res = new MetricAggregate();
+ fill(res, list,scheduleId,hideEmpty);
+ resList.add(res);
}
else
throw new StuffNotFoundException("Metrics for schedule " + scheduleId);
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 7e908ad..6631ef4 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
@@ -22,6 +22,7 @@ import java.util.List;
import javax.ejb.Local;
import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@@ -54,7 +55,7 @@ public interface MetricHandlerLocal {
Response getMetricData(@PathParam("scheduleId") int scheduleId,
@QueryParam("startTime") long startTime,
@QueryParam("endTime") long endTime,
- @QueryParam("dataPoints") int dataPoints,
+ @QueryParam("dataPoints") @DefaultValue("60") int dataPoints,
@QueryParam("hideEmpty") boolean hideEmpty,
@Context Request request,
@Context HttpHeaders headers);
commit 95a713e15f42a5be3d800b800012482b8ee555c2
Merge: f74b119 bf5446c
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Dec 7 12:04:38 2011 +0100
Merge remote-tracking branch 'origin/master' into feature/rest
commit f74b119c57c4fe7721127b2faa9a5b0b046a8811
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Dec 7 12:04:02 2011 +0100
Initial set of integration tests for the REST api.
diff --git a/modules/integration-tests/rest-api/README.md b/modules/integration-tests/rest-api/README.md
new file mode 100644
index 0000000..b5551be
--- /dev/null
+++ b/modules/integration-tests/rest-api/README.md
@@ -0,0 +1,13 @@
+# REST-API Integration tests
+
+These require a running server with at least one platform as resource id 10001 in inventory.
+Also required are two accounts
+
+* rhqadmin with password rhqadmin in the superuser role
+* user with password name23 as a restricted user
+
+The server to connect to can be given on the command line via `-Drest.server=<server>` as in
+
+ `mvn -Pdev -Drest.server=pintsize test`
+
+If no server is given, localhost is assumed.
\ No newline at end of file
diff --git a/modules/integration-tests/rest-api/pom.xml b/modules/integration-tests/rest-api/pom.xml
new file mode 100644
index 0000000..4a2c4a6
--- /dev/null
+++ b/modules/integration-tests/rest-api/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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-integration-tests</artifactId>
+ <version>4.3.0-SNAPSHOT</version>
+ <relativePath>../../../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>rest-api-tests</artifactId>
+
+ <name>RHQ REST API tests</name>
+
+ <properties>
+ <surefire-plugin.version>2.10</surefire-plugin.version>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${surefire-plugin.version}</version>
+ <dependencies>
+ <dependency>
+ <!-- explicitly choose the junit4.7+ provider -->
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>surefire-junit47</artifactId>
+ <version>${surefire-plugin.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.restfuse</groupId>
+ <artifactId>com.eclipsesource.restfuse</artifactId>
+ <version>1.0.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.2</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GetStatusTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GetStatusTest.java
new file mode 100644
index 0000000..b59bd11
--- /dev/null
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GetStatusTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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, 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.modules.integrationTests.restApi;
+
+
+import com.eclipsesource.restfuse.AuthenticationType;
+import com.eclipsesource.restfuse.Destination;
+import com.eclipsesource.restfuse.HttpJUnitRunner;
+import com.eclipsesource.restfuse.Method;
+import com.eclipsesource.restfuse.Response;
+import com.eclipsesource.restfuse.annotation.Authentication;
+import com.eclipsesource.restfuse.annotation.Context;
+import com.eclipsesource.restfuse.annotation.HttpTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test the status part of the API
+ */
+(a)RunWith(HttpJUnitRunner.class)
+public class GetStatusTest {
+
+
+
+ @Rule
+ public Destination destination = new Destination("http://" + System.getProperty("rest.server","localhost") + ":7080/rest/1");
+
+ @Context
+ private Response response;
+
+
+ @Test
+ @HttpTest( method = Method.GET, path = "/status" )
+ public void testAuthRequired() {
+ com.eclipsesource.restfuse.Assert.assertUnauthorized(response);
+ }
+
+
+ @Test
+ @HttpTest( method = Method.GET, path = "/status" ,authentications =
+ @Authentication(type = AuthenticationType.BASIC, user = "rhqadmin", password = "rhqadmin")
+ )
+ public void testAuthRhqadmin() {
+ com.eclipsesource.restfuse.Assert.assertOk(response);
+ }
+
+ @Test
+ @HttpTest( method = Method.GET, path = "/status" ,authentications =
+ @Authentication(type = AuthenticationType.BASIC, user = "user", password = "name23")
+ )
+ public void testAuthRestricted() {
+ com.eclipsesource.restfuse.Assert.assertForbidden(response);
+ }
+
+
+}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
new file mode 100644
index 0000000..88cfaaf
--- /dev/null
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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, 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.modules.integrationTests.restApi;
+
+import com.eclipsesource.restfuse.AuthenticationType;
+import com.eclipsesource.restfuse.Destination;
+import com.eclipsesource.restfuse.HttpJUnitRunner;
+import com.eclipsesource.restfuse.Method;
+import com.eclipsesource.restfuse.Response;
+import com.eclipsesource.restfuse.annotation.Authentication;
+import com.eclipsesource.restfuse.annotation.Context;
+import com.eclipsesource.restfuse.annotation.Header;
+import com.eclipsesource.restfuse.annotation.HttpTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static junit.framework.Assert.assertTrue;
+
+/**
+ * Test the resources part
+ * @author Heiko W. Rupp
+ */
+(a)RunWith(HttpJUnitRunner.class)
+public class ResourcesTest {
+
+ @Rule
+ public Destination destination = new Destination("http://" + System.getProperty("rest.server","localhost") + ":7080/rest/1");
+
+ @Context
+ private Response response;
+
+
+ @HttpTest( method = Method.GET, path = "/resource/platforms" )
+ public void testAuthRequired() {
+ com.eclipsesource.restfuse.Assert.assertUnauthorized(response);
+ }
+
+ @HttpTest( method = Method.GET, path = "/resource/platforms",authentications =
+ @Authentication(type = AuthenticationType.BASIC, user = "rhqadmin", password = "rhqadmin")
+ )
+ public void testPlatformsPresent() {
+ com.eclipsesource.restfuse.Assert.assertOk(response);
+ assertTrue(response.hasBody());
+ }
+
+ @HttpTest( method = Method.GET, path = "/resource/10001",authentications =
+ @Authentication(type = AuthenticationType.BASIC, user = "rhqadmin", password = "rhqadmin"),
+ headers = {@Header(name = "Accept",value ="application/json")}
+ )
+ public void testGetPlatformJson() {
+ com.eclipsesource.restfuse.Assert.assertOk(response);
+ assertTrue(response.hasBody());
+ }
+
+ @HttpTest( method = Method.GET, path = "/resource/10001",authentications =
+ @Authentication(type = AuthenticationType.BASIC, user = "rhqadmin", password = "rhqadmin"),
+ headers = {@Header(name = "Accept",value ="application/xml")}
+ )
+ public void testGetPlatformXml() {
+ com.eclipsesource.restfuse.Assert.assertOk(response);
+ assertTrue(response.hasBody());
+ }
+
+ @HttpTest( method = Method.GET, path = "/resource/10001/schedules",authentications =
+ @Authentication(type = AuthenticationType.BASIC, user = "rhqadmin", password = "rhqadmin"),
+ headers = {@Header(name = "Accept",value ="application/json")}
+ )
+ public void testGetPlatformSchedules() {
+ com.eclipsesource.restfuse.Assert.assertOk(response);
+ assertTrue(response.hasBody());
+ }
+
+ @HttpTest( method = Method.GET, path = "/resource/10001/children",authentications =
+ @Authentication(type = AuthenticationType.BASIC, user = "rhqadmin", password = "rhqadmin"),
+ headers = {@Header(name = "Accept",value ="application/json")}
+ )
+ public void testGetPlatformChildren() {
+ com.eclipsesource.restfuse.Assert.assertOk(response);
+ assertTrue(response.hasBody());
+ }
+
+}
commit 56eab8fd42ea5c3cfece191a71fef81fd8bf9c54
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Dec 7 12:03:28 2011 +0100
Improve Exception mapping
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
index d951767..58ccf30 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
@@ -18,11 +18,11 @@
*/
package org.rhq.enterprise.server.rest;
-import javax.ejb.EJBException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
+import org.rhq.enterprise.server.authz.PermissionException;
import org.rhq.enterprise.server.resource.ResourceNotFoundException;
/**
@@ -30,31 +30,39 @@ import org.rhq.enterprise.server.resource.ResourceNotFoundException;
* @author Heiko W. Rupp
*/
@Provider
-public class CustomExceptionMapper implements ExceptionMapper<EJBException> {
+public class CustomExceptionMapper implements ExceptionMapper<Exception> {
@Override
- public Response toResponse(EJBException e) {
+ public Response toResponse(Exception e) {
Throwable cause = e.getCause();
+ Response.ResponseBuilder builder;
if (cause !=null) {
+ Response.Status status;
if (cause instanceof StuffNotFoundException)
- return Response.status(Response.Status.NOT_FOUND)
- .entity(cause.getMessage())
- .build();
+ status =Response.Status.NOT_FOUND;
else if (cause instanceof ResourceNotFoundException)
- return Response.status(Response.Status.NOT_FOUND)
- .entity(cause.getMessage())
- .build();
+ status = Response.Status.NOT_FOUND;
else if (cause instanceof ParameterMissingException)
- return Response.status(Response.Status.NOT_ACCEPTABLE)
- .entity(cause.getMessage())
- .build();
+ status = Response.Status.NOT_ACCEPTABLE;
+ else if (cause instanceof PermissionException)
+ status = Response.Status.FORBIDDEN;
else
- return Response.status(Response.Status.SERVICE_UNAVAILABLE)
- .entity(cause.getMessage())
- .build();
+ status = Response.Status.SERVICE_UNAVAILABLE;
+
+ builder = Response.status(status);
+ builder.entity(cause.getMessage());
+ }
+ else {
+ if (e instanceof PermissionException) {
+ builder = Response.status(Response.Status.FORBIDDEN);
+ } else {
+ builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR);
+ }
+ if (e.getMessage()!=null)
+ builder.entity(e.getMessage());
}
- throw e;
+ return builder.build();
}
}
commit 8c1ab57450bc314e7a469ff968d4c24a806905ef
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Dec 7 09:30:45 2011 +0100
Allow to obtain metrics for multiple schedules at once.
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 8be8070..5934dbe 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
@@ -26,9 +26,14 @@ import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
@@ -38,6 +43,7 @@ import javax.ws.rs.core.UriInfo;
import org.jboss.cache.Fqn;
+import org.rhq.core.domain.common.EntityContext;
import org.rhq.core.domain.measurement.DataType;
import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.measurement.MeasurementSchedule;
@@ -73,7 +79,7 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
@Context Request request,
@Context HttpHeaders headers) {
- if (dataPoints<0)
+ if (dataPoints<=0)
throw new IllegalArgumentException("dataPoints must be >0 ");
if (startTime==0) {
@@ -103,11 +109,14 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
List<List<MeasurementDataNumericHighLowComposite>> listList = dataManager.findDataForResource(caller,
schedule.getResource().getId(), new int[]{definitionId}, startTime, endTime, dataPoints);
+/*
long minTime=Long.MAX_VALUE;
long maxTime=0;
+*/
if (!listList.isEmpty()) {
List<MeasurementDataNumericHighLowComposite> list = listList.get(0);
+/*
for (MeasurementDataNumericHighLowComposite c : list) {
long timestamp = c.getTimestamp();
if (!Double.isNaN(c.getValue()) || !hideEmpty) {
@@ -123,6 +132,9 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
}
res.setMaxTimeStamp(maxTime);
res.setMinTimeStamp(minTime);
+*/
+ res = fill(list,scheduleId,hideEmpty);
+ }
CacheControl cc = new CacheControl();
int maxAge = (int) (schedule.getInterval() / 1000L)/2; // millis ; half of schedule interval
@@ -144,6 +156,76 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
return builder.build();
}
+ private MetricAggregate fill(List<MeasurementDataNumericHighLowComposite> list,int scheduleId , boolean hideEmpty) {
+ long minTime=Long.MAX_VALUE;
+ long maxTime=0;
+ MetricAggregate res = new MetricAggregate();
+ res.setScheduleId(scheduleId);
+
+ for (MeasurementDataNumericHighLowComposite c : list) {
+ long timestamp = c.getTimestamp();
+ if (!Double.isNaN(c.getValue()) || !hideEmpty) {
+ MetricAggregate.DataPoint dp = new MetricAggregate.DataPoint(timestamp,c.getValue(),c.getHighValue(),c.getLowValue());
+ res.addDataPoint(dp);
+ }
+ if (timestamp <minTime)
+ minTime= timestamp;
+ if (timestamp >maxTime)
+ maxTime= timestamp;
+ }
+ res.setNumDataPoints(list.size());
+ res.setMaxTimeStamp(maxTime);
+ res.setMinTimeStamp(minTime);
+
+ return res;
+ }
+
+ @Override
+ @GET
+ @Path("data")
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_HTML})
+ public Response getMetricDataMulti(@QueryParam("sid") String schedules, @QueryParam("startTime") long startTime,
+ @QueryParam("endTime") long endTime, @QueryParam("dataPoints") int dataPoints,
+ @QueryParam("hideEmpty") boolean hideEmpty, @Context Request request,
+ @Context HttpHeaders headers) {
+
+ if (startTime==0) {
+ endTime = System.currentTimeMillis();
+ startTime = endTime - EIGHT_HOURS;
+ }
+
+ String[] tmp = schedules.split(",");
+ Integer[] scheduleIds = new Integer[tmp.length];
+ try {
+ for (int i = 0; i < tmp.length ; i++)
+ scheduleIds[i] = Integer.parseInt(tmp[i]);
+ }
+ catch (NumberFormatException nfe) {
+ throw new IllegalArgumentException("Bad input: " + nfe.getMessage());
+ }
+
+ List<MetricAggregate> resList = new ArrayList<MetricAggregate>(scheduleIds.length);
+ for (Integer scheduleId : scheduleIds) {
+ MeasurementSchedule sched = scheduleManager.getScheduleById(caller,scheduleId);
+ if (sched==null)
+ throw new StuffNotFoundException("Schedule with id " + scheduleId);
+ int definitionId = sched.getDefinition().getId();
+ List<List<MeasurementDataNumericHighLowComposite>> listList =
+ dataManager.findDataForContext(caller, EntityContext.forResource(sched.getResource().getId()),definitionId,startTime,endTime,dataPoints);
+ if (!listList.isEmpty()) {
+ List<MeasurementDataNumericHighLowComposite> list = listList.get(0);
+ MetricAggregate ma = fill(list,scheduleId,hideEmpty);
+ resList.add(ma);
+ }
+ else
+ throw new StuffNotFoundException("Metrics for schedule " + scheduleId);
+ }
+
+ GenericEntity<List<MetricAggregate>> metAgg = new GenericEntity<List<MetricAggregate>>(resList) {};
+
+ return Response.ok(metAgg).build();
+
+ }
/**
* Return a metric schedule with the respective status codes for cache validation
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 44844ae..7e908ad 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
@@ -18,7 +18,6 @@
*/
package org.rhq.enterprise.server.rest;
-import java.io.InputStream;
import java.util.List;
import javax.ejb.Local;
@@ -60,6 +59,17 @@ public interface MetricHandlerLocal {
@Context Request request,
@Context HttpHeaders headers);
+ @GET
+ @Path("data")
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
+ Response getMetricDataMulti(@QueryParam("sid") String scheduleIds,
+ @QueryParam("startTime") long startTime,
+ @QueryParam("endTime") long endTime,
+ @QueryParam("dataPoints") int dataPoints,
+ @QueryParam("hideEmpty") boolean hideEmpty,
+ @Context Request request,
+ @Context HttpHeaders headers);
+
@GET
@Path("data/resource/{resourceId}")
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 d6af76e..16b6d40 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
@@ -41,15 +41,17 @@ public class MetricAggregate {
long maxTimeStamp;
public MetricAggregate() {
+ dataPoints = new ArrayList<DataPoint>();
}
public MetricAggregate(Integer scheduleId, double min, double avg, double max) {
+ this();
this.scheduleId = scheduleId;
this.min = min;
this.avg = avg;
this.max = max;
- dataPoints = new ArrayList<DataPoint>();
+
}
@XmlElement
commit bf5446c876c5d799a6fb58cf3c6a2e050a0c6390
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Dec 6 17:03:30 2011 -0500
[BZ 755019] sort the deployment table
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentListView.java
index 4f78a16..a1f2c13 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentListView.java
@@ -26,6 +26,7 @@ import java.util.HashMap;
import com.smartgwt.client.data.Criteria;
import com.smartgwt.client.types.ListGridFieldType;
+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.CellFormatter;
@@ -44,6 +45,7 @@ import org.rhq.enterprise.gui.coregui.client.components.table.EscapedHtmlCellFor
import org.rhq.enterprise.gui.coregui.client.components.table.Table;
import org.rhq.enterprise.gui.coregui.client.components.table.TimestampCellFormatter;
import org.rhq.enterprise.gui.coregui.client.util.StringUtility;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableListGrid;
/**
* @author Greg Hinkle
@@ -60,6 +62,14 @@ public class BundleDeploymentListView extends Table<BundleDeploymentDataSource>
}
@Override
+ protected LocatableListGrid createListGrid(String locatorId) {
+ LocatableListGrid grid = super.createListGrid(locatorId);
+ grid.setSortField(BundleDeploymentDataSource.FIELD_DEPLOY_TIME);
+ grid.setSortDirection(SortDirection.DESCENDING);
+ return grid;
+ }
+
+ @Override
protected void configureTable() {
ListGridField idField = new ListGridField(BundleDeploymentDataSource.FIELD_ID, MSG.common_title_id());
ListGridField nameField = new ListGridField(BundleDeploymentDataSource.FIELD_NAME, MSG
commit 8a2f8f8caf0c10cfc279dc49a8526da44bb7702b
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Dec 6 16:23:05 2011 -0500
[BZ 755019] sort the deployment audit trail
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleResourceDeploymentHistoryListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleResourceDeploymentHistoryListView.java
index 749b042..63a10d7 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleResourceDeploymentHistoryListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleResourceDeploymentHistoryListView.java
@@ -32,6 +32,7 @@ import com.smartgwt.client.types.DateDisplayFormat;
import com.smartgwt.client.types.ExpansionMode;
import com.smartgwt.client.types.ListGridFieldType;
import com.smartgwt.client.types.SelectionStyle;
+import com.smartgwt.client.types.SortDirection;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.DoubleClickEvent;
@@ -92,6 +93,8 @@ public class BundleResourceDeploymentHistoryListView extends LocatableVLayout {
grid.setCanExpandRecords(true);
grid.setExpansionMode(ExpansionMode.DETAIL_FIELD);
grid.setDetailField("message");
+ grid.setSortField("timestamp");
+ grid.setSortDirection(SortDirection.ASCENDING);
ListGridField action = new ListGridField("action", MSG.view_bundle_deploy_action());
action.setAutoFitWidth(true);
commit 64c7032453ec453246ffb3a9a2bcb664903be88e
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue Dec 6 16:11:42 2011 -0500
[Bug 753866 - DB Upgrade needs more work for existing drift records]
This is to support RHQ 4.1 and 4.2 drift upgrades to 4.3. It adds
two Java upgrade tasks and puts them into the existing 2.115 step. (JON
note, JON3.0 already places the db at 2.116 and the previous
version of 2.115 was already sufficient for JON3.0 purposes. We *do not*
want these new changes applied to JON3.0 upgrades and so I did not
create a new schema task for this, on purpose.)
diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/DatabaseType.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/DatabaseType.java
index 27fee40..eb2f6a7 100644
--- a/modules/core/dbutils/src/main/java/org/rhq/core/db/DatabaseType.java
+++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/DatabaseType.java
@@ -560,6 +560,20 @@ public abstract class DatabaseType {
public abstract int getNextSequenceValue(Connection conn, String table, String key) throws SQLException;
/**
+ * A utility that returns the string for sequence use in an Insert statement
+ *
+ * @param conn The connection to use to get the sequence value.
+ * @param sequenceName The sequence name for the table.
+ *
+ * @return the sequence generating string
+ *
+ * @throws SQLException
+ */
+ public String getSequenceInsertValue(Connection conn, String sequenceName) {
+ return "nextval('" + sequenceName + "')";
+ }
+
+ /**
* Creates a sequence with the given name. Its initial value is specified along with its increment (both are
* specified as Strings).
*
@@ -570,13 +584,15 @@ public abstract class DatabaseType {
* @param seqIdCacheSize
* @throws SQLException
*/
- public void createSequence(Connection conn, String name, String initial, String increment, String seqIdCacheSize) throws SQLException {
+ public void createSequence(Connection conn, String name, String initial, String increment, String seqIdCacheSize)
+ throws SQLException {
CreateSequenceExprBuilder builder = CreateSequenceExprBuilder.getBuilder(this);
HashMap<String, Object> terms = new HashMap<String, Object>();
terms.put(CreateSequenceExprBuilder.KEY_SEQ_NAME, name);
terms.put(CreateSequenceExprBuilder.KEY_SEQ_START, initial);
terms.put(CreateSequenceExprBuilder.KEY_SEQ_INCREMENT, increment);
- terms.put(CreateSequenceExprBuilder.KEY_SEQ_CACHE_SIZE, CreateSequenceExprBuilder.getSafeSequenceCacheSize(builder, seqIdCacheSize));
+ terms.put(CreateSequenceExprBuilder.KEY_SEQ_CACHE_SIZE, CreateSequenceExprBuilder.getSafeSequenceCacheSize(
+ builder, seqIdCacheSize));
executeSql(conn, builder.build(terms));
}
diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/OracleDatabaseType.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/OracleDatabaseType.java
index abf73a3..b4ea5e9 100644
--- a/modules/core/dbutils/src/main/java/org/rhq/core/db/OracleDatabaseType.java
+++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/OracleDatabaseType.java
@@ -95,6 +95,10 @@ public abstract class OracleDatabaseType extends DatabaseType {
}
}
+ public String getSequenceInsertValue(Connection conn, String sequenceName) {
+ return sequenceName + ".NEXTVAL";
+ }
+
/**
* @see DatabaseType#getNextSequenceValue(Connection, String, String)
*/
diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DriftPathDirectoryDatabaseUpgradeTask.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DriftPathDirectoryDatabaseUpgradeTask.java
new file mode 100644
index 0000000..6b87331
--- /dev/null
+++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DriftPathDirectoryDatabaseUpgradeTask.java
@@ -0,0 +1,71 @@
+/*
+ * 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.db.upgrade;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import mazz.i18n.Logger;
+
+import org.rhq.core.db.DatabaseType;
+import org.rhq.core.db.DbUtilsI18NFactory;
+import org.rhq.core.db.DbUtilsI18NResourceKeys;
+
+/**
+ * Database upgrade task 2.115 adds rhq_drift.path_directory column to store the directory portion of the path
+ * column. This code sets the value appropriately.
+ *
+ * @author Jay Shaughnessy
+ */
+public class DriftPathDirectoryDatabaseUpgradeTask implements DatabaseUpgradeTask {
+
+ private static final Logger LOG = DbUtilsI18NFactory.getLogger(DriftPathDirectoryDatabaseUpgradeTask.class);
+
+ public void execute(DatabaseType databaseType, Connection connection) throws SQLException {
+
+ Statement s = null;
+
+ try {
+ String sql = "select d.ID, d.PATH, d.PATH_DIRECTORY from RHQ_DRIFT d";
+ LOG.debug(DbUtilsI18NResourceKeys.EXECUTING_SQL, sql);
+
+ s = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
+ ResultSet rs = s.executeQuery(sql);
+
+ while (rs.next()) {
+ // note, this is guaranteed to be non-null and valid
+ String path = rs.getString(2);
+ String dir = getDir(path);
+ rs.updateString(3, dir);
+ rs.updateRow();
+ }
+ } finally {
+ databaseType.closeStatement(s);
+ }
+ }
+
+ private String getDir(String path) {
+ int i = path.lastIndexOf("/");
+ String result = (i != -1) ? path.substring(0, i) : "./";
+
+ return result;
+ }
+}
diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DriftTemplateMapDatabaseUpgradeTask.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DriftTemplateMapDatabaseUpgradeTask.java
new file mode 100644
index 0000000..d060a2a
--- /dev/null
+++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DriftTemplateMapDatabaseUpgradeTask.java
@@ -0,0 +1,65 @@
+/*
+ * 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.db.upgrade;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import mazz.i18n.Logger;
+
+import org.rhq.core.db.DatabaseType;
+import org.rhq.core.db.DbUtilsI18NFactory;
+import org.rhq.core.db.DbUtilsI18NResourceKeys;
+
+/**
+ * Database upgrade task 2.115 adds the rhq_drift_def_template table. The table is initially populated here
+ * by using data in the to-be-removed rhq_drift_template_map table.
+ *
+ * @author Jay Shaughnessy
+ */
+public class DriftTemplateMapDatabaseUpgradeTask implements DatabaseUpgradeTask {
+
+ private static final Logger LOG = DbUtilsI18NFactory.getLogger(DriftPathDirectoryDatabaseUpgradeTask.class);
+
+ public void execute(DatabaseType databaseType, Connection connection) throws SQLException {
+
+ String sql = "" //
+ + " insert into RHQ_DRIFT_DEF_TEMPLATE (" //
+ + " ID," //
+ + " RESOURCE_TYPE_ID," //
+ + " CONFIG_ID," //
+ + " NAME," //
+ + " DESCRIPTION," //
+ + " IS_USER_DEFINED," //
+ + " CTIME )" //
+ + " select " + databaseType.getSequenceInsertValue(connection, "RHQ_DRIFT_DEF_TEMPLATE_ID_SEQ") + "," //
+ + " tm.RESOURCE_TYPE_ID, " //
+ + " ct.CONFIG_ID, " //
+ + " ct.NAME, " //
+ + " ct.DESCRIPTION, " //
+ + " " + databaseType.getBooleanValue(false) + "," //
+ + " " + System.currentTimeMillis() //
+ + " from RHQ_DRIFT_TEMPLATE_MAP tm " //
+ + " join RHQ_RESOURCE_TYPE rt on tm.RESOURCE_TYPE_ID = rt.ID" //
+ + " join RHQ_CONFIG_TEMPLATE ct on tm.CONFIG_TEMPLATE_ID = ct.ID";
+ LOG.debug(DbUtilsI18NResourceKeys.EXECUTING_SQL, sql);
+
+ databaseType.executeSql(connection, sql);
+ }
+}
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 fb2ed85..8f10a3b 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -3781,12 +3781,11 @@
<!-- RHQ_DRIFT -->
<!-- Add new path_directory column -->
<schema-addColumn table="RHQ_DRIFT" column="PATH_DIRECTORY" columnType="VARCHAR2" precision="1024" />
- <!-- TODO: This needs to be a java update step! -->
- <schema-directSQL>
- <statement desc="RHQ_DRIFT_DEFINITION: set drift_handling_mode column (normal)">
- UPDATE RHQ_DRIFT SET PATH_DIRECTORY = PATH
- </statement>
- </schema-directSQL>
+
+ <!-- Set the new path_directory column using the current path column values -->
+ <schema-javaTask className="DriftPathDirectoryDatabaseUpgradeTask" />
+
+ <!-- Now it is safe to set the new path_directory column not null -->
<schema-alterColumn table="RHQ_DRIFT" column="PATH_DIRECTORY" nullable="FALSE" />
<!-- add new drift_set_id column and FK -->
@@ -3800,8 +3799,10 @@
</statement>
</schema-directSQL>
- <!-- TODO For RHQ 4.3: Java upgrade step to set path_directory from path in rhq_drift -->
- <!-- TODO For RHQ 4.3: Java upgrade step for rhq_drift_template_map conversion and removal -->
+ <!-- Morph rhq_drift_template_map rows into rhq_drift_def_template rows. The rhq_drift_template_map
+ table is obsolete. -->
+ <schema-javaTask className="DriftTemplateMapDatabaseUpgradeTask" />
+
</schemaSpec>
<schemaSpec version="2.116">
commit 16823b9934ea91e81e0b7102bd464a57875fe033
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Dec 6 14:16:32 2011 -0500
[BZ 752550] remove old downloaded bundle files to help clean out the tmp directory
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/bundle/BundleManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/bundle/BundleManager.java
index d240606..561e4a1 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/bundle/BundleManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/bundle/BundleManager.java
@@ -23,6 +23,7 @@
package org.rhq.core.pc.bundle;
import java.io.File;
+import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.HashMap;
@@ -47,10 +48,10 @@ import org.rhq.core.domain.bundle.BundleDeploymentStatus;
import org.rhq.core.domain.bundle.BundleDestination;
import org.rhq.core.domain.bundle.BundleResourceDeployment;
import org.rhq.core.domain.bundle.BundleResourceDeploymentHistory;
+import org.rhq.core.domain.bundle.BundleResourceDeploymentHistory.Status;
import org.rhq.core.domain.bundle.BundleType;
import org.rhq.core.domain.bundle.BundleVersion;
import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration;
-import org.rhq.core.domain.bundle.BundleResourceDeploymentHistory.Status;
import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.core.domain.resource.Resource;
@@ -72,6 +73,7 @@ import org.rhq.core.pluginapi.bundle.BundleManagerProvider;
import org.rhq.core.pluginapi.bundle.BundlePurgeResult;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.exception.ThrowableUtil;
+import org.rhq.core.util.file.FileUtil;
/**
* Manages the bundle subsystem, which allows bundles of content to be installed.
@@ -172,6 +174,12 @@ public class BundleManager extends AgentService implements BundleAgentService, B
File bundleFilesDir = new File(pluginTmpDir, "bundle-versions/"
+ bundleDeployment.getBundleVersion().getId());
bundleFilesDir.mkdirs();
+
+ // clean up any old downloads we may have retrieved before. This helps clean out
+ // our temp directory so we don't unnecessarily fill up our file system with obsolete files
+ removeOldDownloadedBundleFiles(bundleFilesDir);
+
+ // now download the bundle files we need for the current deployment
Map<PackageVersion, File> downloadedFiles = downloadBundleFiles(resourceDeployment,
bundleFilesDir);
@@ -311,6 +319,35 @@ public class BundleManager extends AgentService implements BundleAgentService, B
}
/**
+ * Given a directory where the current deployment's bundle files will reside, this method will clear out
+ * any other files located in other peer directories. In other words, the given directory and all its
+ * subdirectories and child files are left untouched, but all files and directories found in peer
+ * directories are wiped. This helps clean out our temp directory so we don't fill up the file system
+ * with old downloaded files that we don't need anymore. See BZ 752550.
+ *
+ * @param currentBundleVersionFilesDir
+ */
+ private void removeOldDownloadedBundleFiles(final File currentBundleVersionFilesDir) {
+ File parent = null;
+ try {
+ parent = currentBundleVersionFilesDir.getParentFile();
+ File[] doomedFiles = parent.listFiles(new FileFilter() {
+ public boolean accept(File child) {
+ return !currentBundleVersionFilesDir.equals(child);
+ }
+ });
+ for (File doomedFile : doomedFiles) {
+ FileUtil.purge(doomedFile, true);
+ }
+ } catch (Exception e) {
+ log.warn("Failed to clean up old downloaded bundle files in ["
+ + parent
+ + "]. You can ignore this but if the agent is asked to deploy a lot of bundles, the file system may fill up."
+ + " Cause: " + e);
+ }
+ }
+
+ /**
* Downloads the bundle's files into the bundle plugin's tmp directory and returns that tmp directory.
*
* @param resourceDeployment access to deployment information, including what bundle files need to be downloaded
commit 32e06f0466e3a6a440518c4bd72e21c012bd6afa
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue Dec 6 12:08:35 2011 -0500
[Bug 760209 - Drift Carousel not filtering the drift entries]
I think this broke when initial criteria handling changed in the
underlying Table implementation. The initial criteria was set correctly
but that was no longer applied directly to the grid, instead we now
manually perform the initial fetch. But that led to an overriden method
getting called to return the current criteria, which had yet to be
determined (it was thought to be needed on refresh only). So, the fix was
to immediately set the current criteria to the initial criteria in the
subclass.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselMemberView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselMemberView.java
index 47b5d3d..991ec84 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselMemberView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselMemberView.java
@@ -71,6 +71,7 @@ public class DriftCarouselMemberView extends DriftHistoryView implements Carouse
super(locatorId, null, context, hasWriteAccess, initialCriteria);
+ this.carouselCriteria = initialCriteria;
this.changeSet = driftChangeSet;
((DriftCarouselDataSource) getDataSource()).setChangeSetId(this.changeSet.getId());
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java
index 6ccbb17..f941c6f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java
@@ -242,7 +242,7 @@ public class DriftCarouselView extends BookmarkableCarousel implements DetailsVi
}
changeSetCriteria.addFilterStartVersion(String.valueOf(startVersion));
- // apply the drift-level carousel filters in order to filter out changesets that have no applicab;e drift
+ // apply the drift-level carousel filters in order to filter out changesets that have no applicable drift
Criteria criteria = getCurrentCriteria();
DriftCategory[] driftCategoriesFilter = RPCDataSource.getArrayFilter(criteria,
DriftDataSource.FILTER_CATEGORIES, DriftCategory.class);
commit 71db2833a06ad1537d8a27fe5a0399850d6f81bd
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Dec 6 16:48:56 2011 +0100
Allow to limit schedules by name
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 59efeba..64cdea3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -195,6 +195,7 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
public Response getSchedules(int resourceId,
String scheduleType,
boolean enabledOnly,
+ String name,
@Context Request request,
@Context HttpHeaders headers,
@Context UriInfo uriInfo) {
@@ -216,26 +217,28 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
if ("all".equals(scheduleType) ||
scheduleType.toLowerCase().equals(definition.getDataType().toString().toLowerCase()) ) {
if (!enabledOnly || (enabledOnly && schedule.isEnabled() )) {
- MetricSchedule ms = new MetricSchedule(schedule.getId(), definition.getName(), definition.getDisplayName(),
- schedule.isEnabled(),schedule.getInterval(), definition.getUnits().toString(),
- definition.getDataType().toString());
- UriBuilder uriBuilder;
- URI uri;
- if (definition.getDataType()== DataType.MEASUREMENT) {
+ if (name==null || (name!=null && name.equals(definition.getName()))) {
+ MetricSchedule ms = new MetricSchedule(schedule.getId(), definition.getName(), definition.getDisplayName(),
+ schedule.isEnabled(),schedule.getInterval(), definition.getUnits().toString(),
+ definition.getDataType().toString());
+ UriBuilder uriBuilder;
+ URI uri;
+ if (definition.getDataType()== DataType.MEASUREMENT) {
+ uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/metric/data/{id}");
+ uri = uriBuilder.build(schedule.getId());
+ Link metricLink = new Link("metric",uri.toString());
+ ms.addLink(metricLink);
+ }
+ // create link to the resource
uriBuilder = uriInfo.getBaseUriBuilder();
- uriBuilder.path("/metric/data/{id}");
- uri = uriBuilder.build(schedule.getId());
- Link metricLink = new Link("metric",uri.toString());
- ms.addLink(metricLink);
+ uriBuilder.path("resource/" + schedule.getResource().getId());
+ uri = uriBuilder.build();
+ Link link = new Link("resource",uri.toString());
+ ms.addLink(link);
+
+ ret.add(ms);
}
- // create link to the resource
- uriBuilder = uriInfo.getBaseUriBuilder();
- uriBuilder.path("resource/" + schedule.getResource().getId());
- uri = uriBuilder.build();
- Link link = new Link("resource",uri.toString());
- ms.addLink(link);
-
- ret.add(ms);
}
}
}
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 ab9ea62..77f268f 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
@@ -88,6 +88,7 @@ public interface ResourceHandlerLocal {
Response getSchedules(@PathParam("id") int resourceId,
@QueryParam("type") @DefaultValue("all") String scheduleType,
@QueryParam("enabledOnly") @DefaultValue("true") boolean enabledOnly,
+ @QueryParam("name") String name,
@Context Request request,
@Context HttpHeaders headers,
@Context UriInfo uriInfo);
commit 01902864918073d86e08d088061ffc85efc593da
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Dec 6 12:16:42 2011 +0100
Make ResourceWithType show up as <resource> in xml output
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
index 132fc34..735efa1 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
@@ -39,7 +39,7 @@ import org.jboss.resteasy.spi.touri.URITemplate;
* A (partial) resource with some type information
* @author Heiko W. Rupp
*/
-@XmlRootElement
+@XmlRootElement(name="resource")
/*
@XmlAccessorType(XmlAccessType.NONE)
@URITemplate("{id}")
commit 83197699d41880beb6266fc47d38cbf201bce7a4
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Dec 5 15:55:31 2011 -0500
[Bug 760145 - Drift snapshot displays wrong directory name on windows]
This is fairly bad as the paths get corrupted for all drift entries when
the basedir is a windows file system root (e.g. c:/ or d:/). There is
no workaround other than not using the file system root as the basedir.
I'm not sure, this may also happen using the a linux root "/" basedir.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
index 0ba5795..71ddf44 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
@@ -538,7 +538,13 @@ public class DriftDetector implements Runnable {
if (basedir.equals(file)) {
return ".";
}
- return file.getAbsolutePath().substring(basedir.getAbsolutePath().length() + 1);
+ String filePath = file.getAbsolutePath();
+ String basedirPath = basedir.getAbsolutePath();
+ int basedirLen = basedirPath.length();
+ if (!basedirPath.endsWith(File.separator)) {
+ ++basedirLen;
+ }
+ return filePath.substring(basedirLen);
}
private String sha256(File file) throws IOException {
commit 6f3d99d160c4910bffe16ada89b625fe251bea44
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Dec 5 15:51:07 2011 -0500
[Bug 760289 - Excessive file scanning in drift detection when using includes filters]
Now, when using includes file paths limit the directory scanning to only
those included directories.
Note that using a "." as an includes path basically translates to using
the base directory, in which case the scan will be as it is now.
A future enhancement may be to analyze the pattern and decide
whether a recursive scan is necessary. Currently. So, using includes
patterns to just look for certain files in the base directory will
expose you to the full scan.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
index 3f32f1f..0ba5795 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
@@ -45,6 +45,7 @@ import org.rhq.common.drift.FileEntry;
import org.rhq.common.drift.Headers;
import org.rhq.core.domain.drift.DriftChangeSetCategory;
import org.rhq.core.domain.drift.DriftDefinition;
+import org.rhq.core.domain.drift.Filter;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.file.FileVisitor;
@@ -167,13 +168,12 @@ public class DriftDetector implements Runnable {
log.debug("Generating drift change set for " + schedule);
- File currentSnapshot = changeSetMgr.findChangeSet(schedule.getResourceId(),
- schedule.getDriftDefinition().getName(), COVERAGE);
+ File currentSnapshot = changeSetMgr.findChangeSet(schedule.getResourceId(), schedule.getDriftDefinition()
+ .getName(), COVERAGE);
File snapshotFile = currentSnapshot;
if (schedule.getDriftDefinition().isPinned()) {
snapshotFile = new File(snapshotFile.getParentFile(), "snapshot.pinned");
-
}
final File basedir = new File(basedir(schedule.getResourceId(), schedule.getDriftDefinition()));
@@ -203,43 +203,50 @@ public class DriftDetector implements Runnable {
}
// First look for files that have either been modified or deleted
- scanForModifiedOrDeletedFiles(schedule, basedir, processedFiles, snapshotEntries, deltaEntries, coverageReader);
+ scanForModifiedOrDeletedFiles(schedule, basedir, processedFiles, snapshotEntries, deltaEntries,
+ coverageReader);
} finally {
coverageReader.close();
}
// If the basedir is still valid we need to do a directory tree scan to look for newly added files
if (basedir.isDirectory()) {
- forEachFile(basedir, new FilterFileVisitor(basedir, schedule.getDriftDefinition().getIncludes(), schedule
- .getDriftDefinition().getExcludes(), new FileVisitor() {
- @Override
- public void visit(File file) {
- try {
- if (processedFiles.contains(file)) {
- return;
- }
+ DriftDefinition driftDef = schedule.getDriftDefinition();
+ List<Filter> includes = driftDef.getIncludes();
+ List<Filter> excludes = driftDef.getExcludes();
+
+ for (File dir : getScanDirectories(basedir, includes)) {
+ forEachFile(dir, new FilterFileVisitor(basedir, includes, excludes, new FileVisitor() {
+ @Override
+ public void visit(File file) {
+ try {
+ if (processedFiles.contains(file)) {
+ return;
+ }
- if (!file.canRead()) {
- if (log.isDebugEnabled()) {
- log.debug("Skipping " + file.getPath() + " since it is not readable.");
+ if (!file.canRead()) {
+ if (log.isDebugEnabled()) {
+ log.debug("Skipping " + file.getPath() + " since it is not readable.");
+ }
+ return;
}
- return;
- }
- if (log.isInfoEnabled()) {
- log.info("Detected added file for " + schedule + " --> " + file.getAbsolutePath());
- }
+ if (log.isInfoEnabled()) {
+ log.info("Detected added file for " + schedule + " --> " + file.getAbsolutePath());
+ }
- FileEntry newEntry = addedFileEntry(relativePath(basedir, file), sha256(file));
- deltaEntries.add(newEntry);
- snapshotEntries.add(newEntry);
- } catch (IOException e) {
- log.error("An error occurred while generating a drift change set for " + schedule + ": "
- + e.getMessage());
- throw new DriftDetectionException("An error occurred while generating a drift change set", e);
+ FileEntry newEntry = addedFileEntry(relativePath(basedir, file), sha256(file));
+ deltaEntries.add(newEntry);
+ snapshotEntries.add(newEntry);
+ } catch (IOException e) {
+ log.error("An error occurred while generating a drift change set for " + schedule + ": "
+ + e.getMessage());
+ throw new DriftDetectionException("An error occurred while generating a drift change set",
+ e);
+ }
}
- }
- }));
+ }));
+ }
}
if (deltaEntries.isEmpty()) {
@@ -250,8 +257,8 @@ public class DriftDetector implements Runnable {
// the current snapshot to match the pinned snapshot. Note though
// that we increment the snapshot version in order to let the server
// know about the state change.
- if (schedule.getDriftDefinition().isPinned() && newVersion > 1 && !isPreviousChangeSetEmpty(
- schedule.getResourceId(), schedule.getDriftDefinition())) {
+ if (schedule.getDriftDefinition().isPinned() && newVersion > 1
+ && !isPreviousChangeSetEmpty(schedule.getResourceId(), schedule.getDriftDefinition())) {
currentSnapshot.delete();
File newSnapshot = updateCurrentSnapshot(schedule, snapshotEntries, newVersion);
@@ -259,8 +266,8 @@ public class DriftDetector implements Runnable {
// TODO report back to the server that we are back in compliance
}
} else {
- if (schedule.getDriftDefinition().isPinned() && newVersion > 1 &&
- isSameAsPreviousChangeSet(deltaEntries, currentSnapshot)) {
+ if (schedule.getDriftDefinition().isPinned() && newVersion > 1
+ && isSameAsPreviousChangeSet(deltaEntries, currentSnapshot)) {
// if we are still out of compliance just report, we report a
// repeat change set to indicate no changes but also still out
// of compliance.
@@ -276,6 +283,26 @@ public class DriftDetector implements Runnable {
}
}
+ private Set<File> getScanDirectories(final File basedir, List<Filter> includes) {
+
+ Set<File> directories = new HashSet<File>();
+
+ if (null == includes || includes.isEmpty()) {
+ directories.add(basedir);
+ } else {
+ for (Filter filter : includes) {
+ String path = filter.getPath();
+ if (".".equals(path)) {
+ directories.add(basedir);
+ } else {
+ directories.add(new File(basedir, path));
+ }
+ }
+ }
+
+ return directories;
+ }
+
private void scanForModifiedOrDeletedFiles(DriftDetectionSchedule schedule, File basedir, Set<File> processedFiles,
List<FileEntry> snapshotEntries, List<FileEntry> deltaEntries, ChangeSetReader coverageReader)
throws IOException {
@@ -312,6 +339,7 @@ public class DriftDetector implements Runnable {
}
}
+ @SuppressWarnings("unused")
private boolean isPreviousChangeSetEmpty(int resourceId, DriftDefinition definition) throws IOException {
File changeSet = changeSetMgr.findChangeSet(resourceId, definition.getName(), DRIFT);
if (!changeSet.exists()) {
@@ -337,15 +365,14 @@ public class DriftDetector implements Runnable {
}
private void updateDeltaSnapshot(DriftDetectionSummary summary, DriftDetectionSchedule schedule,
- List<FileEntry> deltaEntries, int newVersion, File oldSnapshot, File newSnapshot)
- throws IOException {
+ List<FileEntry> deltaEntries, int newVersion, File oldSnapshot, File newSnapshot) throws IOException {
ChangeSetWriter deltaWriter = null;
try {
Headers deltaHeaders = createHeaders(schedule, DRIFT, newVersion);
- File driftChangeSet = changeSetMgr.findChangeSet(schedule.getResourceId(),
- schedule.getDriftDefinition().getName(), DRIFT);
+ File driftChangeSet = changeSetMgr.findChangeSet(schedule.getResourceId(), schedule.getDriftDefinition()
+ .getName(), DRIFT);
deltaWriter = changeSetMgr.getChangeSetWriter(driftChangeSet, deltaHeaders);
summary.setDriftChangeSet(driftChangeSet);
@@ -376,10 +403,9 @@ public class DriftDetector implements Runnable {
try {
Headers snapshotHeaders = createHeaders(schedule, COVERAGE, newVersion);
- File newSnapshot = changeSetMgr.findChangeSet(schedule.getResourceId(),
- schedule.getDriftDefinition().getName(), COVERAGE);
- newSnapshotWriter = changeSetMgr.getChangeSetWriter(schedule.getResourceId(),
- snapshotHeaders);
+ File newSnapshot = changeSetMgr.findChangeSet(schedule.getResourceId(), schedule.getDriftDefinition()
+ .getName(), COVERAGE);
+ newSnapshotWriter = changeSetMgr.getChangeSetWriter(schedule.getResourceId(), snapshotHeaders);
for (FileEntry entry : snapshotEntries) {
newSnapshotWriter.write(entry);
@@ -411,19 +437,19 @@ public class DriftDetector implements Runnable {
return false;
}
switch (entry.getType()) {
- case FILE_ADDED:
- if (!entry.getNewSHA().equals(newEntry.getNewSHA())) {
- return false;
- }
- case FILE_CHANGED:
- if (!entry.getNewSHA().equals(newEntry.getNewSHA()) ||
- !entry.getOldSHA().equals(newEntry.getOldSHA())) {
- return false;
- }
- default: // FILE_REMOVED
- if (!entry.getOldSHA().equals(newEntry.getOldSHA())) {
- return false;
- }
+ case FILE_ADDED:
+ if (!entry.getNewSHA().equals(newEntry.getNewSHA())) {
+ return false;
+ }
+ case FILE_CHANGED:
+ if (!entry.getNewSHA().equals(newEntry.getNewSHA())
+ || !entry.getOldSHA().equals(newEntry.getOldSHA())) {
+ return false;
+ }
+ default: // FILE_REMOVED
+ if (!entry.getOldSHA().equals(newEntry.getOldSHA())) {
+ return false;
+ }
}
numEntries++;
}
@@ -443,9 +469,9 @@ public class DriftDetector implements Runnable {
if (!basedir.exists()) {
if (log.isWarnEnabled()) {
- log.warn("The base directory [" + basedir.getAbsolutePath() + "] for " + schedule + " does not " +
- "exist. You may want review the drift definition and verify that the value of the base " +
- "directory is in fact correct.");
+ log.warn("The base directory [" + basedir.getAbsolutePath() + "] for " + schedule + " does not "
+ + "exist. You may want review the drift definition and verify that the value of the base "
+ + "directory is in fact correct.");
}
summary.setBaseDirExists(false);
return;
@@ -477,9 +503,13 @@ public class DriftDetector implements Runnable {
}
private void doDirectoryScan(final DriftDetectionSchedule schedule, DriftDefinition driftDef, final File basedir,
- final ChangeSetWriter writer) {
- forEachFile(basedir, new FilterFileVisitor(basedir, driftDef.getIncludes(), driftDef.getExcludes(),
- new FileVisitor() {
+ final ChangeSetWriter writer) {
+
+ List<Filter> includes = driftDef.getIncludes();
+ List<Filter> excludes = driftDef.getExcludes();
+
+ for (File dir : getScanDirectories(basedir, includes)) {
+ forEachFile(dir, new FilterFileVisitor(basedir, includes, excludes, new FileVisitor() {
@Override
public void visit(File file) {
try {
@@ -501,6 +531,7 @@ public class DriftDetector implements Runnable {
}
}
}));
+ }
}
private String relativePath(File basedir, File file) {
commit be9d41a3a6e8be965b5d016bea666c38af29b31c
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Dec 5 11:08:25 2011 -0500
[Bug 760105 - Drift: Unchecking the 'File Changed' option in 'Category' drop-down in the carousel view displays Globally uncaught exception]
This had to do with the filtering leaving no eligible snapshots.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java
index 544ef81..6ccbb17 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftCarouselView.java
@@ -167,7 +167,7 @@ public class DriftCarouselView extends BookmarkableCarousel implements DetailsVi
break;
}
}
- if (null == maxSnapshotVersion || maxSnapshotVersion < carouselStart) {
+ if (null == maxSnapshotVersion || null == carouselStart || maxSnapshotVersion < carouselStart) {
maxSnapshotVersion = carouselStart;
setCarouselStartFilterMax(maxSnapshotVersion);
}
commit bfb46035204786e3e1297a41cdb1eede7e901e77
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Dec 5 16:43:27 2011 +0100
[BZ 760148] - Use the unprivileged method introduced by the commit
0589b9ee8488bd1 for BZ 694892 for obtaining the version info upon
the CLI login.
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/LoginCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/LoginCommand.java
index 3ce9598..2f4c640 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/LoginCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/LoginCommand.java
@@ -115,7 +115,7 @@ public class LoginCommand implements ClientCommand {
Subject subject = remoteClient.login(username, password);
- ProductInfo info = remoteClient.getSystemManager().getServerDetails(subject).getProductInfo();
+ ProductInfo info = remoteClient.getSystemManager().getProductInfo(subject);
String version = info.getVersion()
+ " (" + info.getBuildNumber() + ")";
client.getPrintWriter().println("Remote server version is: " + version);
commit 69e2b1d81dc42b0bfc12ee8e32b08d7b2beba38d
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri Dec 2 13:52:59 2011 -0500
[Bug 759485 - Error viewing live data in the resource metric graph portlet]
- Fixed the live graph code to throw out metric requests returning no values
- Fixed CpuComponent to return valid data on a live metric request, instead
of null.
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 01284cc..5076804 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
@@ -19,6 +19,7 @@
package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring;
import java.util.Date;
+import java.util.Iterator;
import java.util.Set;
import ca.nanometrics.gflot.client.Axis;
@@ -81,6 +82,7 @@ public class LiveGraphView extends LocatableVLayout {
private SimplePlot plot;
private Timer dataLoader;
+ @SuppressWarnings("unused")
private long min, max;
public LiveGraphView(String locatorId) {
@@ -231,7 +233,12 @@ public class LiveGraphView extends LocatableVLayout {
}
public void onSuccess(Set<MeasurementData> result) {
- MeasurementDataNumeric d = (MeasurementDataNumeric) result.iterator().next();
+ Iterator<MeasurementData> i = result.iterator();
+ if (!i.hasNext()) {
+ return;
+ }
+
+ MeasurementDataNumeric d = (MeasurementDataNumeric) i.next();
handler.add(new DataPoint(d.getTimestamp(), d.getValue()));
plot.redraw();
diff --git a/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/CpuComponent.java b/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/CpuComponent.java
index d5bc264..f045126 100644
--- a/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/CpuComponent.java
+++ b/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/CpuComponent.java
@@ -124,14 +124,15 @@ public class CpuComponent implements ResourceComponent<PlatformComponent>, Measu
CpuEntry previousCpu = cpuCache.put(property, currentCpu);
previousCpu = (null == previousCpu) ? startCpuEntry : previousCpu;
- // if for some reason the delta time is excessive then toss
- // the metric, since it depends on a reasonable interval between
- // prev and curr. This can happen due to avail down or a newly
- // activated metric. Allow up to twice the metric interval.
+ // if for some reason the delta time is excessive then toss the metric, since it depends
+ // on a reasonable interval between prev and curr. This can happen due to avail down or a newly
+ // activated metric. Allow up to twice the metric interval. If the metric interval is
+ // 0 (for a live data request) then just use a 10 minute interval.
Number num = null;
long deltaTime = currentCpu.getTimestamp() - previousCpu.getTimestamp();
+ long metricInterval = (0 < request.getInterval()) ? request.getInterval() : 600000L;
- if (deltaTime <= (2 * request.getInterval())) {
+ if (deltaTime <= (2 * metricInterval)) {
// Use the same calculation that SIGAR uses to generate the percentages. The difference is that
// we use a safe "previous" cpu record.
num = getPercentage(previousCpu.getCpu(), cpu, property);
commit 024946c9b0969f316428740a780180e1dfd322ed
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Dec 2 12:31:33 2011 -0500
Utility that examines jar files and/or directories and will print out
packages that are found in more than one jar file. To use it:
java -cp test-utils.jar org.rhq.test.DuplicatePackagesDetector <list of jar files or directories>
You can optionally set the system prop in -Drhq.verbose for extra messages.
If you do not pass in any arguments, it will default to your local maven
repo. Specifically, it will default to "$HOME/.m2/repository/orq/rhq".
diff --git a/modules/test-utils/src/main/java/org/rhq/test/DuplicatePackagesDetector.java b/modules/test-utils/src/main/java/org/rhq/test/DuplicatePackagesDetector.java
new file mode 100644
index 0000000..ec6820a
--- /dev/null
+++ b/modules/test-utils/src/main/java/org/rhq/test/DuplicatePackagesDetector.java
@@ -0,0 +1,194 @@
+package org.rhq.test;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+/**
+ * This will walk a set of jar files and directories and print out
+ * packages that are found in more than one jar file.
+ *
+ * @author John Mazzitelli
+ */
+public class DuplicatePackagesDetector {
+
+ static Visitor visitor;
+
+ static boolean verbose = Boolean.getBoolean("rhq.verbose");
+
+ private static void debug(String msg) {
+ if (verbose) {
+ System.out.println(msg);
+ }
+ }
+
+ /**
+ * Each argument is the name of a .jar file or a directory that will
+ * be walked looking for jar files.
+ */
+ public static void main(String[] args) {
+ visitor = new Visitor();
+
+ if (args.length == 0) {
+ // no arguments given, try to use the user's local maven repo of all the RHQ libraries
+ String homeEnv = System.getenv("HOME");
+ if (homeEnv != null && homeEnv.length() > 0) {
+ String s = File.separator;
+ args = new String[] { homeEnv + s + ".m2" + s + "repository" + s + "org" + s + "rhq" };
+ }
+ }
+
+ for (String arg : args) {
+ File file = new File(arg);
+ debug("Processing [" + file.getAbsolutePath() + "]...");
+ if (file.exists()) {
+ if (file.isDirectory()) {
+ processDirectory(file);
+ } else {
+ processFile(file);
+ }
+ } else {
+ System.err.println("File does not exist: " + arg);
+ }
+
+ }
+
+ // print out what we've found
+ System.out.println("======================================================================");
+ Map<String, Set<String>> map = visitor.getMap(); // key=dir (pkg) name; value=list of jars where dir is
+ for (Entry<String, Set<String>> entry : map.entrySet()) {
+ String packageName = entry.getKey();
+ Set<String> jarFiles = entry.getValue();
+ if (jarFiles.size() > 1 || verbose) {
+ System.out.println(packageName);
+ for (String jarFile : jarFiles) {
+ System.out.println("\t" + jarFile);
+ }
+ }
+ }
+ }
+
+ public static void processDirectory(File dir) {
+ File[] dirEntries = dir.listFiles();
+ if (dirEntries != null) {
+ for (File dirEntry : dirEntries) {
+ if (dirEntry.isDirectory()) {
+ processDirectory(dirEntry);
+ } else {
+ processFile(dirEntry);
+ }
+ }
+ }
+ }
+
+ public static void processFile(File file) {
+ // if its not a .jar file, ignore it
+ if (!file.getName().endsWith(".jar")) {
+ debug("Not a jar file, skipping [" + file.getAbsolutePath() + "]");
+ return;
+ }
+
+ try {
+ walkZipFile(file, visitor);
+ } catch (Exception e) {
+ System.err.println("Cannot process jar file [" + file + "]:" + e.toString());
+ }
+ }
+
+ /**
+ * Walks the entries of a zip file, allowing a listener to "visit" each node and perform tasks on
+ * the zip entry.
+ *
+ * @param zipFile the zip file to walk
+ * @param visitor the object that will be notified for each entry in the zip file
+ *
+ * @throws Exception if any errors occur during the reading or visiting
+ */
+ public static void walkZipFile(File zipFile, Visitor visitor) throws Exception {
+ FileInputStream fis = new FileInputStream(zipFile);
+ try {
+ InputStream zipContent = new BufferedInputStream(fis);
+ try {
+ ZipInputStream zis = new ZipInputStream(zipContent);
+
+ ZipEntry e;
+ while ((e = zis.getNextEntry()) != null) {
+ boolean keepGoing = visitor
+ .visit(e, zis, (verbose) ? zipFile.getAbsolutePath() : zipFile.getName());
+ if (!keepGoing) {
+ break; // visitor told us to stop
+ }
+ }
+ } finally {
+ zipContent.close();
+ }
+ } finally {
+ fis.close();
+ }
+ }
+
+ public static class Visitor {
+ // keyed on directory name - the value is all the jar files that had that directory in it
+ private Map<String, Set<String>> map = new HashMap<String, Set<String>>();
+
+ public Map<String, Set<String>> getMap() {
+ return map;
+ }
+
+ /**
+ * Visits a specific zip file entry. Implementations can read the entry content from the given stream but
+ * must <b>not</b> close the stream - the caller of this method will handle the lifecycle of the stream.
+ *
+ * @param entry the entry being visited
+ * @param stream the stream containing the zip content
+ * @param zipFilePath the actual zip file that is being walked
+ * @return the visitor should return <code>true</code> if everything is OK and processing of the zip content
+ * should continue; returning <code>false</code> will tell the walker to abort further traversing
+ * of the zip content.
+ * @throws Exception if the visitation failed for some reason - this will abort further walking of the zip content
+ */
+ public boolean visit(ZipEntry entry, ZipInputStream stream, String zipFilePath) throws Exception {
+ if (!entry.isDirectory()) {
+ String[] dirAndName = splitPathName(entry.getName());
+ if (dirAndName != null) {
+ String dirName = dirAndName[0];
+ Set<String> zipFilePaths = map.get(dirName);
+ if (zipFilePaths == null) {
+ zipFilePaths = new HashSet<String>();
+ map.put(dirName, zipFilePaths);
+ }
+ zipFilePaths.add(zipFilePath);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Splits the path from the filename and returns as a 2-dimension array.
+ * If the full name does NOT end with .class, <code>null</code> is returned.
+ * Thus, this only processes Java classes.
+ * @param fullname the name to split
+ * @return first element is the path, second element is the filename
+ */
+ private String[] splitPathName(String fullname) {
+ if (fullname.endsWith(".class")) {
+ int lastSlash = fullname.lastIndexOf('/');
+ if (lastSlash >= 0) {
+ return new String[] { fullname.substring(0, lastSlash), fullname.substring(lastSlash + 1) };
+ } else {
+ return new String[] { "", fullname };
+ }
+ } else {
+ return null;
+ }
+ }
+ }
+}
commit 2b26d4412f3fbc28f4131efa7732f3f5e31e4955
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Dec 1 18:04:18 2011 -0500
[BZ 759173] rename package name so we don't have the same package in different signed jars
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 9b18acb..74f7ab8 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
@@ -7,7 +7,7 @@ import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.util.PageList;
-import org.rhq.enterprise.client.RemoteClient;
+import org.rhq.enterprise.clientapi.RemoteClient;
import org.rhq.enterprise.server.resource.ResourceManagerRemote;
/**
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 9f91c88..77d8f24 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
@@ -12,7 +12,7 @@ import org.jboss.seam.annotations.web.RequestParameter;
import org.jboss.seam.core.Conversation;
import org.rhq.core.domain.auth.Subject;
-import org.rhq.enterprise.client.RemoteClient;
+import org.rhq.enterprise.clientapi.RemoteClient;
import org.rhq.enterprise.server.auth.SubjectManagerRemote;
/**
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 27af798..191c537 100755
--- 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
@@ -46,6 +46,7 @@ import mazz.i18n.Msg;
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.clientapi.RemoteClient;
/**
* @author Greg Hinkle
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 abbc496..f51e148 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
@@ -44,6 +44,7 @@ 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
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/LoginCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/LoginCommand.java
index cac73a2..3ce9598 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/LoginCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/LoginCommand.java
@@ -30,7 +30,7 @@ import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.common.ProductInfo;
import org.rhq.core.domain.common.ServerDetails;
import org.rhq.enterprise.client.ClientMain;
-import org.rhq.enterprise.client.RemoteClient;
+import org.rhq.enterprise.clientapi.RemoteClient;
import org.rhq.enterprise.server.system.ServerVersion;
/**
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 815629d..4120f2d 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
@@ -11,8 +11,8 @@ import java.util.ArrayList;
import org.testng.annotations.Test;
import org.rhq.enterprise.client.ClientMain;
-import org.rhq.enterprise.client.RemoteClient;
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;
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/client/RemoteClient.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/client/RemoteClient.java
deleted file mode 100644
index bb0205b..0000000
--- a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/client/RemoteClient.java
+++ /dev/null
@@ -1,506 +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.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.jboss.remoting.Client;
-import org.jboss.remoting.InvokerLocator;
-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.core.domain.auth.Subject;
-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.
- *
- * @author Greg Hinkle
- * @author Simeon Pinder
- * @author Jay Shaughnessy
- * @author John Mazzitelli
- */
-public class RemoteClient implements RhqFacade {
-
- private static final Log LOG = LogFactory.getLog(RemoteClient.class);
-
- public static final String NONSECURE_TRANSPORT = "servlet";
- public static final String SECURE_TRANSPORT = "sslservlet";
-
- private String transport;
- private final String host;
- private final int port;
- private boolean loggedIn;
- private boolean connected;
- private Map<String, Object> managers;
- private Subject subject;
- private Client remotingClient;
- private String subsystem = null;
-
- /**
- * Creates a client that will communicate with the server running on the given host
- * listening on the given port. This constructor will not attempt to connect or login
- * to the remote server - use {@link #login(String, String)} for that.
- *
- * @param host
- * @param port
- */
- public RemoteClient(String host, int port) {
- this(null, host, port);
- }
-
- /**
- * Creates a client that will communicate with the server running on the given host
- * listening on the given port over the given transport.
- * This constructor will not attempt to connect or login
- * to the remote server - use {@link #login(String, String)} for that.
- *
- * @param transport valid values are "servlet" and "sslservlet" - if <code>null</code>,
- * sslservlet will be used for ports that end with "443", servlet otherwise
- * @param host
- * @param port
- */
- public RemoteClient(String transport, String host, int port) {
- this(transport, host, port, null);
- }
-
- public RemoteClient(String transport, String host, int port, String subsystem) {
- this.transport = (transport != null) ? transport : guessTransport(port);
- this.host = host;
- this.port = port;
- this.subsystem = subsystem;
- }
-
- /**
- * Connects to the remote server and logs in with the given credentials.
- * After successfully executing this, {@link #isLoggedIn()} will be <code>true</code>
- * and {@link #getSubject()} will return the subject that this method returns.
- *
- * @param user
- * @param password
- *
- * @return the logged in user
- *
- * @throws Exception if failed to connect to the server or log in
- */
- public Subject login(String user, String password) throws Exception {
-
- logout();
- doConnect();
-
- this.subject = getSubjectManager().login(user, password);
- this.loggedIn = true;
-
- return this.subject;
- }
-
- /**
- * Logs out from the server and disconnects this client.
- */
- public void logout() {
- try {
- if (this.loggedIn && this.subject != null) {
- getSubjectManager().logout(this.subject);
- }
- } catch (Exception e) {
- // just keep going so we can disconnect this client
- }
-
- doDisconnect();
-
- this.subject = null;
- this.loggedIn = false;
- }
-
- /**
- * Connects to the remote server but does not establish a user session. This can be used
- * with the limited API that does not require a Subject.
- *
- * After successfully executing this, {@link #isConnected()} will be <code>true</code>
- * and {@link #getSubject()} will return the subject that this method returns.
- * @throws Exception if failed to connect to the server or log in
- */
- public void connect() throws Exception {
- if (this.loggedIn) {
- String name = (null == this.subject) ? "" : this.subject.getName();
- throw new IllegalStateException("User " + name + " must log out before connection can be established.");
- }
-
- doDisconnect();
- doConnect();
- this.connected = true;
- }
-
- /**
- * Disconnect from the server.
- */
- public void disconnect() {
- if (this.loggedIn) {
- String name = (null == this.subject) ? "" : this.subject.getName();
- throw new IllegalStateException("User " + name + " is logged in. Call logout() instead of disconnect().");
- }
-
- doDisconnect();
- this.connected = false;
- }
-
- /**
- * Returns <code>true</code> if and only if this client successfully connected
- * to the remote server and the user successfully logged in.
- *
- * @return if the user was able to connect and log into the server
- */
- public boolean isLoggedIn() {
- return this.loggedIn;
- }
-
- /**
- * Returns <code>true</code> if and only if this client successfully connected
- * to the remote server.
- *
- * @return if the user was able to connect and log into the server
- */
- public boolean isConnected() {
- return this.connected;
- }
-
- /**
- * Returns the information on the user that is logged in.
- * May be <code>null</code> if the user never logged in successfully.
- *
- * @return user information or <code>null</code>
- */
- public Subject getSubject() {
- return this.subject;
- }
-
- public String getHost() {
- return this.host;
- }
-
- public int getPort() {
- return this.port;
- }
-
- public String getTransport() {
- return transport;
- }
-
- protected String guessTransport(int port) {
- return String.valueOf(port).endsWith("443") ? SECURE_TRANSPORT : NONSECURE_TRANSPORT;
- }
-
- /**
- * Sets the underlying transport to use to communicate with the server.
- * Available transports are "servlet" and "sslservlet".
- * If you set it to <code>null</code>, then the transport to be used will
- * be set appropriately for the {@link #getPort()} (e.g. a secure transport
- * will be used for ports that end with 443, a non-secure transport will be
- * used for all other ports).
- *
- * @param transport
- */
- public void setTransport(String transport) {
- this.transport = transport;
- }
-
- public AlertManagerRemote getAlertManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.AlertManager);
- }
-
- public AlertDefinitionManagerRemote getAlertDefinitionManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.AlertDefinitionManager);
- }
-
- public AvailabilityManagerRemote getAvailabilityManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.AvailabilityManager);
- }
-
- public BundleManagerRemote getBundleManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.BundleManager);
- }
-
- public CallTimeDataManagerRemote getCallTimeDataManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.CallTimeDataManager);
- }
-
- public DriftManagerRemote getDriftManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.DriftManager);
- }
-
- public DriftTemplateManagerRemote getDriftTemplateManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.DriftTemplateManager);
- }
-
- public RepoManagerRemote getRepoManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.RepoManager);
- }
-
- public ConfigurationManagerRemote getConfigurationManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.ConfigurationManager);
- }
-
- public ContentManagerRemote getContentManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.ContentManager);
- }
-
- public DataAccessManagerRemote getDataAccessManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.DataAccessManager);
- }
-
- public DiscoveryBossRemote getDiscoveryBoss() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.DiscoveryBoss);
- }
-
- public EventManagerRemote getEventManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.EventManager);
- }
-
- public MeasurementBaselineManagerRemote getMeasurementBaselineManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementBaselineManager);
- }
-
- public MeasurementDataManagerRemote getMeasurementDataManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementDataManager);
- }
-
- public MeasurementDefinitionManagerRemote getMeasurementDefinitionManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementDefinitionManager);
- }
-
- public MeasurementScheduleManagerRemote getMeasurementScheduleManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementScheduleManager);
- }
-
- public OperationManagerRemote getOperationManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.OperationManager);
- }
-
- public ResourceManagerRemote getResourceManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceManager);
- }
-
- public ResourceFactoryManagerRemote getResourceFactoryManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceFactoryManager);
- }
-
- public ResourceGroupManagerRemote getResourceGroupManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceGroupManager);
- }
-
- public ResourceTypeManagerRemote getResourceTypeManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceTypeManager);
- }
-
- public RoleManagerRemote getRoleManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.RoleManager);
- }
-
- public SavedSearchManagerRemote getSavedSearchManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.SavedSearchManager);
- }
-
- public SubjectManagerRemote getSubjectManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.SubjectManager);
- }
-
- public SupportManagerRemote getSupportManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.SupportManager);
- }
-
- public SystemManagerRemote getSystemManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.SystemManager);
- }
-
- public RemoteInstallManagerRemote getRemoteInstallManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.RemoteInstallManager);
- }
-
- public TagManagerRemote getTagManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.TagManager);
- }
-
- public SynchronizationManagerRemote getSynchronizationManager() {
- return RemoteClientProxy.getProcessor(this, RhqManagers.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() {
- if (this.managers == null) {
-
- this.managers = new HashMap<String, Object>();
-
- for (RhqManagers manager : RhqManagers.values()) {
- try {
- Method m = this.getClass().getMethod("get" + manager.name());
- if (manager.enabled()) {
- this.managers.put(manager.name(), m.invoke(this));
- }
- } catch (Throwable e) {
- LOG.error("Failed to load manager " + manager + " due to missing class.", e);
- }
- }
- }
-
- return this.managers;
- }
-
- @Override
- public String toString() {
- return this.getClass().getSimpleName() + "[" + "transport=" + transport + ", host=" + host + ", port=" + port
- + ", subsystem=" + subsystem + ", connected=" + connected + ", loggedIn=" + loggedIn + ", subject="
- + subject + ']';
- }
-
- /**
- * Returns the internal JBoss/Remoting client used to perform the low-level
- * comm with the server.
- *
- * This is package-scoped so the proxy can use it.
- *
- * @return remoting client used to talk to the server
- */
- Client getRemotingClient() {
- return this.remotingClient;
- }
-
- private void doDisconnect() {
- try {
- if (this.remotingClient != null && this.remotingClient.isConnected()) {
- this.remotingClient.disconnect();
- }
- } catch (Exception e) {
- LOG.warn(e); // TODO what to do here?
- } finally {
- this.remotingClient = null;
- }
- }
-
- private void doConnect() throws Exception {
- String locatorURI = this.transport + "://" + this.host + ":" + this.port
- + "/jboss-remoting-servlet-invoker/ServerInvokerServlet";
- InvokerLocator locator = new InvokerLocator(locatorURI);
-
- String subsystem = "REMOTEAPI";
- if ((this.subsystem != null) && (this.subsystem.trim().equalsIgnoreCase("WSREMOTEAPI"))) {
- subsystem = "WSREMOTEAPI";
- }
- Map<String, String> remotingConfig = buildRemotingConfig(locatorURI);
- this.remotingClient = new Client(locator, subsystem, remotingConfig);
- this.remotingClient.connect();
- }
-
- private Map<String, String> buildRemotingConfig(String locatorURI) {
- Map<String, String> config = new HashMap<String, String>();
- if (SecurityUtil.isTransportSecure(locatorURI)) {
- setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_STORE_FILE_PATH, "data/keystore.dat");
- setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_STORE_ALGORITHM, "SunX509");
- setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_STORE_TYPE, "JKS");
- setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_STORE_PASSWORD, "password");
- setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_PASSWORD, "password");
- setConfigProp(config, SSLSocketBuilder.REMOTING_TRUST_STORE_FILE_PATH, null);
- setConfigProp(config, SSLSocketBuilder.REMOTING_TRUST_STORE_ALGORITHM, null);
- setConfigProp(config, SSLSocketBuilder.REMOTING_TRUST_STORE_TYPE, null);
- setConfigProp(config, SSLSocketBuilder.REMOTING_TRUST_STORE_PASSWORD, null);
- setConfigProp(config, SSLSocketBuilder.REMOTING_SSL_PROTOCOL, null);
- setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_ALIAS, "self");
- setConfigProp(config, SSLSocketBuilder.REMOTING_SERVER_AUTH_MODE, "false");
- config.put(SSLSocketBuilder.REMOTING_SOCKET_USE_CLIENT_MODE, "true");
-
- // since we do not know the server's client-auth mode, assume we need a keystore and let's make sure we have one
- SSLSocketBuilder dummy_sslbuilder = new SSLSocketBuilder(); // just so we can test finding our keystore
- try {
- // this allows the configured keystore file to be a URL, file path or a resource relative to our classloader
- dummy_sslbuilder.setKeyStoreURL(config.get(SSLSocketBuilder.REMOTING_KEY_STORE_FILE_PATH));
- } catch (Exception e) {
- // this probably is due to the fact that the keystore doesn't exist yet - let's prepare one now
- SecurityUtil.createKeyStore(config.get(SSLSocketBuilder.REMOTING_KEY_STORE_FILE_PATH),
- config.get(SSLSocketBuilder.REMOTING_KEY_ALIAS), "CN=RHQ, OU=RedHat, O=redhat.com, C=US",
- config.get(SSLSocketBuilder.REMOTING_KEY_STORE_PASSWORD),
- config.get(SSLSocketBuilder.REMOTING_KEY_PASSWORD), "DSA", 36500);
-
- // now try to set it again, if an exception is still thrown, it's an unrecoverable error
- dummy_sslbuilder.setKeyStoreURL(config.get(SSLSocketBuilder.REMOTING_KEY_STORE_FILE_PATH));
- }
-
- // in case the transport floats over https - we want to make sure a hostname verifier is installed and allows all hosts
- config.put(HTTPSClientInvoker.IGNORE_HTTPS_HOST, "true");
- }
- return config;
- }
-
- /**
- * Looks up the prop name in system properties and puts the value in the map. If the property
- * isn't set, the given default is used. If the given default is null and the property isn't
- * set, then the map is not populated.
- *
- * @param configMap
- * @param propName
- * @param defaultValue
- */
- private void setConfigProp(Map<String, String> configMap, String propName, String defaultValue) {
- String propValue = System.getProperty(propName, defaultValue);
- if (propValue != null) {
- configMap.put(propName, propValue);
- }
- return;
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/client/RemoteClientProxy.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/client/RemoteClientProxy.java
deleted file mode 100644
index 38dec8b..0000000
--- a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/client/RemoteClientProxy.java
+++ /dev/null
@@ -1,101 +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.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.RhqManagers;
-import org.rhq.bindings.util.InterfaceSimplifier;
-import org.rhq.core.server.ExternalizableStrategy;
-
-/**
- * This class acts as a local SLSB proxy to make remote invocations
- * to SLSB Remotes over a remoting invoker.
- *
- * @author Greg Hinkle
- * @author Lukas Krejci
- */
-public class RemoteClientProxy extends AbstractRhqFacadeProxy<RemoteClient> {
-
- private static final Log LOG = LogFactory.getLog(RemoteClientProxy.class);
-
- public RemoteClientProxy(RemoteClient client, RhqManagers manager) {
- super(client, manager);
- }
-
- public Class<?> getRemoteInterface() {
- return this.getManager().remote();
- }
-
- @SuppressWarnings("unchecked")
- public static <T> T getProcessor(RemoteClient remoteClient, RhqManagers 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);
- } catch (Throwable t) {
- LOG.debug(t);
- throw t;
- }
- }
-
- protected Object doInvoke(Object proxy, Method originalMethod, java.lang.Class<?>[] argTypes, 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;
- }
-}
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
new file mode 100644
index 0000000..0ec565e
--- /dev/null
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
@@ -0,0 +1,506 @@
+/*
+ * 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.clientapi;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.jboss.remoting.Client;
+import org.jboss.remoting.InvokerLocator;
+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.core.domain.auth.Subject;
+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.
+ *
+ * @author Greg Hinkle
+ * @author Simeon Pinder
+ * @author Jay Shaughnessy
+ * @author John Mazzitelli
+ */
+public class RemoteClient implements RhqFacade {
+
+ private static final Log LOG = LogFactory.getLog(RemoteClient.class);
+
+ public static final String NONSECURE_TRANSPORT = "servlet";
+ public static final String SECURE_TRANSPORT = "sslservlet";
+
+ private String transport;
+ private final String host;
+ private final int port;
+ private boolean loggedIn;
+ private boolean connected;
+ private Map<String, Object> managers;
+ private Subject subject;
+ private Client remotingClient;
+ private String subsystem = null;
+
+ /**
+ * Creates a client that will communicate with the server running on the given host
+ * listening on the given port. This constructor will not attempt to connect or login
+ * to the remote server - use {@link #login(String, String)} for that.
+ *
+ * @param host
+ * @param port
+ */
+ public RemoteClient(String host, int port) {
+ this(null, host, port);
+ }
+
+ /**
+ * Creates a client that will communicate with the server running on the given host
+ * listening on the given port over the given transport.
+ * This constructor will not attempt to connect or login
+ * to the remote server - use {@link #login(String, String)} for that.
+ *
+ * @param transport valid values are "servlet" and "sslservlet" - if <code>null</code>,
+ * sslservlet will be used for ports that end with "443", servlet otherwise
+ * @param host
+ * @param port
+ */
+ public RemoteClient(String transport, String host, int port) {
+ this(transport, host, port, null);
+ }
+
+ public RemoteClient(String transport, String host, int port, String subsystem) {
+ this.transport = (transport != null) ? transport : guessTransport(port);
+ this.host = host;
+ this.port = port;
+ this.subsystem = subsystem;
+ }
+
+ /**
+ * Connects to the remote server and logs in with the given credentials.
+ * After successfully executing this, {@link #isLoggedIn()} will be <code>true</code>
+ * and {@link #getSubject()} will return the subject that this method returns.
+ *
+ * @param user
+ * @param password
+ *
+ * @return the logged in user
+ *
+ * @throws Exception if failed to connect to the server or log in
+ */
+ public Subject login(String user, String password) throws Exception {
+
+ logout();
+ doConnect();
+
+ this.subject = getSubjectManager().login(user, password);
+ this.loggedIn = true;
+
+ return this.subject;
+ }
+
+ /**
+ * Logs out from the server and disconnects this client.
+ */
+ public void logout() {
+ try {
+ if (this.loggedIn && this.subject != null) {
+ getSubjectManager().logout(this.subject);
+ }
+ } catch (Exception e) {
+ // just keep going so we can disconnect this client
+ }
+
+ doDisconnect();
+
+ this.subject = null;
+ this.loggedIn = false;
+ }
+
+ /**
+ * Connects to the remote server but does not establish a user session. This can be used
+ * with the limited API that does not require a Subject.
+ *
+ * After successfully executing this, {@link #isConnected()} will be <code>true</code>
+ * and {@link #getSubject()} will return the subject that this method returns.
+ * @throws Exception if failed to connect to the server or log in
+ */
+ public void connect() throws Exception {
+ if (this.loggedIn) {
+ String name = (null == this.subject) ? "" : this.subject.getName();
+ throw new IllegalStateException("User " + name + " must log out before connection can be established.");
+ }
+
+ doDisconnect();
+ doConnect();
+ this.connected = true;
+ }
+
+ /**
+ * Disconnect from the server.
+ */
+ public void disconnect() {
+ if (this.loggedIn) {
+ String name = (null == this.subject) ? "" : this.subject.getName();
+ throw new IllegalStateException("User " + name + " is logged in. Call logout() instead of disconnect().");
+ }
+
+ doDisconnect();
+ this.connected = false;
+ }
+
+ /**
+ * Returns <code>true</code> if and only if this client successfully connected
+ * to the remote server and the user successfully logged in.
+ *
+ * @return if the user was able to connect and log into the server
+ */
+ public boolean isLoggedIn() {
+ return this.loggedIn;
+ }
+
+ /**
+ * Returns <code>true</code> if and only if this client successfully connected
+ * to the remote server.
+ *
+ * @return if the user was able to connect and log into the server
+ */
+ public boolean isConnected() {
+ return this.connected;
+ }
+
+ /**
+ * Returns the information on the user that is logged in.
+ * May be <code>null</code> if the user never logged in successfully.
+ *
+ * @return user information or <code>null</code>
+ */
+ public Subject getSubject() {
+ return this.subject;
+ }
+
+ public String getHost() {
+ return this.host;
+ }
+
+ public int getPort() {
+ return this.port;
+ }
+
+ public String getTransport() {
+ return transport;
+ }
+
+ protected String guessTransport(int port) {
+ return String.valueOf(port).endsWith("443") ? SECURE_TRANSPORT : NONSECURE_TRANSPORT;
+ }
+
+ /**
+ * Sets the underlying transport to use to communicate with the server.
+ * Available transports are "servlet" and "sslservlet".
+ * If you set it to <code>null</code>, then the transport to be used will
+ * be set appropriately for the {@link #getPort()} (e.g. a secure transport
+ * will be used for ports that end with 443, a non-secure transport will be
+ * used for all other ports).
+ *
+ * @param transport
+ */
+ public void setTransport(String transport) {
+ this.transport = transport;
+ }
+
+ public AlertManagerRemote getAlertManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.AlertManager);
+ }
+
+ public AlertDefinitionManagerRemote getAlertDefinitionManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.AlertDefinitionManager);
+ }
+
+ public AvailabilityManagerRemote getAvailabilityManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.AvailabilityManager);
+ }
+
+ public BundleManagerRemote getBundleManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.BundleManager);
+ }
+
+ public CallTimeDataManagerRemote getCallTimeDataManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.CallTimeDataManager);
+ }
+
+ public DriftManagerRemote getDriftManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.DriftManager);
+ }
+
+ public DriftTemplateManagerRemote getDriftTemplateManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.DriftTemplateManager);
+ }
+
+ public RepoManagerRemote getRepoManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.RepoManager);
+ }
+
+ public ConfigurationManagerRemote getConfigurationManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.ConfigurationManager);
+ }
+
+ public ContentManagerRemote getContentManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.ContentManager);
+ }
+
+ public DataAccessManagerRemote getDataAccessManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.DataAccessManager);
+ }
+
+ public DiscoveryBossRemote getDiscoveryBoss() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.DiscoveryBoss);
+ }
+
+ public EventManagerRemote getEventManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.EventManager);
+ }
+
+ public MeasurementBaselineManagerRemote getMeasurementBaselineManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementBaselineManager);
+ }
+
+ public MeasurementDataManagerRemote getMeasurementDataManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementDataManager);
+ }
+
+ public MeasurementDefinitionManagerRemote getMeasurementDefinitionManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementDefinitionManager);
+ }
+
+ public MeasurementScheduleManagerRemote getMeasurementScheduleManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementScheduleManager);
+ }
+
+ public OperationManagerRemote getOperationManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.OperationManager);
+ }
+
+ public ResourceManagerRemote getResourceManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceManager);
+ }
+
+ public ResourceFactoryManagerRemote getResourceFactoryManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceFactoryManager);
+ }
+
+ public ResourceGroupManagerRemote getResourceGroupManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceGroupManager);
+ }
+
+ public ResourceTypeManagerRemote getResourceTypeManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceTypeManager);
+ }
+
+ public RoleManagerRemote getRoleManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.RoleManager);
+ }
+
+ public SavedSearchManagerRemote getSavedSearchManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.SavedSearchManager);
+ }
+
+ public SubjectManagerRemote getSubjectManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.SubjectManager);
+ }
+
+ public SupportManagerRemote getSupportManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.SupportManager);
+ }
+
+ public SystemManagerRemote getSystemManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.SystemManager);
+ }
+
+ public RemoteInstallManagerRemote getRemoteInstallManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.RemoteInstallManager);
+ }
+
+ public TagManagerRemote getTagManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.TagManager);
+ }
+
+ public SynchronizationManagerRemote getSynchronizationManager() {
+ return RemoteClientProxy.getProcessor(this, RhqManagers.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() {
+ if (this.managers == null) {
+
+ this.managers = new HashMap<String, Object>();
+
+ for (RhqManagers manager : RhqManagers.values()) {
+ try {
+ Method m = this.getClass().getMethod("get" + manager.name());
+ if (manager.enabled()) {
+ this.managers.put(manager.name(), m.invoke(this));
+ }
+ } catch (Throwable e) {
+ LOG.error("Failed to load manager " + manager + " due to missing class.", e);
+ }
+ }
+ }
+
+ return this.managers;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + "[" + "transport=" + transport + ", host=" + host + ", port=" + port
+ + ", subsystem=" + subsystem + ", connected=" + connected + ", loggedIn=" + loggedIn + ", subject="
+ + subject + ']';
+ }
+
+ /**
+ * Returns the internal JBoss/Remoting client used to perform the low-level
+ * comm with the server.
+ *
+ * This is package-scoped so the proxy can use it.
+ *
+ * @return remoting client used to talk to the server
+ */
+ Client getRemotingClient() {
+ return this.remotingClient;
+ }
+
+ private void doDisconnect() {
+ try {
+ if (this.remotingClient != null && this.remotingClient.isConnected()) {
+ this.remotingClient.disconnect();
+ }
+ } catch (Exception e) {
+ LOG.warn(e); // TODO what to do here?
+ } finally {
+ this.remotingClient = null;
+ }
+ }
+
+ private void doConnect() throws Exception {
+ String locatorURI = this.transport + "://" + this.host + ":" + this.port
+ + "/jboss-remoting-servlet-invoker/ServerInvokerServlet";
+ InvokerLocator locator = new InvokerLocator(locatorURI);
+
+ String subsystem = "REMOTEAPI";
+ if ((this.subsystem != null) && (this.subsystem.trim().equalsIgnoreCase("WSREMOTEAPI"))) {
+ subsystem = "WSREMOTEAPI";
+ }
+ Map<String, String> remotingConfig = buildRemotingConfig(locatorURI);
+ this.remotingClient = new Client(locator, subsystem, remotingConfig);
+ this.remotingClient.connect();
+ }
+
+ private Map<String, String> buildRemotingConfig(String locatorURI) {
+ Map<String, String> config = new HashMap<String, String>();
+ if (SecurityUtil.isTransportSecure(locatorURI)) {
+ setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_STORE_FILE_PATH, "data/keystore.dat");
+ setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_STORE_ALGORITHM, "SunX509");
+ setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_STORE_TYPE, "JKS");
+ setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_STORE_PASSWORD, "password");
+ setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_PASSWORD, "password");
+ setConfigProp(config, SSLSocketBuilder.REMOTING_TRUST_STORE_FILE_PATH, null);
+ setConfigProp(config, SSLSocketBuilder.REMOTING_TRUST_STORE_ALGORITHM, null);
+ setConfigProp(config, SSLSocketBuilder.REMOTING_TRUST_STORE_TYPE, null);
+ setConfigProp(config, SSLSocketBuilder.REMOTING_TRUST_STORE_PASSWORD, null);
+ setConfigProp(config, SSLSocketBuilder.REMOTING_SSL_PROTOCOL, null);
+ setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_ALIAS, "self");
+ setConfigProp(config, SSLSocketBuilder.REMOTING_SERVER_AUTH_MODE, "false");
+ config.put(SSLSocketBuilder.REMOTING_SOCKET_USE_CLIENT_MODE, "true");
+
+ // since we do not know the server's client-auth mode, assume we need a keystore and let's make sure we have one
+ SSLSocketBuilder dummy_sslbuilder = new SSLSocketBuilder(); // just so we can test finding our keystore
+ try {
+ // this allows the configured keystore file to be a URL, file path or a resource relative to our classloader
+ dummy_sslbuilder.setKeyStoreURL(config.get(SSLSocketBuilder.REMOTING_KEY_STORE_FILE_PATH));
+ } catch (Exception e) {
+ // this probably is due to the fact that the keystore doesn't exist yet - let's prepare one now
+ SecurityUtil.createKeyStore(config.get(SSLSocketBuilder.REMOTING_KEY_STORE_FILE_PATH),
+ config.get(SSLSocketBuilder.REMOTING_KEY_ALIAS), "CN=RHQ, OU=RedHat, O=redhat.com, C=US",
+ config.get(SSLSocketBuilder.REMOTING_KEY_STORE_PASSWORD),
+ config.get(SSLSocketBuilder.REMOTING_KEY_PASSWORD), "DSA", 36500);
+
+ // now try to set it again, if an exception is still thrown, it's an unrecoverable error
+ dummy_sslbuilder.setKeyStoreURL(config.get(SSLSocketBuilder.REMOTING_KEY_STORE_FILE_PATH));
+ }
+
+ // in case the transport floats over https - we want to make sure a hostname verifier is installed and allows all hosts
+ config.put(HTTPSClientInvoker.IGNORE_HTTPS_HOST, "true");
+ }
+ return config;
+ }
+
+ /**
+ * Looks up the prop name in system properties and puts the value in the map. If the property
+ * isn't set, the given default is used. If the given default is null and the property isn't
+ * set, then the map is not populated.
+ *
+ * @param configMap
+ * @param propName
+ * @param defaultValue
+ */
+ private void setConfigProp(Map<String, String> configMap, String propName, String defaultValue) {
+ String propValue = System.getProperty(propName, defaultValue);
+ if (propValue != null) {
+ configMap.put(propName, propValue);
+ }
+ return;
+ }
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..a3daeb7
--- /dev/null
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java
@@ -0,0 +1,101 @@
+/*
+ * 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.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.RhqManagers;
+import org.rhq.bindings.util.InterfaceSimplifier;
+import org.rhq.core.server.ExternalizableStrategy;
+
+/**
+ * This class acts as a local SLSB proxy to make remote invocations
+ * to SLSB Remotes over a remoting invoker.
+ *
+ * @author Greg Hinkle
+ * @author Lukas Krejci
+ */
+public class RemoteClientProxy extends AbstractRhqFacadeProxy<RemoteClient> {
+
+ private static final Log LOG = LogFactory.getLog(RemoteClientProxy.class);
+
+ public RemoteClientProxy(RemoteClient client, RhqManagers manager) {
+ super(client, manager);
+ }
+
+ public Class<?> getRemoteInterface() {
+ return this.getManager().remote();
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <T> T getProcessor(RemoteClient remoteClient, RhqManagers 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);
+ } catch (Throwable t) {
+ LOG.debug(t);
+ throw t;
+ }
+ }
+
+ protected Object doInvoke(Object proxy, Method originalMethod, java.lang.Class<?>[] argTypes, 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;
+ }
+}
commit 81960e013533ee848aacc7716bf4bc254df93b2d
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu Dec 1 12:17:43 2011 -0500
[Bug 759167 - Client side exception generated when viewing empty compatible group]
This turns out to be something of a happy accident. The offending code
made an assumption that the group would not be empty. But looking more
closely it seems to me that the entire code block is unnecessary. Moreover,
it added a round trip to the DB when displaying the group level dashboard.
It was trying to determine whether to render the bundle deployment
portlet. From what I can see, this can be determined already by looking
at the type's facets. And in fact the code was already in place. So,
- removing unnecessary db round-trip code (was even being done for mixed groups)
- keeping the existing facet-based code, which seems to do the right thing
- fixing a secondary problem that displayed the bundle deployment portlet for mixed groups.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java
index ec71b3f..a50cea5 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java
@@ -246,8 +246,8 @@ public class DashboardView extends LocatableVLayout {
} else {
// TODO: i18n
Message message = new Message("There is already a dashboard named '" + trimmedName
- + "'. Please specify a name that is not already in use.", Message.Severity.Error,
- EnumSet.of(Message.Option.Transient));
+ + "'. Please specify a name that is not already in use.", Message.Severity.Error, EnumSet
+ .of(Message.Option.Transient));
CoreGUI.getMessageCenter().notify(message);
nameItem.setValue(storedDashboard.getName());
}
@@ -299,8 +299,6 @@ public class DashboardView extends LocatableVLayout {
}
});
-
-
// build the menu of valid portlets for this context, sorted by portlet name
final Menu addPortletMenu = new LocatableMenu(editForm.extendLocatorId("PortletMenu"));
LinkedHashMap<String, String> valueMap;
@@ -512,6 +510,7 @@ public class DashboardView extends LocatableVLayout {
groupMenuMap.remove(GroupOobsPortlet.KEY);
groupMenuMap.remove(GroupPkgHistoryPortlet.KEY);
groupMenuMap.remove(GroupConfigurationUpdatesPortlet.KEY);
+ groupMenuMap.remove(GroupBundleDeploymentsPortlet.KEY);
} else {
// for compatible may still need to do some pruning.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/summary/ActivityView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/summary/ActivityView.java
index 09abe9d..991098e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/summary/ActivityView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/summary/ActivityView.java
@@ -18,11 +18,9 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.summary;
-import java.util.HashMap;
import java.util.Map;
import java.util.Set;
-import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.util.BooleanCallback;
import com.smartgwt.client.util.SC;
@@ -36,16 +34,11 @@ import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.common.EntityContext;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.criteria.DashboardCriteria;
-import org.rhq.core.domain.criteria.ResourceGroupCriteria;
import org.rhq.core.domain.dashboard.Dashboard;
import org.rhq.core.domain.dashboard.DashboardCategory;
import org.rhq.core.domain.dashboard.DashboardPortlet;
-import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.resource.ResourceCategory;
-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.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.InitializableView;
@@ -55,7 +48,6 @@ import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
import org.rhq.enterprise.gui.coregui.client.dashboard.DashboardContainer;
import org.rhq.enterprise.gui.coregui.client.dashboard.DashboardView;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.groups.GroupAlertsPortlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.groups.GroupBundleDeploymentsPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.groups.GroupConfigurationUpdatesPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.groups.GroupMetricsPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.groups.GroupOperationsPortlet;
@@ -212,44 +204,6 @@ public class ActivityView extends LocatableVLayout implements DashboardContainer
//figure out which portlets to display and how
Map<String, String> groupKeyNameMap = DashboardView.processPortletNameMapForGroup(groupComposite);
- //initiate asynch call to execute and then update the dashboard with bundle deployment portlet if necessary
- ResourceGroupCriteria criteria = new ResourceGroupCriteria();
- criteria.addFilterId(group.getId());
- criteria.fetchExplicitResources(true);
- criteria.setPageControl(new PageControl(0, 1));
- GWTServiceLookup.getResourceGroupService().findResourceGroupsByCriteria(criteria,
- new AsyncCallback<PageList<ResourceGroup>>() {
- @Override
- public void onSuccess(PageList<ResourceGroup> results) {
- if (!results.isEmpty()) {
- ResourceGroup grp = results.get(0);
- Set<Resource> explicitMembers = grp.getExplicitResources();
- Resource[] currentResources = new Resource[explicitMembers.size()];
- explicitMembers.toArray(currentResources);
- Map<String, String> portletToAdd = new HashMap<String, String>();
- //membership dynamically determined if all platforms then will be compatible.
- if (group.getGroupCategory().equals(GroupCategory.COMPATIBLE)) {
- if (currentResources[0].getResourceType().getCategory().equals(ResourceCategory.PLATFORM)) {
- //this portlet allowed to add bundle portlet monitoring
- portletToAdd.put(GroupBundleDeploymentsPortlet.KEY, GroupBundleDeploymentsPortlet.NAME);
- }
- if (!portletToAdd.isEmpty()) {
- //update dashboard with that portlet and reload
- updateDashboardWithPortlets(portletToAdd, dashboard, 100);
- //request reload of dashboard widget
- setDashboard(dashboard);
- markForRedraw();
- }
- }
- }
- }
-
- @Override
- public void onFailure(Throwable caught) {
- Log.debug("Error retrieving information for group [" + group.getId() + "]:" + caught.getMessage());
- }
- });
-
//reset positioning parameters
colLeft = 0;
colRight = 1;
commit 49eaa2bfe7d58efad3881522715f288d2ee01763
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Sun Nov 27 21:32:54 2011 +0100
Adapt the examples to the latest changes in the API.
Make the simple examples more stable by selecting active schedules via ajax callbacks.
Move whisker() into the rhq namespace.
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/bars_simple.html b/modules/enterprise/gui/rest-war/src/main/webapp/bars_simple.html
index 710b19b..e4e96d9 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/bars_simple.html
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/bars_simple.html
@@ -3,6 +3,7 @@
<head>
<title>Bar Chart</title>
<script type="text/javascript" src="js/d3.js"></script>
+ <script type="text/javascript" src="js/jquery.js"></script>
<style type="text/css">
body {
@@ -16,107 +17,114 @@ svg {
</style>
</head>
<body>
- <h2>Schedule id 10003</h2>
+ <h1 id="resId">Resource</h1>
+ <h2 id="header">Schedule</h2>
<script type="text/javascript">
-//var data = d3.range(60).map(Math.random);
-
-d3.json(
- '/rest/1/metric/data/10003.json',
- function (jsondata) {
-
- // create the chart here with
- // the returned data
-
-// console.log(jsondata);
- var points = jsondata.metricAggregate.dataPoints;
- var min = jsondata.metricAggregate.min;
- var max = jsondata.metricAggregate.max;
-
- console.log(min);
- console.log(max);
-
- console.log(points);
-
- var data = points.map(function(d) {
- var t = d.value - min;
- if (t<0)
- t=0;
- return t;
- });
- console.log(data);
-
-
-
-var w = 430,
- h = 630,
- x = d3.scale.linear().domain([0, max-min]).range([0, w]),
- y = d3.scale.ordinal().domain(d3.range(data.length)).rangeBands([0, h], .2);
-
-var vis = d3.select("body")
- .append("svg:svg")
- .attr("width", w + 40)
- .attr("height", h + 20)
- .append("svg:g")
- .attr("transform", "translate(20,0)");
-
-var bars = vis.selectAll("g.bar")
- .data(data)
- .enter().append("svg:g")
- .attr("class", "bar")
- .attr("transform", function(d, i) { return "translate(0," + y(i) + ")"; });
-
-bars.append("svg:rect")
- .attr("fill", "steelblue")
- .attr("width", x)
- .attr("height", y.rangeBand());
-
-bars.append("svg:text")
- .attr("x", x)
- .attr("y", y.rangeBand() / 2)
- .attr("dx", -6)
- .attr("dy", ".35em")
- .attr("fill", "white")
- .attr("text-anchor", "end")
- .text(x.tickFormat(100));
-
-bars.append("svg:text")
- .attr("x", 0)
- .attr("y", y.rangeBand() / 2)
- .attr("dx", -6)
- .attr("dy", ".35em")
- .attr("text-anchor", "end")
- .text(function(d, i) { return String.fromCharCode(65 + i); });
-
-var rules = vis.selectAll("g.rule")
- .data(x.ticks(10))
- .enter().append("svg:g")
- .attr("class", "rule")
- .attr("transform", function(d) { return "translate(" + x(d) + ",0)"; });
-
-rules.append("svg:line")
- .attr("y1", h)
- .attr("y2", h + 6)
- .attr("stroke", "black");
-
-rules.append("svg:line")
- .attr("y1", 0)
- .attr("y2", h)
- .attr("stroke", "white")
- .attr("stroke-opacity", .3);
-
-rules.append("svg:text")
- .attr("y", h + 9)
- .attr("dy", ".71em")
- .attr("text-anchor", "middle")
- .text(x.tickFormat(10));
-
-vis.append("svg:line")
- .attr("y1", 0)
- .attr("y2", h)
- .attr("stroke", "black");
-
- });
+ // Get the platforms and then the first one
+ $.getJSON('/rest/1/resource/platforms.json', function (json) {
+ var res = json[0];
+ var rid = res.resourceId;
+ $("#resId").text("Resource " + rid + " (" + res.resourceName + ")");
+
+ // Now get the metrical schedules of the platform
+ $.getJSON("/rest/1/resource/"+rid+"/schedules.json?type=metric", function (json2) {
+
+ // Take the first
+ var schId = json2[0].scheduleId;
+ $("#header").text("Schedule " + schId + " (" + json2[0].scheduleName + ")");
+
+ // And call d3 graphing on it
+ d3.json(
+ '/rest/1/metric/data/'+schId+'.json',
+ function (jsondata) {
+
+ // create the chart here with
+ // the returned data
+
+ var points = jsondata.dataPoints;
+ var min = jsondata.min;
+ var max = jsondata.max;
+
+ var data = points.map(function(d) {
+ var t = d.value - min;
+ if (t<0)
+ t=0;
+ return t;
+ });
+
+ var w = 430,
+ h = 630,
+ x = d3.scale.linear().domain([0, max-min]).range([0, w]),
+ y = d3.scale.ordinal().domain(d3.range(data.length)).rangeBands([0, h], .2);
+
+ var vis = d3.select("body")
+ .append("svg:svg")
+ .attr("width", w + 40)
+ .attr("height", h + 20)
+ .append("svg:g")
+ .attr("transform", "translate(20,0)");
+
+ var bars = vis.selectAll("g.bar")
+ .data(data)
+ .enter().append("svg:g")
+ .attr("class", "bar")
+ .attr("transform", function(d, i) { return "translate(0," + y(i) + ")"; });
+
+ bars.append("svg:rect")
+ .attr("fill", "steelblue")
+ .attr("width", x)
+ .attr("height", y.rangeBand());
+
+ bars.append("svg:text")
+ .attr("x", x)
+ .attr("y", y.rangeBand() / 2)
+ .attr("dx", -6)
+ .attr("dy", ".35em")
+ .attr("fill", "white")
+ .attr("text-anchor", "end")
+ .text(x.tickFormat(100));
+
+ bars.append("svg:text")
+ .attr("x", 0)
+ .attr("y", y.rangeBand() / 2)
+ .attr("dx", -6)
+ .attr("dy", ".35em")
+ .attr("text-anchor", "end")
+ .text(function(d, i) { return String.fromCharCode(65 + i); });
+
+ var rules = vis.selectAll("g.rule")
+ .data(x.ticks(10))
+ .enter().append("svg:g")
+ .attr("class", "rule")
+ .attr("transform", function(d) { return "translate(" + x(d) + ",0)"; });
+
+ rules.append("svg:line")
+ .attr("y1", h)
+ .attr("y2", h + 6)
+ .attr("stroke", "black");
+
+ rules.append("svg:line")
+ .attr("y1", 0)
+ .attr("y2", h)
+ .attr("stroke", "white")
+ .attr("stroke-opacity", .3);
+
+ rules.append("svg:text")
+ .attr("y", h + 9)
+ .attr("dy", ".71em")
+ .attr("text-anchor", "middle")
+ .text(x.tickFormat(10));
+
+ vis.append("svg:line")
+ .attr("y1", 0)
+ .attr("y2", h)
+ .attr("stroke", "black");
+
+ });
+
+ })
+ })
</script>
</body>
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/js/jquery.js b/modules/enterprise/gui/rest-war/src/main/webapp/js/jquery.js
new file mode 100644
index 0000000..8ccd0ea
--- /dev/null
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/js/jquery.js
@@ -0,0 +1,9266 @@
+/*!
+ * jQuery JavaScript Library v1.7.1
+ * http://jquery.com/
+ *
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Mon Nov 21 21:11:03 2011 -0500
+ */
+(function( window, undefined ) {
+
+// Use the correct document accordingly with window argument (sandbox)
+var document = window.document,
+ navigator = window.navigator,
+ location = window.location;
+var jQuery = (function() {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context, rootjQuery );
+ },
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ // A central reference to the root jQuery(document)
+ rootjQuery,
+
+ // A simple way to check for HTML strings or ID strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
+
+ // Check if a string has a non-whitespace character in it
+ rnotwhite = /\S/,
+
+ // Used for trimming whitespace
+ trimLeft = /^\s+/,
+ trimRight = /\s+$/,
+
+ // Match a standalone tag
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+
+ // JSON RegExp
+ rvalidchars = /^[\],:{}\s]*$/,
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+ rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+
+ // Useragent RegExp
+ rwebkit = /(webkit)[ \/]([\w.]+)/,
+ ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
+ rmsie = /(msie) ([\w.]+)/,
+ rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
+
+ // Matches dashed string for camelizing
+ rdashAlpha = /-([a-z]|[0-9])/ig,
+ rmsPrefix = /^-ms-/,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return ( letter + "" ).toUpperCase();
+ },
+
+ // Keep a UserAgent string for use with jQuery.browser
+ userAgent = navigator.userAgent,
+
+ // For matching the engine and version of the browser
+ browserMatch,
+
+ // The deferred used on DOM ready
+ readyList,
+
+ // The ready event handler
+ DOMContentLoaded,
+
+ // Save a reference to some core methods
+ toString = Object.prototype.toString,
+ hasOwn = Object.prototype.hasOwnProperty,
+ push = Array.prototype.push,
+ slice = Array.prototype.slice,
+ trim = String.prototype.trim,
+ indexOf = Array.prototype.indexOf,
+
+ // [[Class]] -> type pairs
+ class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+ constructor: jQuery,
+ init: function( selector, context, rootjQuery ) {
+ var match, elem, ret, doc;
+
+ // Handle $(""), $(null), or $(undefined)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle $(DOMElement)
+ if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+ }
+
+ // The body element only exists once, optimize finding it
+ if ( selector === "body" && !context && document.body ) {
+ this.context = document;
+ this[0] = document.body;
+ this.selector = selector;
+ this.length = 1;
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ // Are we dealing with HTML string or an ID?
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = quickExpr.exec( selector );
+ }
+
+ // Verify a match, and that no context was specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+ doc = ( context ? context.ownerDocument || context : document );
+
+ // If a single string is passed in and it's a single tag
+ // just do a createElement and skip the rest
+ ret = rsingleTag.exec( selector );
+
+ if ( ret ) {
+ if ( jQuery.isPlainObject( context ) ) {
+ selector = [ document.createElement( ret[1] ) ];
+ jQuery.fn.attr.call( selector, context, true );
+
+ } else {
+ selector = [ doc.createElement( ret[1] ) ];
+ }
+
+ } else {
+ ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
+ selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
+ }
+
+ return jQuery.merge( this, selector );
+
+ // HANDLE: $("#id")
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The current version of jQuery being used
+ jquery: "1.7.1",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
+
+ toArray: function() {
+ return slice.call( this, 0 );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num == null ?
+
+ // Return a 'clean' array
+ this.toArray() :
+
+ // Return just the object
+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems, name, selector ) {
+ // Build a new jQuery matched element set
+ var ret = this.constructor();
+
+ if ( jQuery.isArray( elems ) ) {
+ push.apply( ret, elems );
+
+ } else {
+ jQuery.merge( ret, elems );
+ }
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+
+ ret.context = this.context;
+
+ if ( name === "find" ) {
+ ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
+ } else if ( name ) {
+ ret.selector = this.selector + "." + name + "(" + selector + ")";
+ }
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ ready: function( fn ) {
+ // Attach the listeners
+ jQuery.bindReady();
+
+ // Add the callback
+ readyList.add( fn );
+
+ return this;
+ },
+
+ eq: function( i ) {
+ i = +i;
+ return i === -1 ?
+ this.slice( i ) :
+ this.slice( i, i + 1 );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ),
+ "slice", slice.call(arguments).join(",") );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: [].sort,
+ splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( length === i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ noConflict: function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+ },
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+ // Either a released hold or an DOMready/load event and not yet ready
+ if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready, 1 );
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.fireWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.trigger ) {
+ jQuery( document ).trigger( "ready" ).off( "ready" );
+ }
+ }
+ },
+
+ bindReady: function() {
+ if ( readyList ) {
+ return;
+ }
+
+ readyList = jQuery.Callbacks( "once memory" );
+
+ // Catch cases where $(document).ready() is called after the
+ // browser event has already occurred.
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ return setTimeout( jQuery.ready, 1 );
+ }
+
+ // Mozilla, Opera and webkit nightlies currently support this event
+ if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", jQuery.ready, false );
+
+ // If IE event model is used
+ } else if ( document.attachEvent ) {
+ // ensure firing before onload,
+ // maybe late but safe also for iframes
+ document.attachEvent( "onreadystatechange", DOMContentLoaded );
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", jQuery.ready );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var toplevel = false;
+
+ try {
+ toplevel = window.frameElement == null;
+ } catch(e) {}
+
+ if ( document.documentElement.doScroll && toplevel ) {
+ doScrollCheck();
+ }
+ }
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray || function( obj ) {
+ return jQuery.type(obj) === "array";
+ },
+
+ // A crude way of determining if an object is a window
+ isWindow: function( obj ) {
+ return obj && typeof obj === "object" && "setInterval" in obj;
+ },
+
+ isNumeric: function( obj ) {
+ return !isNaN( parseFloat(obj) ) && isFinite( obj );
+ },
+
+ type: function( obj ) {
+ return obj == null ?
+ String( obj ) :
+ class2type[ toString.call(obj) ] || "object";
+ },
+
+ isPlainObject: function( obj ) {
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ try {
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !hasOwn.call(obj, "constructor") &&
+ !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+ } catch ( e ) {
+ // IE8,9 Will throw exceptions on certain host objects #9897
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+
+ var key;
+ for ( key in obj ) {}
+
+ return key === undefined || hasOwn.call( obj, key );
+ },
+
+ isEmptyObject: function( obj ) {
+ for ( var name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ parseJSON: function( data ) {
+ if ( typeof data !== "string" || !data ) {
+ return null;
+ }
+
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
+ data = jQuery.trim( data );
+
+ // Attempt to parse using the native JSON parser first
+ if ( window.JSON && window.JSON.parse ) {
+ return window.JSON.parse( data );
+ }
+
+ // Make sure the incoming data is actual JSON
+ // Logic borrowed from http://json.org/json2.js
+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+ .replace( rvalidtokens, "]" )
+ .replace( rvalidbraces, "")) ) {
+
+ return ( new Function( "return " + data ) )();
+
+ }
+ jQuery.error( "Invalid JSON: " + data );
+ },
+
+ // Cross-browser xml parsing
+ parseXML: function( data ) {
+ var xml, tmp;
+ try {
+ if ( window.DOMParser ) { // Standard
+ tmp = new DOMParser();
+ xml = tmp.parseFromString( data , "text/xml" );
+ } else { // IE
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
+ xml.async = "false";
+ xml.loadXML( data );
+ }
+ } catch( e ) {
+ xml = undefined;
+ }
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+ },
+
+ noop: function() {},
+
+ // Evaluates a script in a global context
+ // Workarounds based on findings by Jim Driscoll
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-...
+ globalEval: function( data ) {
+ if ( data && rnotwhite.test( data ) ) {
+ // We use execScript on Internet Explorer
+ // We use an anonymous function so that context is window
+ // rather than jQuery in Firefox
+ ( window.execScript || function( data ) {
+ window[ "eval" ].call( window, data );
+ } )( data );
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+ },
+
+ // args is for internal usage only
+ each: function( object, callback, args ) {
+ var name, i = 0,
+ length = object.length,
+ isObj = length === undefined || jQuery.isFunction( object );
+
+ if ( args ) {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.apply( object[ name ], args ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.apply( object[ i++ ], args ) === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return object;
+ },
+
+ // Use native String.trim function wherever possible
+ trim: trim ?
+ function( text ) {
+ return text == null ?
+ "" :
+ trim.call( text );
+ } :
+
+ // Otherwise use our own trimming functionality
+ function( text ) {
+ return text == null ?
+ "" :
+ text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( array, results ) {
+ var ret = results || [];
+
+ if ( array != null ) {
+ // The window, strings (and functions) also have 'length'
+ // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+ var type = jQuery.type( array );
+
+ if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
+ push.call( ret, array );
+ } else {
+ jQuery.merge( ret, array );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, array, i ) {
+ var len;
+
+ if ( array ) {
+ if ( indexOf ) {
+ return indexOf.call( array, elem, i );
+ }
+
+ len = array.length;
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+ for ( ; i < len; i++ ) {
+ // Skip accessing in sparse arrays
+ if ( i in array && array[ i ] === elem ) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ var i = first.length,
+ j = 0;
+
+ if ( typeof second.length === "number" ) {
+ for ( var l = second.length; j < l; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+
+ } else {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var ret = [], retVal;
+ inv = !!inv;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
+ retVal = !!callback( elems[ i ], i );
+ if ( inv !== retVal ) {
+ ret.push( elems[ i ] );
+ }
+ }
+
+ return ret;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value, key, ret = [],
+ i = 0,
+ length = elems.length,
+ // jquery objects are treated as arrays
+ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
+
+ // Go through the array, translating each of the items to their
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( key in elems ) {
+ value = callback( elems[ key ], key, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return ret.concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ if ( typeof context === "string" ) {
+ var tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ var args = slice.call( arguments, 2 ),
+ proxy = function() {
+ return fn.apply( context, args.concat( slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ // Mutifunctional method to get and set values to a collection
+ // The value/s can optionally be executed if it's a function
+ access: function( elems, key, value, exec, fn, pass ) {
+ var length = elems.length;
+
+ // Setting many attributes
+ if ( typeof key === "object" ) {
+ for ( var k in key ) {
+ jQuery.access( elems, k, key[k], exec, fn, value );
+ }
+ return elems;
+ }
+
+ // Setting one attribute
+ if ( value !== undefined ) {
+ // Optionally, function values get executed if exec is true
+ exec = !pass && exec && jQuery.isFunction(value);
+
+ for ( var i = 0; i < length; i++ ) {
+ fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+ }
+
+ return elems;
+ }
+
+ // Getting an attribute
+ return length ? fn( elems[0], key ) : undefined;
+ },
+
+ now: function() {
+ return ( new Date() ).getTime();
+ },
+
+ // Use of jQuery.browser is frowned upon.
+ // More details: http://docs.jquery.com/Utilities/jQuery.browser
+ uaMatch: function( ua ) {
+ ua = ua.toLowerCase();
+
+ var match = rwebkit.exec( ua ) ||
+ ropera.exec( ua ) ||
+ rmsie.exec( ua ) ||
+ ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
+ [];
+
+ return { browser: match[1] || "", version: match[2] || "0" };
+ },
+
+ sub: function() {
+ function jQuerySub( selector, context ) {
+ return new jQuerySub.fn.init( selector, context );
+ }
+ jQuery.extend( true, jQuerySub, this );
+ jQuerySub.superclass = this;
+ jQuerySub.fn = jQuerySub.prototype = this();
+ jQuerySub.fn.constructor = jQuerySub;
+ jQuerySub.sub = this.sub;
+ jQuerySub.fn.init = function init( selector, context ) {
+ if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
+ context = jQuerySub( context );
+ }
+
+ return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
+ };
+ jQuerySub.fn.init.prototype = jQuerySub.fn;
+ var rootjQuerySub = jQuerySub(document);
+ return jQuerySub;
+ },
+
+ browser: {}
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+browserMatch = jQuery.uaMatch( userAgent );
+if ( browserMatch.browser ) {
+ jQuery.browser[ browserMatch.browser ] = true;
+ jQuery.browser.version = browserMatch.version;
+}
+
+// Deprecated, use jQuery.browser.webkit instead
+if ( jQuery.browser.webkit ) {
+ jQuery.browser.safari = true;
+}
+
+// IE doesn't match non-breaking spaces with \s
+if ( rnotwhite.test( "\xA0" ) ) {
+ trimLeft = /^[\s\xA0]+/;
+ trimRight = /[\s\xA0]+$/;
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+
+// Cleanup functions for the document ready method
+if ( document.addEventListener ) {
+ DOMContentLoaded = function() {
+ document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+ jQuery.ready();
+ };
+
+} else if ( document.attachEvent ) {
+ DOMContentLoaded = function() {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( document.readyState === "complete" ) {
+ document.detachEvent( "onreadystatechange", DOMContentLoaded );
+ jQuery.ready();
+ }
+ };
+}
+
+// The DOM ready check for Internet Explorer
+function doScrollCheck() {
+ if ( jQuery.isReady ) {
+ return;
+ }
+
+ try {
+ // If IE is used, use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ document.documentElement.doScroll("left");
+ } catch(e) {
+ setTimeout( doScrollCheck, 1 );
+ return;
+ }
+
+ // and execute any waiting functions
+ jQuery.ready();
+}
+
+return jQuery;
+
+})();
+
+
+// String to Object flags format cache
+var flagsCache = {};
+
+// Convert String-formatted flags into Object-formatted ones and store in cache
+function createFlags( flags ) {
+ var object = flagsCache[ flags ] = {},
+ i, length;
+ flags = flags.split( /\s+/ );
+ for ( i = 0, length = flags.length; i < length; i++ ) {
+ object[ flags[i] ] = true;
+ }
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * flags: an optional list of space-separated flags that will change how
+ * the callback list behaves
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible flags:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( flags ) {
+
+ // Convert flags from String-formatted to Object-formatted
+ // (we check in cache first)
+ flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
+
+ var // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = [],
+ // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list is currently firing
+ firing,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // Add one or several callbacks to the list
+ add = function( args ) {
+ var i,
+ length,
+ elem,
+ type,
+ actual;
+ for ( i = 0, length = args.length; i < length; i++ ) {
+ elem = args[ i ];
+ type = jQuery.type( elem );
+ if ( type === "array" ) {
+ // Inspect recursively
+ add( elem );
+ } else if ( type === "function" ) {
+ // Add if not in unique mode and callback is not in
+ if ( !flags.unique || !self.has( elem ) ) {
+ list.push( elem );
+ }
+ }
+ }
+ },
+ // Fire callbacks
+ fire = function( context, args ) {
+ args = args || [];
+ memory = !flags.memory || [ context, args ];
+ firing = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
+ memory = true; // Mark as halted
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( !flags.once ) {
+ if ( stack && stack.length ) {
+ memory = stack.shift();
+ self.fireWith( memory[ 0 ], memory[ 1 ] );
+ }
+ } else if ( memory === true ) {
+ self.disable();
+ } else {
+ list = [];
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ var length = list.length;
+ add( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we're not firing then
+ // we should call right away, unless previous
+ // firing was halted (stopOnFalse)
+ } else if ( memory && memory !== true ) {
+ firingStart = length;
+ fire( memory[ 0 ], memory[ 1 ] );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ var args = arguments,
+ argIndex = 0,
+ argLength = args.length;
+ for ( ; argIndex < argLength ; argIndex++ ) {
+ for ( var i = 0; i < list.length; i++ ) {
+ if ( args[ argIndex ] === list[ i ] ) {
+ // Handle firingIndex and firingLength
+ if ( firing ) {
+ if ( i <= firingLength ) {
+ firingLength--;
+ if ( i <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ // Remove the element
+ list.splice( i--, 1 );
+ // If we have some unicity property then
+ // we only need to do this once
+ if ( flags.unique ) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ return this;
+ },
+ // Control if a given callback is in the list
+ has: function( fn ) {
+ if ( list ) {
+ var i = 0,
+ length = list.length;
+ for ( ; i < length; i++ ) {
+ if ( fn === list[ i ] ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory || memory === true ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( stack ) {
+ if ( firing ) {
+ if ( !flags.once ) {
+ stack.push( [ context, args ] );
+ }
+ } else if ( !( flags.once && memory ) ) {
+ fire( context, args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!memory;
+ }
+ };
+
+ return self;
+};
+
+
+
+
+var // Static reference to slice
+ sliceDeferred = [].slice;
+
+jQuery.extend({
+
+ Deferred: function( func ) {
+ var doneList = jQuery.Callbacks( "once memory" ),
+ failList = jQuery.Callbacks( "once memory" ),
+ progressList = jQuery.Callbacks( "memory" ),
+ state = "pending",
+ lists = {
+ resolve: doneList,
+ reject: failList,
+ notify: progressList
+ },
+ promise = {
+ done: doneList.add,
+ fail: failList.add,
+ progress: progressList.add,
+
+ state: function() {
+ return state;
+ },
+
+ // Deprecated
+ isResolved: doneList.fired,
+ isRejected: failList.fired,
+
+ then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
+ deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
+ return this;
+ },
+ always: function() {
+ deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
+ return this;
+ },
+ pipe: function( fnDone, fnFail, fnProgress ) {
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( {
+ done: [ fnDone, "resolve" ],
+ fail: [ fnFail, "reject" ],
+ progress: [ fnProgress, "notify" ]
+ }, function( handler, data ) {
+ var fn = data[ 0 ],
+ action = data[ 1 ],
+ returned;
+ if ( jQuery.isFunction( fn ) ) {
+ deferred[ handler ](function() {
+ returned = fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
+ } else {
+ newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
+ }
+ });
+ } else {
+ deferred[ handler ]( newDefer[ action ] );
+ }
+ });
+ }).promise();
+ },
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ if ( obj == null ) {
+ obj = promise;
+ } else {
+ for ( var key in promise ) {
+ obj[ key ] = promise[ key ];
+ }
+ }
+ return obj;
+ }
+ },
+ deferred = promise.promise({}),
+ key;
+
+ for ( key in lists ) {
+ deferred[ key ] = lists[ key ].fire;
+ deferred[ key + "With" ] = lists[ key ].fireWith;
+ }
+
+ // Handle state
+ deferred.done( function() {
+ state = "resolved";
+ }, failList.disable, progressList.lock ).fail( function() {
+ state = "rejected";
+ }, doneList.disable, progressList.lock );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( firstParam ) {
+ var args = sliceDeferred.call( arguments, 0 ),
+ i = 0,
+ length = args.length,
+ pValues = new Array( length ),
+ count = length,
+ pCount = length,
+ deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
+ firstParam :
+ jQuery.Deferred(),
+ promise = deferred.promise();
+ function resolveFunc( i ) {
+ return function( value ) {
+ args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+ if ( !( --count ) ) {
+ deferred.resolveWith( deferred, args );
+ }
+ };
+ }
+ function progressFunc( i ) {
+ return function( value ) {
+ pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+ deferred.notifyWith( promise, pValues );
+ };
+ }
+ if ( length > 1 ) {
+ for ( ; i < length; i++ ) {
+ if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
+ args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
+ } else {
+ --count;
+ }
+ }
+ if ( !count ) {
+ deferred.resolveWith( deferred, args );
+ }
+ } else if ( deferred !== firstParam ) {
+ deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
+ }
+ return promise;
+ }
+});
+
+
+
+
+jQuery.support = (function() {
+
+ var support,
+ all,
+ a,
+ select,
+ opt,
+ input,
+ marginDiv,
+ fragment,
+ tds,
+ events,
+ eventName,
+ i,
+ isSupported,
+ div = document.createElement( "div" ),
+ documentElement = document.documentElement;
+
+ // Preliminary tests
+ div.setAttribute("className", "t");
+ div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+
+ all = div.getElementsByTagName( "*" );
+ a = div.getElementsByTagName( "a" )[ 0 ];
+
+ // Can't get basic test support
+ if ( !all || !all.length || !a ) {
+ return {};
+ }
+
+ // First batch of supports tests
+ select = document.createElement( "select" );
+ opt = select.appendChild( document.createElement("option") );
+ input = div.getElementsByTagName( "input" )[ 0 ];
+
+ support = {
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: ( div.firstChild.nodeType === 3 ),
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText instead)
+ style: /top/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: ( a.getAttribute("href") === "/a" ),
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ // Use a regex to work around a WebKit issue. See #5145
+ opacity: /^0.55/.test( a.style.opacity ),
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Make sure that if no value is specified for a checkbox
+ // that it defaults to "on".
+ // (WebKit defaults to "" instead)
+ checkOn: ( input.value === "on" ),
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ optSelected: opt.selected,
+
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+ getSetAttribute: div.className !== "t",
+
+ // Tests for enctype support on a form(#6743)
+ enctype: !!document.createElement("form").enctype,
+
+ // Makes sure cloning an html5 element does not cause problems
+ // Where outerHTML is undefined, this still works
+ html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
+
+ // Will be defined later
+ submitBubbles: true,
+ changeBubbles: true,
+ focusinBubbles: false,
+ deleteExpando: true,
+ noCloneEvent: true,
+ inlineBlockNeedsLayout: false,
+ shrinkWrapBlocks: false,
+ reliableMarginRight: true
+ };
+
+ // Make sure checked status is properly cloned
+ input.checked = true;
+ support.noCloneChecked = input.cloneNode( true ).checked;
+
+ // Make sure that the options inside disabled selects aren't marked as disabled
+ // (WebKit marks them as disabled)
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Test to see if it's possible to delete an expando from an element
+ // Fails in Internet Explorer
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+
+ if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
+ div.attachEvent( "onclick", function() {
+ // Cloning a node shouldn't copy over any
+ // bound event handlers (IE does this)
+ support.noCloneEvent = false;
+ });
+ div.cloneNode( true ).fireEvent( "onclick" );
+ }
+
+ // Check if a radio maintains its value
+ // after being appended to the DOM
+ input = document.createElement("input");
+ input.value = "t";
+ input.setAttribute("type", "radio");
+ support.radioValue = input.value === "t";
+
+ input.setAttribute("checked", "checked");
+ div.appendChild( input );
+ fragment = document.createDocumentFragment();
+ fragment.appendChild( div.lastChild );
+
+ // WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Check if a disconnected checkbox will retain its checked
+ // value of true after appended to the DOM (IE6/7)
+ support.appendChecked = input.checked;
+
+ fragment.removeChild( input );
+ fragment.appendChild( div );
+
+ div.innerHTML = "";
+
+ // Check if div with explicit width and no margin-right incorrectly
+ // gets computed margin-right based on width of container. For more
+ // info see bug #3333
+ // Fails in WebKit before Feb 2011 nightlies
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ if ( window.getComputedStyle ) {
+ marginDiv = document.createElement( "div" );
+ marginDiv.style.width = "0";
+ marginDiv.style.marginRight = "0";
+ div.style.width = "2px";
+ div.appendChild( marginDiv );
+ support.reliableMarginRight =
+ ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
+ }
+
+ // Technique from Juriy Zaytsev
+ // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
+ // We only care about the case where non-standard event systems
+ // are used, namely in IE. Short-circuiting here helps us to
+ // avoid an eval call (in setAttribute) which can cause CSP
+ // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
+ if ( div.attachEvent ) {
+ for( i in {
+ submit: 1,
+ change: 1,
+ focusin: 1
+ }) {
+ eventName = "on" + i;
+ isSupported = ( eventName in div );
+ if ( !isSupported ) {
+ div.setAttribute( eventName, "return;" );
+ isSupported = ( typeof div[ eventName ] === "function" );
+ }
+ support[ i + "Bubbles" ] = isSupported;
+ }
+ }
+
+ fragment.removeChild( div );
+
+ // Null elements to avoid leaks in IE
+ fragment = select = opt = marginDiv = div = input = null;
+
+ // Run tests that need a body at doc ready
+ jQuery(function() {
+ var container, outer, inner, table, td, offsetSupport,
+ conMarginTop, ptlm, vb, style, html,
+ body = document.getElementsByTagName("body")[0];
+
+ if ( !body ) {
+ // Return for frameset docs that don't have a body
+ return;
+ }
+
+ conMarginTop = 1;
+ ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";
+ vb = "visibility:hidden;border:0;";
+ style = "style='" + ptlm + "border:5px solid #000;padding:0;'";
+ html = "<div " + style + "><div></div></div>" +
+ "<table " + style + " cellpadding='0' cellspacing='0'>" +
+ "<tr><td></td></tr></table>";
+
+ container = document.createElement("div");
+ container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
+ body.insertBefore( container, body.firstChild );
+
+ // Construct the test element
+ div = document.createElement("div");
+ container.appendChild( div );
+
+ // Check if table cells still have offsetWidth/Height when they are set
+ // to display:none and there are still other visible table cells in a
+ // table row; if so, offsetWidth/Height are not reliable for use when
+ // determining if an element has been hidden directly using
+ // display:none (it is still safe to use offsets if a parent element is
+ // hidden; don safety goggles and see bug #4512 for more information).
+ // (only IE 8 fails this test)
+ div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
+ tds = div.getElementsByTagName( "td" );
+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+ tds[ 0 ].style.display = "";
+ tds[ 1 ].style.display = "none";
+
+ // Check if empty table cells still have offsetWidth/Height
+ // (IE <= 8 fail this test)
+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+ // Figure out if the W3C box model works as expected
+ div.innerHTML = "";
+ div.style.width = div.style.paddingLeft = "1px";
+ jQuery.boxModel = support.boxModel = div.offsetWidth === 2;
+
+ if ( typeof div.style.zoom !== "undefined" ) {
+ // Check if natively block-level elements act like inline-block
+ // elements when setting their display to 'inline' and giving
+ // them layout
+ // (IE < 8 does this)
+ div.style.display = "inline";
+ div.style.zoom = 1;
+ support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );
+
+ // Check if elements with layout shrink-wrap their children
+ // (IE 6 does this)
+ div.style.display = "";
+ div.innerHTML = "<div style='width:4px;'></div>";
+ support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
+ }
+
+ div.style.cssText = ptlm + vb;
+ div.innerHTML = html;
+
+ outer = div.firstChild;
+ inner = outer.firstChild;
+ td = outer.nextSibling.firstChild.firstChild;
+
+ offsetSupport = {
+ doesNotAddBorder: ( inner.offsetTop !== 5 ),
+ doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
+ };
+
+ inner.style.position = "fixed";
+ inner.style.top = "20px";
+
+ // safari subtracts parent border width here which is 5px
+ offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
+ inner.style.position = inner.style.top = "";
+
+ outer.style.overflow = "hidden";
+ outer.style.position = "relative";
+
+ offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
+ offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );
+
+ body.removeChild( container );
+ div = container = null;
+
+ jQuery.extend( support, offsetSupport );
+ });
+
+ return support;
+})();
+
+
+
+
+var rbrace = /^(?:\{.*\}|\[.*\])$/,
+ rmultiDash = /([A-Z])/g;
+
+jQuery.extend({
+ cache: {},
+
+ // Please use with caution
+ uuid: 0,
+
+ // Unique for each copy of jQuery on the page
+ // Non-digits removed to match rinlinejQuery
+ expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
+
+ // The following elements throw uncatchable exceptions if you
+ // attempt to add expando properties to them.
+ noData: {
+ "embed": true,
+ // Ban all objects except for Flash (which handle expandos)
+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+ "applet": true
+ },
+
+ hasData: function( elem ) {
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+ return !!elem && !isEmptyDataObject( elem );
+ },
+
+ data: function( elem, name, data, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var privateCache, thisCache, ret,
+ internalKey = jQuery.expando,
+ getByName = typeof name === "string",
+
+ // We have to handle DOM nodes and JS objects differently because IE6-7
+ // can't GC object references properly across the DOM-JS boundary
+ isNode = elem.nodeType,
+
+ // Only DOM nodes need the global jQuery cache; JS object data is
+ // attached directly to the object so GC can occur automatically
+ cache = isNode ? jQuery.cache : elem,
+
+ // Only defining an ID for JS objects if its cache already exists allows
+ // the code to shortcut on the same path as a DOM node with no cache
+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
+ isEvents = name === "events";
+
+ // Avoid doing any more work than we need to when trying to get data on an
+ // object that has no data at all
+ if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
+ return;
+ }
+
+ if ( !id ) {
+ // Only DOM nodes need a new unique ID for each element since their data
+ // ends up in the global cache
+ if ( isNode ) {
+ elem[ internalKey ] = id = ++jQuery.uuid;
+ } else {
+ id = internalKey;
+ }
+ }
+
+ if ( !cache[ id ] ) {
+ cache[ id ] = {};
+
+ // Avoids exposing jQuery metadata on plain JS objects when the object
+ // is serialized using JSON.stringify
+ if ( !isNode ) {
+ cache[ id ].toJSON = jQuery.noop;
+ }
+ }
+
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
+ // shallow copied over onto the existing cache
+ if ( typeof name === "object" || typeof name === "function" ) {
+ if ( pvt ) {
+ cache[ id ] = jQuery.extend( cache[ id ], name );
+ } else {
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+ }
+ }
+
+ privateCache = thisCache = cache[ id ];
+
+ // jQuery data() is stored in a separate object inside the object's internal data
+ // cache in order to avoid key collisions between internal data and user-defined
+ // data.
+ if ( !pvt ) {
+ if ( !thisCache.data ) {
+ thisCache.data = {};
+ }
+
+ thisCache = thisCache.data;
+ }
+
+ if ( data !== undefined ) {
+ thisCache[ jQuery.camelCase( name ) ] = data;
+ }
+
+ // Users should not attempt to inspect the internal events object using jQuery.data,
+ // it is undocumented and subject to change. But does anyone listen? No.
+ if ( isEvents && !thisCache[ name ] ) {
+ return privateCache.events;
+ }
+
+ // Check for both converted-to-camel and non-converted data property names
+ // If a data property was specified
+ if ( getByName ) {
+
+ // First Try to find as-is property data
+ ret = thisCache[ name ];
+
+ // Test for null|undefined property data
+ if ( ret == null ) {
+
+ // Try to find the camelCased property
+ ret = thisCache[ jQuery.camelCase( name ) ];
+ }
+ } else {
+ ret = thisCache;
+ }
+
+ return ret;
+ },
+
+ removeData: function( elem, name, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var thisCache, i, l,
+
+ // Reference to internal data cache key
+ internalKey = jQuery.expando,
+
+ isNode = elem.nodeType,
+
+ // See jQuery.data for more information
+ cache = isNode ? jQuery.cache : elem,
+
+ // See jQuery.data for more information
+ id = isNode ? elem[ internalKey ] : internalKey;
+
+ // If there is already no cache entry for this object, there is no
+ // purpose in continuing
+ if ( !cache[ id ] ) {
+ return;
+ }
+
+ if ( name ) {
+
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+ if ( thisCache ) {
+
+ // Support array or space separated string names for data keys
+ if ( !jQuery.isArray( name ) ) {
+
+ // try the string as a key before any manipulation
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+
+ // split the camel cased version by spaces unless a key with the spaces exists
+ name = jQuery.camelCase( name );
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+ name = name.split( " " );
+ }
+ }
+ }
+
+ for ( i = 0, l = name.length; i < l; i++ ) {
+ delete thisCache[ name[i] ];
+ }
+
+ // If there is no data left in the cache, we want to continue
+ // and let the cache object itself get destroyed
+ if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+ return;
+ }
+ }
+ }
+
+ // See jQuery.data for more information
+ if ( !pvt ) {
+ delete cache[ id ].data;
+
+ // Don't destroy the parent cache unless the internal data object
+ // had been the only thing left in it
+ if ( !isEmptyDataObject(cache[ id ]) ) {
+ return;
+ }
+ }
+
+ // Browsers that fail expando deletion also refuse to delete expandos on
+ // the window, but it will allow it on all other JS objects; other browsers
+ // don't care
+ // Ensure that `cache` is not a window object #10080
+ if ( jQuery.support.deleteExpando || !cache.setInterval ) {
+ delete cache[ id ];
+ } else {
+ cache[ id ] = null;
+ }
+
+ // We destroyed the cache and need to eliminate the expando on the node to avoid
+ // false lookups in the cache for entries that no longer exist
+ if ( isNode ) {
+ // IE does not allow us to delete expando properties from nodes,
+ // nor does it have a removeAttribute function on Document nodes;
+ // we must handle all of these cases
+ if ( jQuery.support.deleteExpando ) {
+ delete elem[ internalKey ];
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( internalKey );
+ } else {
+ elem[ internalKey ] = null;
+ }
+ }
+ },
+
+ // For internal use only.
+ _data: function( elem, name, data ) {
+ return jQuery.data( elem, name, data, true );
+ },
+
+ // A method for determining if a DOM node can handle the data expando
+ acceptData: function( elem ) {
+ if ( elem.nodeName ) {
+ var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+ if ( match ) {
+ return !(match === true || elem.getAttribute("classid") !== match);
+ }
+ }
+
+ return true;
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ var parts, attr, name,
+ data = null;
+
+ if ( typeof key === "undefined" ) {
+ if ( this.length ) {
+ data = jQuery.data( this[0] );
+
+ if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) {
+ attr = this[0].attributes;
+ for ( var i = 0, l = attr.length; i < l; i++ ) {
+ name = attr[i].name;
+
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = jQuery.camelCase( name.substring(5) );
+
+ dataAttr( this[0], name, data[ name ] );
+ }
+ }
+ jQuery._data( this[0], "parsedAttrs", true );
+ }
+ }
+
+ return data;
+
+ } else if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ parts = key.split(".");
+ parts[1] = parts[1] ? "." + parts[1] : "";
+
+ if ( value === undefined ) {
+ data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+ // Try to fetch any internally stored data first
+ if ( data === undefined && this.length ) {
+ data = jQuery.data( this[0], key );
+ data = dataAttr( this[0], key, data );
+ }
+
+ return data === undefined && parts[1] ?
+ this.data( parts[0] ) :
+ data;
+
+ } else {
+ return this.each(function() {
+ var self = jQuery( this ),
+ args = [ parts[0], value ];
+
+ self.triggerHandler( "setData" + parts[1] + "!", args );
+ jQuery.data( this, key, value );
+ self.triggerHandler( "changeData" + parts[1] + "!", args );
+ });
+ }
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+});
+
+function dataAttr( elem, key, data ) {
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ jQuery.isNumeric( data ) ? parseFloat( data ) :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ jQuery.data( elem, key, data );
+
+ } else {
+ data = undefined;
+ }
+ }
+
+ return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+ for ( var name in obj ) {
+
+ // if the public data object is empty, the private is still empty
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+ continue;
+ }
+ if ( name !== "toJSON" ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+
+
+function handleQueueMarkDefer( elem, type, src ) {
+ var deferDataKey = type + "defer",
+ queueDataKey = type + "queue",
+ markDataKey = type + "mark",
+ defer = jQuery._data( elem, deferDataKey );
+ if ( defer &&
+ ( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
+ ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
+ // Give room for hard-coded callbacks to fire first
+ // and eventually mark/queue something else on the element
+ setTimeout( function() {
+ if ( !jQuery._data( elem, queueDataKey ) &&
+ !jQuery._data( elem, markDataKey ) ) {
+ jQuery.removeData( elem, deferDataKey, true );
+ defer.fire();
+ }
+ }, 0 );
+ }
+}
+
+jQuery.extend({
+
+ _mark: function( elem, type ) {
+ if ( elem ) {
+ type = ( type || "fx" ) + "mark";
+ jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
+ }
+ },
+
+ _unmark: function( force, elem, type ) {
+ if ( force !== true ) {
+ type = elem;
+ elem = force;
+ force = false;
+ }
+ if ( elem ) {
+ type = type || "fx";
+ var key = type + "mark",
+ count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
+ if ( count ) {
+ jQuery._data( elem, key, count );
+ } else {
+ jQuery.removeData( elem, key, true );
+ handleQueueMarkDefer( elem, type, "mark" );
+ }
+ }
+ },
+
+ queue: function( elem, type, data ) {
+ var q;
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ q = jQuery._data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !q || jQuery.isArray(data) ) {
+ q = jQuery._data( elem, type, jQuery.makeArray(data) );
+ } else {
+ q.push( data );
+ }
+ }
+ return q || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ fn = queue.shift(),
+ hooks = {};
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ }
+
+ if ( fn ) {
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ jQuery._data( elem, type + ".run", hooks );
+ fn.call( elem, function() {
+ jQuery.dequeue( elem, type );
+ }, hooks );
+ }
+
+ if ( !queue.length ) {
+ jQuery.removeData( elem, type + "queue " + type + ".run", true );
+ handleQueueMarkDefer( elem, type, "queue" );
+ }
+ }
+});
+
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ }
+
+ if ( data === undefined ) {
+ return jQuery.queue( this[0], type );
+ }
+ return this.each(function() {
+ var queue = jQuery.queue( this, type, data );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+ // Based off of the plugin by Clint Helfers, with permission.
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
+ delay: function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = setTimeout( next, time );
+ hooks.stop = function() {
+ clearTimeout( timeout );
+ };
+ });
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, object ) {
+ if ( typeof type !== "string" ) {
+ object = type;
+ type = undefined;
+ }
+ type = type || "fx";
+ var defer = jQuery.Deferred(),
+ elements = this,
+ i = elements.length,
+ count = 1,
+ deferDataKey = type + "defer",
+ queueDataKey = type + "queue",
+ markDataKey = type + "mark",
+ tmp;
+ function resolve() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ }
+ while( i-- ) {
+ if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
+ ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
+ jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
+ jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
+ count++;
+ tmp.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise();
+ }
+});
+
+
+
+
+var rclass = /[\n\t\r]/g,
+ rspace = /\s+/,
+ rreturn = /\r/g,
+ rtype = /^(?:button|input)$/i,
+ rfocusable = /^(?:button|input|object|select|textarea)$/i,
+ rclickable = /^a(?:rea)?$/i,
+ rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+ getSetAttribute = jQuery.support.getSetAttribute,
+ nodeHook, boolHook, fixSpecified;
+
+jQuery.fn.extend({
+ attr: function( name, value ) {
+ return jQuery.access( this, name, value, true, jQuery.attr );
+ },
+
+ removeAttr: function( name ) {
+ return this.each(function() {
+ jQuery.removeAttr( this, name );
+ });
+ },
+
+ prop: function( name, value ) {
+ return jQuery.access( this, name, value, true, jQuery.prop );
+ },
+
+ removeProp: function( name ) {
+ name = jQuery.propFix[ name ] || name;
+ return this.each(function() {
+ // try/catch handles cases where IE balks (such as removing a property on window)
+ try {
+ this[ name ] = undefined;
+ delete this[ name ];
+ } catch( e ) {}
+ });
+ },
+
+ addClass: function( value ) {
+ var classNames, i, l, elem,
+ setClass, c, cl;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).addClass( value.call(this, j, this.className) );
+ });
+ }
+
+ if ( value && typeof value === "string" ) {
+ classNames = value.split( rspace );
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.nodeType === 1 ) {
+ if ( !elem.className && classNames.length === 1 ) {
+ elem.className = value;
+
+ } else {
+ setClass = " " + elem.className + " ";
+
+ for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+ if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
+ setClass += classNames[ c ] + " ";
+ }
+ }
+ elem.className = jQuery.trim( setClass );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classNames, i, l, elem, className, c, cl;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).removeClass( value.call(this, j, this.className) );
+ });
+ }
+
+ if ( (value && typeof value === "string") || value === undefined ) {
+ classNames = ( value || "" ).split( rspace );
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.nodeType === 1 && elem.className ) {
+ if ( value ) {
+ className = (" " + elem.className + " ").replace( rclass, " " );
+ for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+ className = className.replace(" " + classNames[ c ] + " ", " ");
+ }
+ elem.className = jQuery.trim( className );
+
+ } else {
+ elem.className = "";
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value,
+ isBool = typeof stateVal === "boolean";
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className,
+ i = 0,
+ self = jQuery( this ),
+ state = stateVal,
+ classNames = value.split( rspace );
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space seperated list
+ state = isBool ? state : !self.hasClass( className );
+ self[ state ? "addClass" : "removeClass" ]( className );
+ }
+
+ } else if ( type === "undefined" || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery._data( this, "__className__", this.className );
+ }
+
+ // toggle whole className
+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ",
+ i = 0,
+ l = this.length;
+ for ( ; i < l; i++ ) {
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ val: function( value ) {
+ var hooks, ret, isFunction,
+ elem = this[0];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
+
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+ // handle most common string cases
+ ret.replace(rreturn, "") :
+ // handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each(function( i ) {
+ var self = jQuery(this), val;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, self.val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+ } else if ( typeof val === "number" ) {
+ val += "";
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map(val, function ( value ) {
+ return value == null ? "" : value + "";
+ });
+ }
+
+ hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ valHooks: {
+ option: {
+ get: function( elem ) {
+ // attributes.value is undefined in Blackberry 4.7 but
+ // uses .value. See #6932
+ var val = elem.attributes.value;
+ return !val || val.specified ? elem.value : elem.text;
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, i, max, option,
+ index = elem.selectedIndex,
+ values = [],
+ options = elem.options,
+ one = elem.type === "select-one";
+
+ // Nothing was selected
+ if ( index < 0 ) {
+ return null;
+ }
+
+ // Loop through all the selected options
+ i = one ? index : 0;
+ max = one ? index + 1 : options.length;
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // Don't return options that are disabled or in a disabled optgroup
+ if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
+ (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
+ if ( one && !values.length && options.length ) {
+ return jQuery( options[ index ] ).val();
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var values = jQuery.makeArray( value );
+
+ jQuery(elem).find("option").each(function() {
+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+ });
+
+ if ( !values.length ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ },
+
+ attrFn: {
+ val: true,
+ css: true,
+ html: true,
+ text: true,
+ data: true,
+ width: true,
+ height: true,
+ offset: true
+ },
+
+ attr: function( elem, name, value, pass ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set attributes on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ if ( pass && name in jQuery.attrFn ) {
+ return jQuery( elem )[ name ]( value );
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === "undefined" ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ // All attributes are lowercase
+ // Grab necessary hook if one is defined
+ if ( notxml ) {
+ name = name.toLowerCase();
+ hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+ }
+
+ if ( value !== undefined ) {
+
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+ return;
+
+ } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ elem.setAttribute( name, "" + value );
+ return value;
+ }
+
+ } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+
+ ret = elem.getAttribute( name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret === null ?
+ undefined :
+ ret;
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var propName, attrNames, name, l,
+ i = 0;
+
+ if ( value && elem.nodeType === 1 ) {
+ attrNames = value.toLowerCase().split( rspace );
+ l = attrNames.length;
+
+ for ( ; i < l; i++ ) {
+ name = attrNames[ i ];
+
+ if ( name ) {
+ propName = jQuery.propFix[ name ] || name;
+
+ // See #9699 for explanation of this approach (setting first, then removal)
+ jQuery.attr( elem, name, "" );
+ elem.removeAttribute( getSetAttribute ? name : propName );
+
+ // Set corresponding property to false for boolean attributes
+ if ( rboolean.test( name ) && propName in elem ) {
+ elem[ propName ] = false;
+ }
+ }
+ }
+ }
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ // We can't allow the type property to be changed (since it causes problems in IE)
+ if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
+ jQuery.error( "type property can't be changed" );
+ } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+ // Setting the type on a radio button after the value resets the value in IE6-9
+ // Reset value to it's default in case type is set after value
+ // This is for element creation
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ },
+ // Use the value property for back compat
+ // Use the nodeHook for button elements in IE6/7 (#1954)
+ value: {
+ get: function( elem, name ) {
+ if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+ return nodeHook.get( elem, name );
+ }
+ return name in elem ?
+ elem.value :
+ null;
+ },
+ set: function( elem, value, name ) {
+ if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+ return nodeHook.set( elem, value, name );
+ }
+ // Does not return so that setAttribute is also used
+ elem.value = value;
+ }
+ }
+ },
+
+ 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( elem, name, value ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set properties on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ if ( notxml ) {
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ return ( elem[ name ] = value );
+ }
+
+ } else {
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+ return elem[ name ];
+ }
+ }
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabi...
+ var attributeNode = elem.getAttributeNode("tabindex");
+
+ return attributeNode && attributeNode.specified ?
+ parseInt( attributeNode.value, 10 ) :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ undefined;
+ }
+ }
+ }
+});
+
+// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
+jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
+
+// Hook for boolean attributes
+boolHook = {
+ get: function( elem, name ) {
+ // Align boolean attributes with corresponding properties
+ // Fall back to attribute presence where some booleans are not supported
+ var attrNode,
+ property = jQuery.prop( elem, name );
+ return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
+ name.toLowerCase() :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ var propName;
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else {
+ // value is true since we know at this point it's type boolean and not false
+ // Set boolean attributes to the same name and set the DOM property
+ propName = jQuery.propFix[ name ] || name;
+ if ( propName in elem ) {
+ // Only set the IDL specifically if it already exists on the element
+ elem[ propName ] = true;
+ }
+
+ elem.setAttribute( name, name.toLowerCase() );
+ }
+ return name;
+ }
+};
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+ fixSpecified = {
+ name: true,
+ id: true
+ };
+
+ // Use this for any attribute in IE6/7
+ // This fixes almost every IE6/7 issue
+ nodeHook = jQuery.valHooks.button = {
+ get: function( elem, name ) {
+ var ret;
+ ret = elem.getAttributeNode( name );
+ return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
+ ret.nodeValue :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ // Set the existing or create a new attribute node
+ var ret = elem.getAttributeNode( name );
+ if ( !ret ) {
+ ret = document.createAttribute( name );
+ elem.setAttributeNode( ret );
+ }
+ return ( ret.nodeValue = value + "" );
+ }
+ };
+
+ // Apply the nodeHook to tabindex
+ jQuery.attrHooks.tabindex.set = nodeHook.set;
+
+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
+ // This is for removals
+ jQuery.each([ "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ set: function( elem, value ) {
+ if ( value === "" ) {
+ elem.setAttribute( name, "auto" );
+ return value;
+ }
+ }
+ });
+ });
+
+ // Set contenteditable to false on removals(#10429)
+ // Setting to empty string throws an error as an invalid value
+ jQuery.attrHooks.contenteditable = {
+ get: nodeHook.get,
+ set: function( elem, value, name ) {
+ if ( value === "" ) {
+ value = "false";
+ }
+ nodeHook.set( elem, value, name );
+ }
+ };
+}
+
+
+// Some attributes require a special call on IE
+if ( !jQuery.support.hrefNormalized ) {
+ jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ get: function( elem ) {
+ var ret = elem.getAttribute( name, 2 );
+ return ret === null ? undefined : ret;
+ }
+ });
+ });
+}
+
+if ( !jQuery.support.style ) {
+ jQuery.attrHooks.style = {
+ get: function( elem ) {
+ // Return undefined in the case of empty string
+ // Normalize to lowercase since IE uppercases css property names
+ return elem.style.cssText.toLowerCase() || undefined;
+ },
+ set: function( elem, value ) {
+ return ( elem.style.cssText = "" + value );
+ }
+ };
+}
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !jQuery.support.optSelected ) {
+ jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ return null;
+ }
+ });
+}
+
+// IE6/7 call enctype encoding
+if ( !jQuery.support.enctype ) {
+ jQuery.propFix.enctype = "encoding";
+}
+
+// Radios and checkboxes getter/setter
+if ( !jQuery.support.checkOn ) {
+ jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ get: function( elem ) {
+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ }
+ };
+ });
+}
+jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+ }
+ }
+ });
+});
+
+
+
+
+var rformElems = /^(?:textarea|input|select)$/i,
+ rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
+ rhoverHack = /\bhover(\.\S+)?\b/,
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|contextmenu)|click/,
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+ rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
+ quickParse = function( selector ) {
+ var quick = rquickIs.exec( selector );
+ if ( quick ) {
+ // 0 1 2 3
+ // [ _, tag, id, class ]
+ quick[1] = ( quick[1] || "" ).toLowerCase();
+ quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
+ }
+ return quick;
+ },
+ quickIs = function( elem, m ) {
+ var attrs = elem.attributes || {};
+ return (
+ (!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
+ (!m[2] || (attrs.id || {}).value === m[2]) &&
+ (!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
+ );
+ },
+ hoverHack = function( events ) {
+ return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
+ };
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ add: function( elem, types, handler, data, selector ) {
+
+ var elemData, eventHandle, events,
+ t, tns, type, namespaces, handleObj,
+ handleObjIn, quick, handlers, special;
+
+ // Don't attach events to noData or text/comment nodes (allow plain objects tho)
+ if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ events = elemData.events;
+ if ( !events ) {
+ elemData.events = events = {};
+ }
+ eventHandle = elemData.handle;
+ if ( !eventHandle ) {
+ elemData.handle = eventHandle = function( e ) {
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+ eventHandle.elem = elem;
+ }
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ types = jQuery.trim( hoverHack(types) ).split( " " );
+ for ( t = 0; t < types.length; t++ ) {
+
+ tns = rtypenamespace.exec( types[t] ) || [];
+ type = tns[1];
+ namespaces = ( tns[2] || "" ).split( "." ).sort();
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend({
+ type: type,
+ origType: tns[1],
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ quick: quickParse( selector ),
+ namespace: namespaces.join(".")
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ handlers = events[ type ];
+ if ( !handlers ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener/attachEvent if the special events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ global: {},
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+
+ var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
+ t, tns, type, origType, namespaces, origCount,
+ j, events, special, handle, eventType, handleObj;
+
+ if ( !elemData || !(events = elemData.events) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
+ for ( t = 0; t < types.length; t++ ) {
+ tns = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tns[1];
+ namespaces = tns[2];
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector? special.delegateType : special.bindType ) || type;
+ eventType = events[ type ] || [];
+ origCount = eventType.length;
+ namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+
+ // Remove matching events
+ for ( j = 0; j < eventType.length; j++ ) {
+ handleObj = eventType[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+ eventType.splice( j--, 1 );
+
+ if ( handleObj.selector ) {
+ eventType.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( eventType.length === 0 && origCount !== eventType.length ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ handle = elemData.handle;
+ if ( handle ) {
+ handle.elem = null;
+ }
+
+ // removeData also checks for emptiness and clears the expando if empty
+ // so use it instead of delete
+ jQuery.removeData( elem, [ "events", "handle" ], true );
+ }
+ },
+
+ // Events that are safe to short-circuit if no handlers are attached.
+ // Native DOM events should not be added, they may have inline handlers.
+ customEvent: {
+ "getData": true,
+ "setData": true,
+ "changeData": true
+ },
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+ // Don't do events on text and comment nodes
+ if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
+ return;
+ }
+
+ // Event object or event type
+ var type = event.type || event,
+ namespaces = [],
+ cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf( "!" ) >= 0 ) {
+ // Exclusive events trigger only for the exact event (no namespaces)
+ type = type.slice(0, -1);
+ exclusive = true;
+ }
+
+ if ( type.indexOf( "." ) >= 0 ) {
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+
+ if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
+ // No jQuery handlers for this event type, and it can't have inline handlers
+ return;
+ }
+
+ // Caller can pass in an Event, Object, or just an event type string
+ event = typeof event === "object" ?
+ // jQuery.Event object
+ event[ jQuery.expando ] ? event :
+ // Object literal
+ new jQuery.Event( type, event ) :
+ // Just the event type (string)
+ new jQuery.Event( type );
+
+ event.type = type;
+ event.isTrigger = true;
+ event.exclusive = exclusive;
+ event.namespace = namespaces.join( "." );
+ event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+ ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
+
+ // Handle a global trigger
+ if ( !elem ) {
+
+ // TODO: Stop taunting the data cache; remove global events and always attach to document
+ cache = jQuery.cache;
+ for ( i in cache ) {
+ if ( cache[ i ].events && cache[ i ].events[ type ] ) {
+ jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
+ }
+ }
+ return;
+ }
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data != null ? jQuery.makeArray( data ) : [];
+ data.unshift( event );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ eventPath = [[ elem, special.bindType || type ]];
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
+ old = null;
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push([ cur, bubbleType ]);
+ old = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( old && old === elem.ownerDocument ) {
+ eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
+ }
+ }
+
+ // Fire handlers on the event path
+ for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
+
+ cur = eventPath[i][0];
+ event.type = eventPath[i][1];
+
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+ // Note that this is a bare JS function and not a jQuery handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
+ event.preventDefault();
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
+ !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ // IE<9 dies on focus/blur to hidden element (#1486)
+ if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ old = elem[ ontype ];
+
+ if ( old ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ elem[ type ]();
+ jQuery.event.triggered = undefined;
+
+ if ( old ) {
+ elem[ ontype ] = old;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event || window.event );
+
+ var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
+ delegateCount = handlers.delegateCount,
+ args = [].slice.call( arguments, 0 ),
+ run_all = !event.exclusive && !event.namespace,
+ handlerQueue = [],
+ i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[0] = event;
+ event.delegateTarget = this;
+
+ // Determine handlers that should run if there are delegated events
+ // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861)
+ if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) {
+
+ // Pregenerate a single jQuery object for reuse with .is()
+ jqcur = jQuery(this);
+ jqcur.context = this.ownerDocument || this;
+
+ for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
+ selMatch = {};
+ matches = [];
+ jqcur[0] = cur;
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+ sel = handleObj.selector;
+
+ if ( selMatch[ sel ] === undefined ) {
+ selMatch[ sel ] = (
+ handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )
+ );
+ }
+ if ( selMatch[ sel ] ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push({ elem: cur, matches: matches });
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( handlers.length > delegateCount ) {
+ handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
+ }
+
+ // Run delegates first; they may want to stop propagation beneath us
+ for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
+ matched = handlerQueue[ i ];
+ event.currentTarget = matched.elem;
+
+ for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
+ handleObj = matched.matches[ j ];
+
+ // Triggered event must either 1) be non-exclusive and have no namespace, or
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+ if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
+
+ event.data = handleObj.data;
+ event.handleObj = handleObj;
+
+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+ .apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ event.result = ret;
+ if ( ret === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ // Includes some event props shared by KeyEvent and MouseEvent
+ // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
+ 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( event, original ) {
+
+ // Add which for key events
+ if ( event.which == null ) {
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
+ }
+
+ return event;
+ }
+ },
+
+ mouseHooks: {
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+ filter: function( event, original ) {
+ var eventDoc, doc, body,
+ button = original.button,
+ fromElement = original.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && original.clientX != null ) {
+ eventDoc = event.target.ownerDocument || document;
+ doc = eventDoc.documentElement;
+ body = eventDoc.body;
+
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
+ }
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && fromElement ) {
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && button !== undefined ) {
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event;
+ }
+ },
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // Create a writable copy of the event object and normalize some properties
+ var i, prop,
+ originalEvent = event,
+ fixHook = jQuery.event.fixHooks[ event.type ] || {},
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+ event = jQuery.Event( originalEvent );
+
+ for ( i = copy.length; i; ) {
+ prop = copy[ --i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
+ if ( !event.target ) {
+ event.target = originalEvent.srcElement || document;
+ }
+
+ // Target should not be a text node (#504, Safari)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
+ if ( event.metaKey === undefined ) {
+ event.metaKey = event.ctrlKey;
+ }
+
+ return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
+ },
+
+ special: {
+ ready: {
+ // Make sure the ready event is setup
+ setup: jQuery.bindReady
+ },
+
+ load: {
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+
+ focus: {
+ delegateType: "focusin"
+ },
+ blur: {
+ delegateType: "focusout"
+ },
+
+ beforeunload: {
+ setup: function( data, namespaces, eventHandle ) {
+ // We only want to do this special case on windows
+ if ( jQuery.isWindow( this ) ) {
+ this.onbeforeunload = eventHandle;
+ }
+ },
+
+ teardown: function( namespaces, eventHandle ) {
+ if ( this.onbeforeunload === eventHandle ) {
+ this.onbeforeunload = null;
+ }
+ }
+ }
+ },
+
+ simulate: function( type, elem, event, bubble ) {
+ // Piggyback on a donor event to simulate a different one.
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
+ // simulated event prevents default then we do the same on the donor.
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ { type: type,
+ isSimulated: true,
+ originalEvent: {}
+ }
+ );
+ if ( bubble ) {
+ jQuery.event.trigger( e, null, elem );
+ } else {
+ jQuery.event.dispatch.call( elem, e );
+ }
+ if ( e.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ }
+};
+
+// Some plugins are using, but it's undocumented/deprecated and will be removed.
+// The 1.7 special event interface should provide all the hooks needed now.
+jQuery.event.handle = jQuery.event.dispatch;
+
+jQuery.removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle, false );
+ }
+ } :
+ function( elem, type, handle ) {
+ if ( elem.detachEvent ) {
+ elem.detachEvent( "on" + type, handle );
+ }
+ };
+
+jQuery.Event = function( src, props ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !(this instanceof jQuery.Event) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+function returnFalse() {
+ return false;
+}
+function returnTrue() {
+ return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-bind...
+jQuery.Event.prototype = {
+ preventDefault: function() {
+ this.isDefaultPrevented = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+
+ // if preventDefault exists run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+
+ // otherwise set the returnValue property of the original event to false (IE)
+ } else {
+ e.returnValue = false;
+ }
+ },
+ stopPropagation: function() {
+ this.isPropagationStopped = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+ // if stopPropagation exists run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+ // otherwise set the cancelBubble property of the original event to true (IE)
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ },
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj,
+ selector = handleObj.selector,
+ ret;
+
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+});
+
+// IE submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+ // Node name check avoids a VML-related crash in IE (#9807)
+ var elem = e.target,
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+ if ( form && !form._submit_attached ) {
+ jQuery.event.add( form, "submit._submit", function( event ) {
+ // If form was submitted by the user, bubble the event up the tree
+ if ( this.parentNode && !event.isTrigger ) {
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
+ }
+ });
+ form._submit_attached = true;
+ }
+ });
+ // return undefined since we don't need an event listener
+ },
+
+ teardown: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+ jQuery.event.remove( this, "._submit" );
+ }
+ };
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !jQuery.support.changeBubbles ) {
+
+ jQuery.event.special.change = {
+
+ setup: function() {
+
+ if ( rformElems.test( this.nodeName ) ) {
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
+ // after a propertychange. Eat the blur-change in special.change.handle.
+ // This still fires onchange a second time for check/radio after blur.
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ jQuery.event.add( this, "propertychange._change", function( event ) {
+ if ( event.originalEvent.propertyName === "checked" ) {
+ this._just_changed = true;
+ }
+ });
+ jQuery.event.add( this, "click._change", function( event ) {
+ if ( this._just_changed && !event.isTrigger ) {
+ this._just_changed = false;
+ jQuery.event.simulate( "change", this, event, true );
+ }
+ });
+ }
+ return false;
+ }
+ // Delegated event; lazy-add a change handler on descendant inputs
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
+ var elem = e.target;
+
+ if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
+ jQuery.event.add( elem, "change._change", function( event ) {
+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+ jQuery.event.simulate( "change", this.parentNode, event, true );
+ }
+ });
+ elem._change_attached = true;
+ }
+ });
+ },
+
+ handle: function( event ) {
+ var elem = event.target;
+
+ // Swallow native change events from checkbox/radio, we already triggered them above
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+ return event.handleObj.handler.apply( this, arguments );
+ }
+ },
+
+ teardown: function() {
+ jQuery.event.remove( this, "._change" );
+
+ return rformElems.test( this.nodeName );
+ }
+ };
+}
+
+// Create "bubbling" focus and blur events
+if ( !jQuery.support.focusinBubbles ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler while someone wants focusin/focusout
+ var attaches = 0,
+ handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ if ( attaches++ === 0 ) {
+ document.addEventListener( orig, handler, true );
+ }
+ },
+ teardown: function() {
+ if ( --attaches === 0 ) {
+ document.removeEventListener( orig, handler, true );
+ }
+ }
+ };
+ });
+}
+
+jQuery.fn.extend({
+
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+ var origFn, type;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+ // ( types-Object, data )
+ data = selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ this.on( type, selector, data, types[ type ], one );
+ }
+ return this;
+ }
+
+ if ( data == null && fn == null ) {
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return this;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return this.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ });
+ },
+ one: function( types, selector, data, fn ) {
+ return this.on.call( this, types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ if ( types && types.preventDefault && types.handleObj ) {
+ // ( event ) dispatched jQuery.Event
+ var handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+ // ( types-object [, selector] )
+ for ( var type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each(function() {
+ jQuery.event.remove( this, types, fn, selector );
+ });
+ },
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ live: function( types, data, fn ) {
+ jQuery( this.context ).on( types, this.selector, data, fn );
+ return this;
+ },
+ die: function( types, fn ) {
+ jQuery( this.context ).off( types, this.selector || "**", fn );
+ return this;
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+ triggerHandler: function( type, data ) {
+ if ( this[0] ) {
+ return jQuery.event.trigger( type, data, this[0], true );
+ }
+ },
+
+ toggle: function( fn ) {
+ // Save reference to arguments for access in closure
+ var args = arguments,
+ guid = fn.guid || jQuery.guid++,
+ i = 0,
+ toggler = function( event ) {
+ // Figure out which function to execute
+ var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+ jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+ // Make sure that clicks stop
+ event.preventDefault();
+
+ // and execute the function
+ return args[ lastToggle ].apply( this, arguments ) || false;
+ };
+
+ // link all the functions, so any of them can unbind this click handler
+ toggler.guid = guid;
+ while ( i < args.length ) {
+ args[ i++ ].guid = guid;
+ }
+
+ return this.click( toggler );
+ },
+
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ }
+});
+
+jQuery.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( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ if ( fn == null ) {
+ fn = data;
+ data = null;
+ }
+
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+
+ if ( jQuery.attrFn ) {
+ jQuery.attrFn[ name ] = true;
+ }
+
+ if ( rkeyEvent.test( name ) ) {
+ jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
+ }
+
+ if ( rmouseEvent.test( name ) ) {
+ jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
+ }
+});
+
+
+
+/*!
+ * Sizzle CSS Selector Engine
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ * More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+ expando = "sizcache" + (Math.random() + '').replace('.', ''),
+ done = 0,
+ toString = Object.prototype.toString,
+ hasDuplicate = false,
+ baseHasDuplicate = true,
+ rBackslash = /\\/g,
+ rReturn = /\r\n/g,
+ rNonWord = /\W/;
+
+// Here we check if the JavaScript engine is using some sort of
+// optimization where it does not always call our comparision
+// function. If that is the case, discard the hasDuplicate value.
+// Thus far that includes Google Chrome.
+[0, 0].sort(function() {
+ baseHasDuplicate = false;
+ return 0;
+});
+
+var Sizzle = function( selector, context, results, seed ) {
+ results = results || [];
+ context = context || document;
+
+ var origContext = context;
+
+ if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
+ return [];
+ }
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ var m, set, checkSet, extra, ret, cur, pop, i,
+ prune = true,
+ contextXML = Sizzle.isXML( context ),
+ parts = [],
+ soFar = selector;
+
+ // Reset the position of the chunker regexp (start from head)
+ do {
+ chunker.exec( "" );
+ m = chunker.exec( soFar );
+
+ if ( m ) {
+ soFar = m[3];
+
+ parts.push( m[1] );
+
+ if ( m[2] ) {
+ extra = m[3];
+ break;
+ }
+ }
+ } while ( m );
+
+ if ( parts.length > 1 && origPOS.exec( selector ) ) {
+
+ if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+ set = posProcess( parts[0] + parts[1], context, seed );
+
+ } else {
+ set = Expr.relative[ parts[0] ] ?
+ [ context ] :
+ Sizzle( parts.shift(), context );
+
+ while ( parts.length ) {
+ selector = parts.shift();
+
+ if ( Expr.relative[ selector ] ) {
+ selector += parts.shift();
+ }
+
+ set = posProcess( selector, set, seed );
+ }
+ }
+
+ } else {
+ // Take a shortcut and set the context if the root selector is an ID
+ // (but not if it'll be faster if the inner selector is an ID)
+ if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
+ Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
+
+ ret = Sizzle.find( parts.shift(), context, contextXML );
+ context = ret.expr ?
+ Sizzle.filter( ret.expr, ret.set )[0] :
+ ret.set[0];
+ }
+
+ if ( context ) {
+ ret = seed ?
+ { expr: parts.pop(), set: makeArray(seed) } :
+ Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
+
+ set = ret.expr ?
+ Sizzle.filter( ret.expr, ret.set ) :
+ ret.set;
+
+ if ( parts.length > 0 ) {
+ checkSet = makeArray( set );
+
+ } else {
+ prune = false;
+ }
+
+ while ( parts.length ) {
+ cur = parts.pop();
+ pop = cur;
+
+ if ( !Expr.relative[ cur ] ) {
+ cur = "";
+ } else {
+ pop = parts.pop();
+ }
+
+ if ( pop == null ) {
+ pop = context;
+ }
+
+ Expr.relative[ cur ]( checkSet, pop, contextXML );
+ }
+
+ } else {
+ checkSet = parts = [];
+ }
+ }
+
+ if ( !checkSet ) {
+ checkSet = set;
+ }
+
+ if ( !checkSet ) {
+ Sizzle.error( cur || selector );
+ }
+
+ if ( toString.call(checkSet) === "[object Array]" ) {
+ if ( !prune ) {
+ results.push.apply( results, checkSet );
+
+ } else if ( context && context.nodeType === 1 ) {
+ for ( i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
+ results.push( set[i] );
+ }
+ }
+
+ } else {
+ for ( i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+ results.push( set[i] );
+ }
+ }
+ }
+
+ } else {
+ makeArray( checkSet, results );
+ }
+
+ if ( extra ) {
+ Sizzle( extra, origContext, results, seed );
+ Sizzle.uniqueSort( results );
+ }
+
+ return results;
+};
+
+Sizzle.uniqueSort = function( results ) {
+ if ( sortOrder ) {
+ hasDuplicate = baseHasDuplicate;
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ for ( var i = 1; i < results.length; i++ ) {
+ if ( results[i] === results[ i - 1 ] ) {
+ results.splice( i--, 1 );
+ }
+ }
+ }
+ }
+
+ return results;
+};
+
+Sizzle.matches = function( expr, set ) {
+ return Sizzle( expr, null, null, set );
+};
+
+Sizzle.matchesSelector = function( node, expr ) {
+ return Sizzle( expr, null, null, [node] ).length > 0;
+};
+
+Sizzle.find = function( expr, context, isXML ) {
+ var set, i, len, match, type, left;
+
+ if ( !expr ) {
+ return [];
+ }
+
+ for ( i = 0, len = Expr.order.length; i < len; i++ ) {
+ type = Expr.order[i];
+
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
+ left = match[1];
+ match.splice( 1, 1 );
+
+ if ( left.substr( left.length - 1 ) !== "\\" ) {
+ match[1] = (match[1] || "").replace( rBackslash, "" );
+ set = Expr.find[ type ]( match, context, isXML );
+
+ if ( set != null ) {
+ expr = expr.replace( Expr.match[ type ], "" );
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !set ) {
+ set = typeof context.getElementsByTagName !== "undefined" ?
+ context.getElementsByTagName( "*" ) :
+ [];
+ }
+
+ return { set: set, expr: expr };
+};
+
+Sizzle.filter = function( expr, set, inplace, not ) {
+ var match, anyFound,
+ type, found, item, filter, left,
+ i, pass,
+ old = expr,
+ result = [],
+ curLoop = set,
+ isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
+
+ while ( expr && set.length ) {
+ for ( type in Expr.filter ) {
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
+ filter = Expr.filter[ type ];
+ left = match[1];
+
+ anyFound = false;
+
+ match.splice(1,1);
+
+ if ( left.substr( left.length - 1 ) === "\\" ) {
+ continue;
+ }
+
+ if ( curLoop === result ) {
+ result = [];
+ }
+
+ if ( Expr.preFilter[ type ] ) {
+ match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+
+ if ( !match ) {
+ anyFound = found = true;
+
+ } else if ( match === true ) {
+ continue;
+ }
+ }
+
+ if ( match ) {
+ for ( i = 0; (item = curLoop[i]) != null; i++ ) {
+ if ( item ) {
+ found = filter( item, match, i, curLoop );
+ pass = not ^ found;
+
+ if ( inplace && found != null ) {
+ if ( pass ) {
+ anyFound = true;
+
+ } else {
+ curLoop[i] = false;
+ }
+
+ } else if ( pass ) {
+ result.push( item );
+ anyFound = true;
+ }
+ }
+ }
+ }
+
+ if ( found !== undefined ) {
+ if ( !inplace ) {
+ curLoop = result;
+ }
+
+ expr = expr.replace( Expr.match[ type ], "" );
+
+ if ( !anyFound ) {
+ return [];
+ }
+
+ break;
+ }
+ }
+ }
+
+ // Improper expression
+ if ( expr === old ) {
+ if ( anyFound == null ) {
+ Sizzle.error( expr );
+
+ } else {
+ break;
+ }
+ }
+
+ old = expr;
+ }
+
+ return curLoop;
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Utility function for retreiving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+var getText = Sizzle.getText = function( elem ) {
+ var i, node,
+ nodeType = elem.nodeType,
+ ret = "";
+
+ if ( nodeType ) {
+ if ( nodeType === 1 || nodeType === 9 ) {
+ // Use textContent || innerText for elements
+ if ( typeof elem.textContent === 'string' ) {
+ return elem.textContent;
+ } else if ( typeof elem.innerText === 'string' ) {
+ // Replace IE's carriage returns
+ return elem.innerText.replace( rReturn, '' );
+ } else {
+ // Traverse it's children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ } else {
+
+ // If no nodeType, this is expected to be an array
+ for ( i = 0; (node = elem[i]); i++ ) {
+ // Do not traverse comment nodes
+ if ( node.nodeType !== 8 ) {
+ ret += getText( node );
+ }
+ }
+ }
+ return ret;
+};
+
+var Expr = Sizzle.selectors = {
+ order: [ "ID", "NAME", "TAG" ],
+
+ match: {
+ ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+ CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+ NAME: /\[name=['"]*((?:[\w\u00c0-\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( elem ) {
+ return elem.getAttribute( "href" );
+ },
+ type: function( elem ) {
+ return elem.getAttribute( "type" );
+ }
+ },
+
+ relative: {
+ "+": function(checkSet, part){
+ var isPartStr = typeof part === "string",
+ isTag = isPartStr && !rNonWord.test( part ),
+ isPartStrNotTag = isPartStr && !isTag;
+
+ if ( isTag ) {
+ part = part.toLowerCase();
+ }
+
+ for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+ if ( (elem = checkSet[i]) ) {
+ while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+ checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
+ elem || false :
+ elem === part;
+ }
+ }
+
+ if ( isPartStrNotTag ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ },
+
+ ">": function( checkSet, part ) {
+ var elem,
+ isPartStr = typeof part === "string",
+ i = 0,
+ l = checkSet.length;
+
+ if ( isPartStr && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
+
+ for ( ; i < l; i++ ) {
+ elem = checkSet[i];
+
+ if ( elem ) {
+ var parent = elem.parentNode;
+ checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
+ }
+ }
+
+ } else {
+ for ( ; i < l; i++ ) {
+ elem = checkSet[i];
+
+ if ( elem ) {
+ checkSet[i] = isPartStr ?
+ elem.parentNode :
+ elem.parentNode === part;
+ }
+ }
+
+ if ( isPartStr ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ }
+ },
+
+ "": function(checkSet, part, isXML){
+ var nodeCheck,
+ doneName = done++,
+ checkFn = dirCheck;
+
+ if ( typeof part === "string" && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
+ nodeCheck = part;
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
+ },
+
+ "~": function( checkSet, part, isXML ) {
+ var nodeCheck,
+ doneName = done++,
+ checkFn = dirCheck;
+
+ if ( typeof part === "string" && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
+ nodeCheck = part;
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
+ }
+ },
+
+ find: {
+ ID: function( match, context, isXML ) {
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [m] : [];
+ }
+ },
+
+ NAME: function( match, context ) {
+ if ( typeof context.getElementsByName !== "undefined" ) {
+ var ret = [],
+ results = context.getElementsByName( match[1] );
+
+ for ( var i = 0, l = results.length; i < l; i++ ) {
+ if ( results[i].getAttribute("name") === match[1] ) {
+ ret.push( results[i] );
+ }
+ }
+
+ return ret.length === 0 ? null : ret;
+ }
+ },
+
+ TAG: function( match, context ) {
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ return context.getElementsByTagName( match[1] );
+ }
+ }
+ },
+ preFilter: {
+ CLASS: function( match, curLoop, inplace, result, not, isXML ) {
+ match = " " + match[1].replace( rBackslash, "" ) + " ";
+
+ if ( isXML ) {
+ return match;
+ }
+
+ for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+ if ( elem ) {
+ if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
+ if ( !inplace ) {
+ result.push( elem );
+ }
+
+ } else if ( inplace ) {
+ curLoop[i] = false;
+ }
+ }
+ }
+
+ return false;
+ },
+
+ ID: function( match ) {
+ return match[1].replace( rBackslash, "" );
+ },
+
+ TAG: function( match, curLoop ) {
+ return match[1].replace( rBackslash, "" ).toLowerCase();
+ },
+
+ CHILD: function( match ) {
+ if ( match[1] === "nth" ) {
+ if ( !match[2] ) {
+ Sizzle.error( match[0] );
+ }
+
+ match[2] = match[2].replace(/^\+|\s*/g, '');
+
+ // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+ var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
+ match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
+ !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+ // calculate the numbers (first)n+(last) including if they are negative
+ match[2] = (test[1] + (test[2] || 1)) - 0;
+ match[3] = test[3] - 0;
+ }
+ else if ( match[2] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // TODO: Move to normal caching system
+ match[0] = done++;
+
+ return match;
+ },
+
+ ATTR: function( match, curLoop, inplace, result, not, isXML ) {
+ var name = match[1] = match[1].replace( rBackslash, "" );
+
+ if ( !isXML && Expr.attrMap[name] ) {
+ match[1] = Expr.attrMap[name];
+ }
+
+ // Handle if an un-quoted value was used
+ match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
+
+ if ( match[2] === "~=" ) {
+ match[4] = " " + match[4] + " ";
+ }
+
+ return match;
+ },
+
+ PSEUDO: function( match, curLoop, inplace, result, not ) {
+ if ( match[1] === "not" ) {
+ // If we're dealing with a complex expression, or a simple one
+ if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
+ match[3] = Sizzle(match[3], null, null, curLoop);
+
+ } else {
+ var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+
+ if ( !inplace ) {
+ result.push.apply( result, ret );
+ }
+
+ return false;
+ }
+
+ } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+ return true;
+ }
+
+ return match;
+ },
+
+ POS: function( match ) {
+ match.unshift( true );
+
+ return match;
+ }
+ },
+
+ filters: {
+ enabled: function( elem ) {
+ return elem.disabled === false && elem.type !== "hidden";
+ },
+
+ disabled: function( elem ) {
+ return elem.disabled === true;
+ },
+
+ checked: function( elem ) {
+ return elem.checked === true;
+ },
+
+ selected: function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ parent: function( elem ) {
+ return !!elem.firstChild;
+ },
+
+ empty: function( elem ) {
+ return !elem.firstChild;
+ },
+
+ has: function( elem, i, match ) {
+ return !!Sizzle( match[3], elem ).length;
+ },
+
+ header: function( elem ) {
+ return (/h\d/i).test( elem.nodeName );
+ },
+
+ text: function( elem ) {
+ var attr = elem.getAttribute( "type" ), type = elem.type;
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
+ // use getAttribute instead to test this case
+ return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
+ },
+
+ radio: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
+ },
+
+ checkbox: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
+ },
+
+ file: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
+ },
+
+ password: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
+ },
+
+ submit: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && "submit" === elem.type;
+ },
+
+ image: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
+ },
+
+ reset: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && "reset" === elem.type;
+ },
+
+ button: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && "button" === elem.type || name === "button";
+ },
+
+ input: function( elem ) {
+ return (/input|select|textarea|button/i).test( elem.nodeName );
+ },
+
+ focus: function( elem ) {
+ return elem === elem.ownerDocument.activeElement;
+ }
+ },
+ setFilters: {
+ first: function( elem, i ) {
+ return i === 0;
+ },
+
+ last: function( elem, i, match, array ) {
+ return i === array.length - 1;
+ },
+
+ even: function( elem, i ) {
+ return i % 2 === 0;
+ },
+
+ odd: function( elem, i ) {
+ return i % 2 === 1;
+ },
+
+ lt: function( elem, i, match ) {
+ return i < match[3] - 0;
+ },
+
+ gt: function( elem, i, match ) {
+ return i > match[3] - 0;
+ },
+
+ nth: function( elem, i, match ) {
+ return match[3] - 0 === i;
+ },
+
+ eq: function( elem, i, match ) {
+ return match[3] - 0 === i;
+ }
+ },
+ filter: {
+ PSEUDO: function( elem, match, i, array ) {
+ var name = match[1],
+ filter = Expr.filters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+
+ } else if ( name === "contains" ) {
+ return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
+
+ } else if ( name === "not" ) {
+ var not = match[3];
+
+ for ( var j = 0, l = not.length; j < l; j++ ) {
+ if ( not[j] === elem ) {
+ return false;
+ }
+ }
+
+ return true;
+
+ } else {
+ Sizzle.error( name );
+ }
+ },
+
+ CHILD: function( elem, match ) {
+ var first, last,
+ doneName, parent, cache,
+ count, diff,
+ type = match[1],
+ node = elem;
+
+ switch ( type ) {
+ case "only":
+ case "first":
+ while ( (node = node.previousSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+
+ if ( type === "first" ) {
+ return true;
+ }
+
+ node = elem;
+
+ case "last":
+ while ( (node = node.nextSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+
+ return true;
+
+ case "nth":
+ first = match[2];
+ last = match[3];
+
+ if ( first === 1 && last === 0 ) {
+ return true;
+ }
+
+ doneName = match[0];
+ parent = elem.parentNode;
+
+ if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
+ count = 0;
+
+ for ( node = parent.firstChild; node; node = node.nextSibling ) {
+ if ( node.nodeType === 1 ) {
+ node.nodeIndex = ++count;
+ }
+ }
+
+ parent[ expando ] = doneName;
+ }
+
+ diff = elem.nodeIndex - last;
+
+ if ( first === 0 ) {
+ return diff === 0;
+
+ } else {
+ return ( diff % first === 0 && diff / first >= 0 );
+ }
+ }
+ },
+
+ ID: function( elem, match ) {
+ return elem.nodeType === 1 && elem.getAttribute("id") === match;
+ },
+
+ TAG: function( elem, match ) {
+ return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
+ },
+
+ CLASS: function( elem, match ) {
+ return (" " + (elem.className || elem.getAttribute("class")) + " ")
+ .indexOf( match ) > -1;
+ },
+
+ ATTR: function( elem, match ) {
+ var name = match[1],
+ result = Sizzle.attr ?
+ Sizzle.attr( elem, name ) :
+ Expr.attrHandle[ name ] ?
+ Expr.attrHandle[ name ]( elem ) :
+ elem[ name ] != null ?
+ elem[ name ] :
+ elem.getAttribute( name ),
+ value = result + "",
+ type = match[2],
+ check = match[4];
+
+ return result == null ?
+ type === "!=" :
+ !type && Sizzle.attr ?
+ result != null :
+ type === "=" ?
+ value === check :
+ type === "*=" ?
+ value.indexOf(check) >= 0 :
+ type === "~=" ?
+ (" " + value + " ").indexOf(check) >= 0 :
+ !check ?
+ value && result !== false :
+ type === "!=" ?
+ value !== check :
+ type === "^=" ?
+ value.indexOf(check) === 0 :
+ type === "$=" ?
+ value.substr(value.length - check.length) === check :
+ type === "|=" ?
+ value === check || value.substr(0, check.length + 1) === check + "-" :
+ false;
+ },
+
+ POS: function( elem, match, i, array ) {
+ var name = match[2],
+ filter = Expr.setFilters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+ }
+ }
+ }
+};
+
+var origPOS = Expr.match.POS,
+ fescape = function(all, num){
+ return "\\" + (num - 0 + 1);
+ };
+
+for ( var type in Expr.match ) {
+ Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
+ Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
+}
+
+var makeArray = function( array, results ) {
+ array = Array.prototype.slice.call( array, 0 );
+
+ if ( results ) {
+ results.push.apply( results, array );
+ return results;
+ }
+
+ return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+// Also verifies that the returned array holds DOM nodes
+// (which is not the case in the Blackberry browser)
+try {
+ Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
+
+// Provide a fallback method if it does not work
+} catch( e ) {
+ makeArray = function( array, results ) {
+ var i = 0,
+ ret = results || [];
+
+ if ( toString.call(array) === "[object Array]" ) {
+ Array.prototype.push.apply( ret, array );
+
+ } else {
+ if ( typeof array.length === "number" ) {
+ for ( var l = array.length; i < l; i++ ) {
+ ret.push( array[i] );
+ }
+
+ } else {
+ for ( ; array[i]; i++ ) {
+ ret.push( array[i] );
+ }
+ }
+ }
+
+ return ret;
+ };
+}
+
+var sortOrder, siblingCheck;
+
+if ( document.documentElement.compareDocumentPosition ) {
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
+ return a.compareDocumentPosition ? -1 : 1;
+ }
+
+ return a.compareDocumentPosition(b) & 4 ? -1 : 1;
+ };
+
+} else {
+ sortOrder = function( a, b ) {
+ // The nodes are identical, we can exit early
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+
+ // Fallback to using sourceIndex (in IE) if it's available on both nodes
+ } else if ( a.sourceIndex && b.sourceIndex ) {
+ return a.sourceIndex - b.sourceIndex;
+ }
+
+ var al, bl,
+ ap = [],
+ bp = [],
+ aup = a.parentNode,
+ bup = b.parentNode,
+ cur = aup;
+
+ // If the nodes are siblings (or identical) we can do a quick check
+ if ( aup === bup ) {
+ return siblingCheck( a, b );
+
+ // If no parents were found then the nodes are disconnected
+ } else if ( !aup ) {
+ return -1;
+
+ } else if ( !bup ) {
+ return 1;
+ }
+
+ // Otherwise they're somewhere else in the tree so we need
+ // to build up a full list of the parentNodes for comparison
+ while ( cur ) {
+ ap.unshift( cur );
+ cur = cur.parentNode;
+ }
+
+ cur = bup;
+
+ while ( cur ) {
+ bp.unshift( cur );
+ cur = cur.parentNode;
+ }
+
+ al = ap.length;
+ bl = bp.length;
+
+ // Start walking down the tree looking for a discrepancy
+ for ( var i = 0; i < al && i < bl; i++ ) {
+ if ( ap[i] !== bp[i] ) {
+ return siblingCheck( ap[i], bp[i] );
+ }
+ }
+
+ // We ended someplace up the tree so do a sibling check
+ return i === al ?
+ siblingCheck( a, bp[i], -1 ) :
+ siblingCheck( ap[i], b, 1 );
+ };
+
+ siblingCheck = function( a, b, ret ) {
+ if ( a === b ) {
+ return ret;
+ }
+
+ var cur = a.nextSibling;
+
+ while ( cur ) {
+ if ( cur === b ) {
+ return -1;
+ }
+
+ cur = cur.nextSibling;
+ }
+
+ return 1;
+ };
+}
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+ // We're going to inject a fake input element with a specified name
+ var form = document.createElement("div"),
+ id = "script" + (new Date()).getTime(),
+ root = document.documentElement;
+
+ form.innerHTML = "<a name='" + id + "'/>";
+
+ // Inject it into the root element, check its status, and remove it quickly
+ root.insertBefore( form, root.firstChild );
+
+ // The workaround has to do additional checks after a getElementById
+ // Which slows things down for other browsers (hence the branching)
+ if ( document.getElementById( id ) ) {
+ Expr.find.ID = function( match, context, isXML ) {
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+
+ return m ?
+ m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
+ [m] :
+ undefined :
+ [];
+ }
+ };
+
+ Expr.filter.ID = function( elem, match ) {
+ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+
+ return elem.nodeType === 1 && node && node.nodeValue === match;
+ };
+ }
+
+ root.removeChild( form );
+
+ // release memory in IE
+ root = form = null;
+})();
+
+(function(){
+ // Check to see if the browser returns only elements
+ // when doing getElementsByTagName("*")
+
+ // Create a fake element
+ var div = document.createElement("div");
+ div.appendChild( document.createComment("") );
+
+ // Make sure no comments are found
+ if ( div.getElementsByTagName("*").length > 0 ) {
+ Expr.find.TAG = function( match, context ) {
+ var results = context.getElementsByTagName( match[1] );
+
+ // Filter out possible comments
+ if ( match[1] === "*" ) {
+ var tmp = [];
+
+ for ( var i = 0; results[i]; i++ ) {
+ if ( results[i].nodeType === 1 ) {
+ tmp.push( results[i] );
+ }
+ }
+
+ results = tmp;
+ }
+
+ return results;
+ };
+ }
+
+ // Check to see if an attribute returns normalized href attributes
+ div.innerHTML = "<a href='#'></a>";
+
+ if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+ div.firstChild.getAttribute("href") !== "#" ) {
+
+ Expr.attrHandle.href = function( elem ) {
+ return elem.getAttribute( "href", 2 );
+ };
+ }
+
+ // release memory in IE
+ div = null;
+})();
+
+if ( document.querySelectorAll ) {
+ (function(){
+ var oldSizzle = Sizzle,
+ div = document.createElement("div"),
+ id = "__sizzle__";
+
+ div.innerHTML = "<p class='TEST'></p>";
+
+ // Safari can't handle uppercase or unicode characters when
+ // in quirks mode.
+ if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+ return;
+ }
+
+ Sizzle = function( query, context, extra, seed ) {
+ context = context || document;
+
+ // Only use querySelectorAll on non-XML documents
+ // (ID selectors don't work in non-HTML documents)
+ if ( !seed && !Sizzle.isXML(context) ) {
+ // See if we find a selector to speed up
+ var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
+
+ if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
+ // Speed-up: Sizzle("TAG")
+ if ( match[1] ) {
+ return makeArray( context.getElementsByTagName( query ), extra );
+
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
+ return makeArray( context.getElementsByClassName( match[2] ), extra );
+ }
+ }
+
+ if ( context.nodeType === 9 ) {
+ // Speed-up: Sizzle("body")
+ // The body element only exists once, optimize finding it
+ if ( query === "body" && context.body ) {
+ return makeArray( [ context.body ], extra );
+
+ // Speed-up: Sizzle("#ID")
+ } else if ( match && match[3] ) {
+ var elem = context.getElementById( match[3] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id === match[3] ) {
+ return makeArray( [ elem ], extra );
+ }
+
+ } else {
+ return makeArray( [], extra );
+ }
+ }
+
+ try {
+ return makeArray( context.querySelectorAll(query), extra );
+ } catch(qsaError) {}
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ var oldContext = context,
+ old = context.getAttribute( "id" ),
+ nid = old || id,
+ hasParent = context.parentNode,
+ relativeHierarchySelector = /^\s*[+~]/.test( query );
+
+ if ( !old ) {
+ context.setAttribute( "id", nid );
+ } else {
+ nid = nid.replace( /'/g, "\\$&" );
+ }
+ if ( relativeHierarchySelector && hasParent ) {
+ context = context.parentNode;
+ }
+
+ try {
+ if ( !relativeHierarchySelector || hasParent ) {
+ return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
+ }
+
+ } catch(pseudoError) {
+ } finally {
+ if ( !old ) {
+ oldContext.removeAttribute( "id" );
+ }
+ }
+ }
+ }
+
+ return oldSizzle(query, context, extra, seed);
+ };
+
+ for ( var prop in oldSizzle ) {
+ Sizzle[ prop ] = oldSizzle[ prop ];
+ }
+
+ // release memory in IE
+ div = null;
+ })();
+}
+
+(function(){
+ var html = document.documentElement,
+ matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
+
+ if ( matches ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9 fails this)
+ var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
+ pseudoWorks = false;
+
+ try {
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( document.documentElement, "[test!='']:sizzle" );
+
+ } catch( pseudoError ) {
+ pseudoWorks = true;
+ }
+
+ Sizzle.matchesSelector = function( node, expr ) {
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
+
+ if ( !Sizzle.isXML( node ) ) {
+ try {
+ if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
+ var ret = matches.call( node, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || !disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9, so check for that
+ node.document && node.document.nodeType !== 11 ) {
+ return ret;
+ }
+ }
+ } catch(e) {}
+ }
+
+ return Sizzle(expr, null, null, [node]).length > 0;
+ };
+ }
+})();
+
+(function(){
+ var div = document.createElement("div");
+
+ div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+
+ // Opera can't find a second classname (in 9.6)
+ // Also, make sure that getElementsByClassName actually exists
+ if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
+ return;
+ }
+
+ // Safari caches class attributes, doesn't catch changes (in 3.2)
+ div.lastChild.className = "e";
+
+ if ( div.getElementsByClassName("e").length === 1 ) {
+ return;
+ }
+
+ Expr.order.splice(1, 0, "CLASS");
+ Expr.find.CLASS = function( match, context, isXML ) {
+ if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+ return context.getElementsByClassName(match[1]);
+ }
+ };
+
+ // release memory in IE
+ div = null;
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+
+ if ( elem ) {
+ var match = false;
+
+ elem = elem[dir];
+
+ while ( elem ) {
+ if ( elem[ expando ] === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 && !isXML ){
+ elem[ expando ] = doneName;
+ elem.sizset = i;
+ }
+
+ if ( elem.nodeName.toLowerCase() === cur ) {
+ match = elem;
+ break;
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+
+ if ( elem ) {
+ var match = false;
+
+ elem = elem[dir];
+
+ while ( elem ) {
+ if ( elem[ expando ] === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 ) {
+ if ( !isXML ) {
+ elem[ expando ] = doneName;
+ elem.sizset = i;
+ }
+
+ if ( typeof cur !== "string" ) {
+ if ( elem === cur ) {
+ match = true;
+ break;
+ }
+
+ } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+ match = elem;
+ break;
+ }
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+if ( document.documentElement.contains ) {
+ Sizzle.contains = function( a, b ) {
+ return a !== b && (a.contains ? a.contains(b) : true);
+ };
+
+} else if ( document.documentElement.compareDocumentPosition ) {
+ Sizzle.contains = function( a, b ) {
+ return !!(a.compareDocumentPosition(b) & 16);
+ };
+
+} else {
+ Sizzle.contains = function() {
+ return false;
+ };
+}
+
+Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
+
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+var posProcess = function( selector, context, seed ) {
+ var match,
+ tmpSet = [],
+ later = "",
+ root = context.nodeType ? [context] : context;
+
+ // Position selectors must be done after the filter
+ // And so must :not(positional) so we move all PSEUDOs to the end
+ while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+ later += match[0];
+ selector = selector.replace( Expr.match.PSEUDO, "" );
+ }
+
+ selector = Expr.relative[selector] ? selector + "*" : selector;
+
+ for ( var i = 0, l = root.length; i < l; i++ ) {
+ Sizzle( selector, root[i], tmpSet, seed );
+ }
+
+ return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+// Override sizzle attribute retrieval
+Sizzle.attr = jQuery.attr;
+Sizzle.selectors.attrMap = {};
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})();
+
+
+var runtil = /Until$/,
+ rparentsprev = /^(?:parents|prevUntil|prevAll)/,
+ // Note: This RegExp should be improved, or likely pulled from Sizzle
+ rmultiselector = /,/,
+ isSimple = /^.[^:#\[\.,]*$/,
+ slice = Array.prototype.slice,
+ POS = jQuery.expr.match.POS,
+ // methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var self = this,
+ i, l;
+
+ if ( typeof selector !== "string" ) {
+ return jQuery( selector ).filter(function() {
+ for ( i = 0, l = self.length; i < l; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ });
+ }
+
+ var ret = this.pushStack( "", "find", selector ),
+ length, n, r;
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ length = ret.length;
+ jQuery.find( selector, this[i], ret );
+
+ if ( i > 0 ) {
+ // Make sure that the results are unique
+ for ( n = length; n < ret.length; n++ ) {
+ for ( r = 0; r < length; r++ ) {
+ if ( ret[r] === ret[n] ) {
+ ret.splice(n--, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+ },
+
+ has: function( target ) {
+ var targets = jQuery( target );
+ return this.filter(function() {
+ for ( var i = 0, l = targets.length; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector, false), "not", selector);
+ },
+
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector, true), "filter", selector );
+ },
+
+ is: function( selector ) {
+ return !!selector && (
+ typeof selector === "string" ?
+ // If this is a positional selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ POS.test( selector ) ?
+ jQuery( selector, this.context ).index( this[0] ) >= 0 :
+ jQuery.filter( selector, this ).length > 0 :
+ this.filter( selector ).length > 0 );
+ },
+
+ closest: function( selectors, context ) {
+ var ret = [], i, l, cur = this[0];
+
+ // Array (deprecated as of jQuery 1.7)
+ if ( jQuery.isArray( selectors ) ) {
+ var level = 1;
+
+ while ( cur && cur.ownerDocument && cur !== context ) {
+ for ( i = 0; i < selectors.length; i++ ) {
+
+ if ( jQuery( cur ).is( selectors[ i ] ) ) {
+ ret.push({ selector: selectors[ i ], elem: cur, level: level });
+ }
+ }
+
+ cur = cur.parentNode;
+ level++;
+ }
+
+ return ret;
+ }
+
+ // String
+ var pos = POS.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ cur = this[i];
+
+ while ( cur ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+ ret.push( cur );
+ break;
+
+ } else {
+ cur = cur.parentNode;
+ if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
+ break;
+ }
+ }
+ }
+ }
+
+ ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
+
+ return this.pushStack( ret, "closest", selectors );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
+ }
+
+ // index in selector
+ if ( typeof elem === "string" ) {
+ return jQuery.inArray( this[0], jQuery( elem ) );
+ }
+
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ var set = typeof selector === "string" ?
+ jQuery( selector, context ) :
+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+ all = jQuery.merge( this.get(), set );
+
+ return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+ all :
+ jQuery.unique( all ) );
+ },
+
+ andSelf: function() {
+ return this.add( this.prevObject );
+ }
+});
+
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+ return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return jQuery.nth( elem, 2, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return jQuery.nth( elem, 2, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( elem.parentNode.firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.makeArray( elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
+
+ if ( !runtil.test( name ) ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
+
+ ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
+
+ if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
+
+ return this.pushStack( ret, name, slice.call( arguments ).join(",") );
+ };
+});
+
+jQuery.extend({
+ filter: function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 ?
+ jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+ jQuery.find.matches(expr, elems);
+ },
+
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ cur = elem[ dir ];
+
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
+ }
+ cur = cur[dir];
+ }
+ return matched;
+ },
+
+ nth: function( cur, result, dir, elem ) {
+ result = result || 1;
+ var num = 0;
+
+ for ( ; cur; cur = cur[dir] ) {
+ if ( cur.nodeType === 1 && ++num === result ) {
+ break;
+ }
+ }
+
+ return cur;
+ },
+
+ sibling: function( n, elem ) {
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
+
+ return r;
+ }
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+
+ // Can't pass null or undefined to indexOf in Firefox 4
+ // Set to 0 to skip string check
+ qualifier = qualifier || 0;
+
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ var retVal = !!qualifier.call( elem, i, elem );
+ return retVal === keep;
+ });
+
+ } else if ( qualifier.nodeType ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ return ( elem === qualifier ) === keep;
+ });
+
+ } else if ( typeof qualifier === "string" ) {
+ var filtered = jQuery.grep(elements, function( elem ) {
+ return elem.nodeType === 1;
+ });
+
+ if ( isSimple.test( qualifier ) ) {
+ return jQuery.filter(qualifier, filtered, !keep);
+ } else {
+ qualifier = jQuery.filter( qualifier, filtered );
+ }
+ }
+
+ return jQuery.grep(elements, function( elem, i ) {
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
+ });
+}
+
+
+
+
+function createSafeFragment( document ) {
+ var list = nodeNames.split( "|" ),
+ safeFrag = document.createDocumentFragment();
+
+ if ( safeFrag.createElement ) {
+ while ( list.length ) {
+ safeFrag.createElement(
+ list.pop()
+ );
+ }
+ }
+ return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" +
+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+ rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
+ rtagName = /<([\w:]+)/,
+ rtbody = /<tbody/i,
+ rhtml = /<|&#?\w+;/,
+ rnoInnerhtml = /<(?:script|style)/i,
+ rnocache = /<(?:script|object|embed|option|style)/i,
+ rnoshimcache = new RegExp("<(?:" + nodeNames + ")", "i"),
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptType = /\/(java|ecma)script/i,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
+ wrapMap = {
+ 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, "", "" ]
+ },
+ safeFragment = createSafeFragment( document );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE can't serialize <link> and <script> tags normally
+if ( !jQuery.support.htmlSerialize ) {
+ wrapMap._default = [ 1, "div<div>", "</div>" ];
+}
+
+jQuery.fn.extend({
+ text: function( text ) {
+ if ( jQuery.isFunction(text) ) {
+ return this.each(function(i) {
+ var self = jQuery( this );
+
+ self.text( text.call(this, i, self.text()) );
+ });
+ }
+
+ if ( typeof text !== "object" && text !== undefined ) {
+ return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+ }
+
+ return jQuery.text( this );
+ },
+
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
+ }
+
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
+ }
+
+ wrap.map(function() {
+ var elem = this;
+
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
+
+ return elem;
+ }).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
+ }
+
+ return this.each(function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each(function(i) {
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+ });
+ },
+
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.insertBefore( elem, this.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this );
+ });
+ } else if ( arguments.length ) {
+ var set = jQuery.clean( arguments );
+ set.push.apply( set, this.toArray() );
+ return this.pushStack( set, "before", arguments );
+ }
+ },
+
+ after: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ });
+ } else if ( arguments.length ) {
+ var set = this.pushStack( this, "after", arguments );
+ set.push.apply( set, jQuery.clean(arguments) );
+ return set;
+ }
+ },
+
+ // keepData is for internal use only--do not document
+ remove: function( selector, keepData ) {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ jQuery.cleanData( [ elem ] );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+ }
+ }
+
+ return this;
+ },
+
+ empty: function() {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ }
+
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map( function () {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ });
+ },
+
+ html: function( value ) {
+ if ( value === undefined ) {
+ return this[0] && this[0].nodeType === 1 ?
+ this[0].innerHTML.replace(rinlinejQuery, "") :
+ null;
+
+ // See if we can take a shortcut and just use innerHTML
+ } else if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
+ !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
+
+ value = value.replace(rxhtmlTag, "<$1></$2>");
+
+ try {
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( this[i].nodeType === 1 ) {
+ jQuery.cleanData( this[i].getElementsByTagName("*") );
+ this[i].innerHTML = value;
+ }
+ }
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {
+ this.empty().append( value );
+ }
+
+ } else if ( jQuery.isFunction( value ) ) {
+ this.each(function(i){
+ var self = jQuery( this );
+
+ self.html( value.call(this, i, self.html()) );
+ });
+
+ } else {
+ this.empty().append( value );
+ }
+
+ return this;
+ },
+
+ replaceWith: function( value ) {
+ if ( this[0] && this[0].parentNode ) {
+ // Make sure that the elements are removed from the DOM before they are inserted
+ // this can help fix replacing a parent with child elements
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function(i) {
+ var self = jQuery(this), old = self.html();
+ self.replaceWith( value.call( this, i, old ) );
+ });
+ }
+
+ if ( typeof value !== "string" ) {
+ value = jQuery( value ).detach();
+ }
+
+ return this.each(function() {
+ var next = this.nextSibling,
+ parent = this.parentNode;
+
+ jQuery( this ).remove();
+
+ if ( next ) {
+ jQuery(next).before( value );
+ } else {
+ jQuery(parent).append( value );
+ }
+ });
+ } else {
+ return this.length ?
+ this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
+ this;
+ }
+ },
+
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
+
+ domManip: function( args, table, callback ) {
+ var results, first, fragment, parent,
+ value = args[0],
+ scripts = [];
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
+ return this.each(function() {
+ jQuery(this).domManip( args, table, callback, true );
+ });
+ }
+
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ args[0] = value.call(this, i, table ? self.html() : undefined);
+ self.domManip( args, table, callback );
+ });
+ }
+
+ if ( this[0] ) {
+ parent = value && value.parentNode;
+
+ // If we're in a fragment, just use that instead of building a new one
+ if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
+ results = { fragment: parent };
+
+ } else {
+ results = jQuery.buildFragment( args, this, scripts );
+ }
+
+ fragment = results.fragment;
+
+ if ( fragment.childNodes.length === 1 ) {
+ first = fragment = fragment.firstChild;
+ } else {
+ first = fragment.firstChild;
+ }
+
+ if ( first ) {
+ table = table && jQuery.nodeName( first, "tr" );
+
+ for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
+ callback.call(
+ table ?
+ root(this[i], first) :
+ this[i],
+ // Make sure that we do not leak memory by inadvertently discarding
+ // the original fragment (which might have attached data) instead of
+ // using it; in addition, use the original fragment object for the last
+ // item instead of first because it can end up being emptied incorrectly
+ // in certain situations (Bug #8070).
+ // Fragments from the fragment cache must always be cloned and never used
+ // in place.
+ results.cacheable || ( l > 1 && i < lastIndex ) ?
+ jQuery.clone( fragment, true, true ) :
+ fragment
+ );
+ }
+ }
+
+ if ( scripts.length ) {
+ jQuery.each( scripts, evalScript );
+ }
+ }
+
+ return this;
+ }
+});
+
+function root( elem, cur ) {
+ return jQuery.nodeName(elem, "table") ?
+ (elem.getElementsByTagName("tbody")[0] ||
+ elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+ elem;
+}
+
+function cloneCopyEvent( src, dest ) {
+
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+ return;
+ }
+
+ var type, i, l,
+ oldData = jQuery._data( src ),
+ curData = jQuery._data( dest, oldData ),
+ events = oldData.events;
+
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
+ }
+ }
+ }
+
+ // make the cloned public data object a copy from the original
+ if ( curData.data ) {
+ curData.data = jQuery.extend( {}, curData.data );
+ }
+}
+
+function cloneFixAttributes( src, dest ) {
+ var nodeName;
+
+ // We do not need to do anything for non-Elements
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ // clearAttributes removes the attributes, which we don't want,
+ // but also removes the attachEvent events, which we *do* want
+ if ( dest.clearAttributes ) {
+ dest.clearAttributes();
+ }
+
+ // mergeAttributes, in contrast, only merges back on the
+ // original attributes, not the events
+ if ( dest.mergeAttributes ) {
+ dest.mergeAttributes( src );
+ }
+
+ nodeName = dest.nodeName.toLowerCase();
+
+ // IE6-8 fail to clone children inside object elements that use
+ // the proprietary classid attribute value (rather than the type
+ // attribute) to identify the type of content to display
+ if ( nodeName === "object" ) {
+ dest.outerHTML = src.outerHTML;
+
+ } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
+ // IE6-8 fails to persist the checked state of a cloned checkbox
+ // or radio button. Worse, IE6-7 fail to give the cloned element
+ // a checked appearance if the defaultChecked value isn't also set
+ if ( src.checked ) {
+ dest.defaultChecked = dest.checked = src.checked;
+ }
+
+ // IE6-7 get confused and end up setting the value of a cloned
+ // checkbox/radio button to an empty string instead of "on"
+ if ( dest.value !== src.value ) {
+ dest.value = src.value;
+ }
+
+ // IE6-8 fails to return the selected option to the default selected
+ // state when cloning options
+ } else if ( nodeName === "option" ) {
+ dest.selected = src.defaultSelected;
+
+ // IE6-8 fails to set the defaultValue to the correct value when
+ // cloning other types of input fields
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+ }
+
+ // Event data gets referenced instead of copied if the expando
+ // gets copied too
+ dest.removeAttribute( jQuery.expando );
+}
+
+jQuery.buildFragment = function( args, nodes, scripts ) {
+ var fragment, cacheable, cacheresults, doc,
+ first = args[ 0 ];
+
+ // nodes may contain either an explicit document object,
+ // a jQuery collection or context object.
+ // If nodes[0] contains a valid object to assign to doc
+ if ( nodes && nodes[0] ) {
+ doc = nodes[0].ownerDocument || nodes[0];
+ }
+
+ // Ensure that an attr object doesn't incorrectly stand in as a document object
+ // Chrome and Firefox seem to allow this to occur and will throw exception
+ // Fixes #8950
+ if ( !doc.createDocumentFragment ) {
+ doc = document;
+ }
+
+ // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
+ // Cloning options loses the selected state, so don't cache them
+ // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
+ // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+ // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
+ if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&
+ first.charAt(0) === "<" && !rnocache.test( first ) &&
+ (jQuery.support.checkClone || !rchecked.test( first )) &&
+ (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {
+
+ cacheable = true;
+
+ cacheresults = jQuery.fragments[ first ];
+ if ( cacheresults && cacheresults !== 1 ) {
+ fragment = cacheresults;
+ }
+ }
+
+ if ( !fragment ) {
+ fragment = doc.createDocumentFragment();
+ jQuery.clean( args, doc, fragment, scripts );
+ }
+
+ if ( cacheable ) {
+ jQuery.fragments[ first ] = cacheresults ? fragment : 1;
+ }
+
+ return { fragment: fragment, cacheable: cacheable };
+};
+
+jQuery.fragments = {};
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var ret = [],
+ insert = jQuery( selector ),
+ parent = this.length === 1 && this[0].parentNode;
+
+ if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
+ insert[ original ]( this[0] );
+ return this;
+
+ } else {
+ for ( var i = 0, l = insert.length; i < l; i++ ) {
+ var elems = ( i > 0 ? this.clone(true) : this ).get();
+ jQuery( insert[i] )[ original ]( elems );
+ ret = ret.concat( elems );
+ }
+
+ return this.pushStack( ret, name, insert.selector );
+ }
+ };
+});
+
+function getAll( elem ) {
+ if ( typeof elem.getElementsByTagName !== "undefined" ) {
+ return elem.getElementsByTagName( "*" );
+
+ } else if ( typeof elem.querySelectorAll !== "undefined" ) {
+ return elem.querySelectorAll( "*" );
+
+ } else {
+ return [];
+ }
+}
+
+// Used in clean, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+ if ( elem.type === "checkbox" || elem.type === "radio" ) {
+ elem.defaultChecked = elem.checked;
+ }
+}
+// Finds all inputs and passes them to fixDefaultChecked
+function findInputs( elem ) {
+ var nodeName = ( elem.nodeName || "" ).toLowerCase();
+ if ( nodeName === "input" ) {
+ fixDefaultChecked( elem );
+ // Skip scripts, get other children
+ } else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) {
+ jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
+ }
+}
+
+// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js
+function shimCloneNode( elem ) {
+ var div = document.createElement( "div" );
+ safeFragment.appendChild( div );
+
+ div.innerHTML = elem.outerHTML;
+ return div.firstChild;
+}
+
+jQuery.extend({
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var srcElements,
+ destElements,
+ i,
+ // IE<=8 does not properly clone detached, unknown element nodes
+ clone = jQuery.support.html5Clone || !rnoshimcache.test( "<" + elem.nodeName ) ?
+ elem.cloneNode( true ) :
+ shimCloneNode( elem );
+
+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+ // IE copies events bound via attachEvent when using cloneNode.
+ // Calling detachEvent on the clone will also remove the events
+ // from the original. In order to get around this, we use some
+ // proprietary methods to clear the events. Thanks to MooTools
+ // guys for this hotness.
+
+ cloneFixAttributes( elem, clone );
+
+ // Using Sizzle here is crazy slow, so we use getElementsByTagName instead
+ srcElements = getAll( elem );
+ destElements = getAll( clone );
+
+ // Weird iteration because IE will replace the length property
+ // with an element if you are cloning the body and one of the
+ // elements on the page has a name or id of "length"
+ for ( i = 0; srcElements[i]; ++i ) {
+ // Ensure that the destination node is not null; Fixes #9587
+ if ( destElements[i] ) {
+ cloneFixAttributes( srcElements[i], destElements[i] );
+ }
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ cloneCopyEvent( elem, clone );
+
+ if ( deepDataAndEvents ) {
+ srcElements = getAll( elem );
+ destElements = getAll( clone );
+
+ for ( i = 0; srcElements[i]; ++i ) {
+ cloneCopyEvent( srcElements[i], destElements[i] );
+ }
+ }
+ }
+
+ srcElements = destElements = null;
+
+ // Return the cloned set
+ return clone;
+ },
+
+ clean: function( elems, context, fragment, scripts ) {
+ var checkScriptType;
+
+ context = context || document;
+
+ // !context.createElement fails in IE with an error but returns typeof 'object'
+ if ( typeof context.createElement === "undefined" ) {
+ context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+ }
+
+ var ret = [], j;
+
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ if ( typeof elem === "number" ) {
+ elem += "";
+ }
+
+ if ( !elem ) {
+ continue;
+ }
+
+ // Convert html string into DOM nodes
+ if ( typeof elem === "string" ) {
+ if ( !rhtml.test( elem ) ) {
+ elem = context.createTextNode( elem );
+ } else {
+ // Fix "XHTML"-style tags in all browsers
+ elem = elem.replace(rxhtmlTag, "<$1></$2>");
+
+ // Trim whitespace, otherwise indexOf won't work as expected
+ var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(),
+ wrap = wrapMap[ tag ] || wrapMap._default,
+ depth = wrap[0],
+ div = context.createElement("div");
+
+ // Append wrapper element to unknown element safe doc fragment
+ if ( context === document ) {
+ // Use the fragment we've already created for this document
+ safeFragment.appendChild( div );
+ } else {
+ // Use a fragment created with the owner document
+ createSafeFragment( context ).appendChild( div );
+ }
+
+ // Go to html and back, then peel off extra wrappers
+ div.innerHTML = wrap[1] + elem + wrap[2];
+
+ // Move to the right depth
+ while ( depth-- ) {
+ div = div.lastChild;
+ }
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !jQuery.support.tbody ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ var hasBody = rtbody.test(elem),
+ tbody = tag === "table" && !hasBody ?
+ div.firstChild && div.firstChild.childNodes :
+
+ // String was a bare <thead> or <tfoot>
+ wrap[1] === "<table>" && !hasBody ?
+ div.childNodes :
+ [];
+
+ for ( j = tbody.length - 1; j >= 0 ; --j ) {
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
+ }
+ }
+ }
+
+ // IE completely kills leading whitespace when innerHTML is used
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+ div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+ }
+
+ elem = div.childNodes;
+ }
+ }
+
+ // Resets defaultChecked for any radios and checkboxes
+ // about to be appended to the DOM in IE 6/7 (#8060)
+ var len;
+ if ( !jQuery.support.appendChecked ) {
+ if ( elem[0] && typeof (len = elem.length) === "number" ) {
+ for ( j = 0; j < len; j++ ) {
+ findInputs( elem[j] );
+ }
+ } else {
+ findInputs( elem );
+ }
+ }
+
+ if ( elem.nodeType ) {
+ ret.push( elem );
+ } else {
+ ret = jQuery.merge( ret, elem );
+ }
+ }
+
+ if ( fragment ) {
+ checkScriptType = function( elem ) {
+ return !elem.type || rscriptType.test( elem.type );
+ };
+ for ( i = 0; ret[i]; i++ ) {
+ if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+ scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+
+ } else {
+ if ( ret[i].nodeType === 1 ) {
+ var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );
+
+ ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
+ }
+ fragment.appendChild( ret[i] );
+ }
+ }
+ }
+
+ return ret;
+ },
+
+ cleanData: function( elems ) {
+ var data, id,
+ cache = jQuery.cache,
+ special = jQuery.event.special,
+ deleteExpando = jQuery.support.deleteExpando;
+
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+ continue;
+ }
+
+ id = elem[ jQuery.expando ];
+
+ if ( id ) {
+ data = cache[ id ];
+
+ if ( data && data.events ) {
+ for ( var type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+
+ // Null the DOM reference to avoid IE6/7/8 leak (#7054)
+ if ( data.handle ) {
+ data.handle.elem = null;
+ }
+ }
+
+ if ( deleteExpando ) {
+ delete elem[ jQuery.expando ];
+
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( jQuery.expando );
+ }
+
+ delete cache[ id ];
+ }
+ }
+ }
+});
+
+function evalScript( i, elem ) {
+ if ( elem.src ) {
+ jQuery.ajax({
+ url: elem.src,
+ async: false,
+ dataType: "script"
+ });
+ } else {
+ jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+}
+
+
+
+
+var ralpha = /alpha\([^)]*\)/i,
+ ropacity = /opacity=([^)]*)/,
+ // fixed for IE9, see #8346
+ rupper = /([A-Z]|^ms)/g,
+ rnumpx = /^-?\d+(?:px)?$/i,
+ rnum = /^-?\d/,
+ rrelNum = /^([\-+])=([\-+.\de]+)/,
+
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssWidth = [ "Left", "Right" ],
+ cssHeight = [ "Top", "Bottom" ],
+ curCSS,
+
+ getComputedStyle,
+ currentStyle;
+
+jQuery.fn.css = function( name, value ) {
+ // Setting 'undefined' is a no-op
+ if ( arguments.length === 2 && value === undefined ) {
+ return this;
+ }
+
+ return jQuery.access( this, name, value, true, function( elem, name, value ) {
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ });
+};
+
+jQuery.extend({
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity", "opacity" );
+ return ret === "" ? "1" : ret;
+
+ } else {
+ return elem.style.opacity;
+ }
+ }
+ }
+ },
+
+ // Exclude the following css properties to add px
+ cssNumber: {
+ "fillOpacity": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ // normalize float css property
+ "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, origName = jQuery.camelCase( name ),
+ style = elem.style, hooks = jQuery.cssHooks[ origName ];
+
+ name = jQuery.cssProps[ origName ] || origName;
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // convert relative number strings (+= or -=) to relative numbers. #7345
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+ value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that NaN and null values aren't set. See: #7116
+ if ( value == null || type === "number" && isNaN( value ) ) {
+ return;
+ }
+
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+ value += "px";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
+ // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+ // Fixes bug #5509
+ try {
+ style[ name ] = value;
+ } catch(e) {}
+ }
+
+ } else {
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra ) {
+ var ret, hooks;
+
+ // Make sure that we're working with the right name
+ name = jQuery.camelCase( name );
+ hooks = jQuery.cssHooks[ name ];
+ name = jQuery.cssProps[ name ] || name;
+
+ // cssFloat needs a special treatment
+ if ( name === "cssFloat" ) {
+ name = "float";
+ }
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
+ return ret;
+
+ // Otherwise, if a way to get the computed value exists, use that
+ } else if ( curCSS ) {
+ return curCSS( elem, name );
+ }
+ },
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback ) {
+ var old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( var name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ callback.call( elem );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+ }
+});
+
+// DEPRECATED, Use jQuery.css() instead
+jQuery.curCSS = jQuery.css;
+
+jQuery.each(["height", "width"], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ var val;
+
+ if ( computed ) {
+ if ( elem.offsetWidth !== 0 ) {
+ return getWH( elem, name, extra );
+ } else {
+ jQuery.swap( elem, cssShow, function() {
+ val = getWH( elem, name, extra );
+ });
+ }
+
+ return val;
+ }
+ },
+
+ set: function( elem, value ) {
+ if ( rnumpx.test( value ) ) {
+ // ignore negative width and height values #1599
+ value = parseFloat( value );
+
+ if ( value >= 0 ) {
+ return value + "px";
+ }
+
+ } else {
+ return value;
+ }
+ }
+ };
+});
+
+if ( !jQuery.support.opacity ) {
+ jQuery.cssHooks.opacity = {
+ get: function( elem, computed ) {
+ // IE uses filters for opacity
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+ ( parseFloat( RegExp.$1 ) / 100 ) + "" :
+ computed ? "1" : "";
+ },
+
+ set: function( elem, value ) {
+ var style = elem.style,
+ currentStyle = elem.currentStyle,
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+ filter = currentStyle && currentStyle.filter || style.filter || "";
+
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
+
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+ if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {
+
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
+ // style.removeAttribute is IE Only, but so apparently is this code path...
+ style.removeAttribute( "filter" );
+
+ // if there there is no filter style applied in a css rule, we are done
+ if ( currentStyle && !currentStyle.filter ) {
+ return;
+ }
+ }
+
+ // otherwise, set new filter values
+ style.filter = ralpha.test( filter ) ?
+ filter.replace( ralpha, opacity ) :
+ filter + " " + opacity;
+ }
+ };
+}
+
+jQuery(function() {
+ // This hook cannot be added until DOM ready because the support test
+ // for it is not run until after DOM ready
+ if ( !jQuery.support.reliableMarginRight ) {
+ jQuery.cssHooks.marginRight = {
+ get: function( elem, computed ) {
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ // Work around by temporarily setting element display to inline-block
+ var ret;
+ jQuery.swap( elem, { "display": "inline-block" }, function() {
+ if ( computed ) {
+ ret = curCSS( elem, "margin-right", "marginRight" );
+ } else {
+ ret = elem.style.marginRight;
+ }
+ });
+ return ret;
+ }
+ };
+ }
+});
+
+if ( document.defaultView && document.defaultView.getComputedStyle ) {
+ getComputedStyle = function( elem, name ) {
+ var ret, defaultView, computedStyle;
+
+ name = name.replace( rupper, "-$1" ).toLowerCase();
+
+ if ( (defaultView = elem.ownerDocument.defaultView) &&
+ (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
+ ret = computedStyle.getPropertyValue( name );
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+ }
+
+ return ret;
+ };
+}
+
+if ( document.documentElement.currentStyle ) {
+ currentStyle = function( elem, name ) {
+ var left, rsLeft, uncomputed,
+ ret = elem.currentStyle && elem.currentStyle[ name ],
+ style = elem.style;
+
+ // Avoid setting ret to empty string here
+ // so we don't default to auto
+ if ( ret === null && style && (uncomputed = style[ name ]) ) {
+ ret = uncomputed;
+ }
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
+
+ // Remember the original values
+ left = style.left;
+ rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
+
+ // Put in the new values to get a computed value out
+ if ( rsLeft ) {
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ }
+ style.left = name === "fontSize" ? "1em" : ( ret || 0 );
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ if ( rsLeft ) {
+ elem.runtimeStyle.left = rsLeft;
+ }
+ }
+
+ return ret === "" ? "auto" : ret;
+ };
+}
+
+curCSS = getComputedStyle || currentStyle;
+
+function getWH( elem, name, extra ) {
+
+ // Start with offset property
+ var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ which = name === "width" ? cssWidth : cssHeight,
+ i = 0,
+ len = which.length;
+
+ if ( val > 0 ) {
+ if ( extra !== "border" ) {
+ for ( ; i < len; i++ ) {
+ if ( !extra ) {
+ val -= parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
+ }
+ if ( extra === "margin" ) {
+ val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
+ } else {
+ val -= parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
+ }
+ }
+ }
+
+ return val + "px";
+ }
+
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name, name );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ] || 0;
+ }
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+
+ // Add padding, border, margin
+ if ( extra ) {
+ for ( ; i < len; i++ ) {
+ val += parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
+ if ( extra !== "padding" ) {
+ val += parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
+ }
+ if ( extra === "margin" ) {
+ val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
+ }
+ }
+ }
+
+ return val + "px";
+}
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.hidden = function( elem ) {
+ var width = elem.offsetWidth,
+ height = elem.offsetHeight;
+
+ return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+ };
+
+ jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+ };
+}
+
+
+
+
+var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rhash = /#.*$/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+ rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+ rquery = /\?/,
+ rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+ rselectTextarea = /^(?:select|textarea)/i,
+ rspacesAjax = /\s+/,
+ rts = /([?&])_=[^&]*/,
+ rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
+
+ // Keep a copy of the old load method
+ _load = jQuery.fn.load,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Document location
+ ajaxLocation,
+
+ // Document location segments
+ ajaxLocParts,
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = ["*/"] + ["*"];
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+ ajaxLocation = location.href;
+} catch( e ) {
+ // Use the href attribute of an A element
+ // since IE will modify it given document.location
+ ajaxLocation = document.createElement( "a" );
+ ajaxLocation.href = "";
+ ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ if ( jQuery.isFunction( func ) ) {
+ var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
+ i = 0,
+ length = dataTypes.length,
+ dataType,
+ list,
+ placeBefore;
+
+ // For each dataType in the dataTypeExpression
+ for ( ; i < length; i++ ) {
+ dataType = dataTypes[ i ];
+ // We control if we're asked to add before
+ // any existing element
+ placeBefore = /^\+/.test( dataType );
+ if ( placeBefore ) {
+ dataType = dataType.substr( 1 ) || "*";
+ }
+ list = structure[ dataType ] = structure[ dataType ] || [];
+ // then we add to the structure accordingly
+ list[ placeBefore ? "unshift" : "push" ]( func );
+ }
+ }
+ };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
+ dataType /* internal */, inspected /* internal */ ) {
+
+ dataType = dataType || options.dataTypes[ 0 ];
+ inspected = inspected || {};
+
+ inspected[ dataType ] = true;
+
+ var list = structure[ dataType ],
+ i = 0,
+ length = list ? list.length : 0,
+ executeOnly = ( structure === prefilters ),
+ selection;
+
+ for ( ; i < length && ( executeOnly || !selection ); i++ ) {
+ selection = list[ i ]( options, originalOptions, jqXHR );
+ // If we got redirected to another dataType
+ // we try there if executing only and not done already
+ if ( typeof selection === "string" ) {
+ if ( !executeOnly || inspected[ selection ] ) {
+ selection = undefined;
+ } else {
+ options.dataTypes.unshift( selection );
+ selection = inspectPrefiltersOrTransports(
+ structure, options, originalOptions, jqXHR, selection, inspected );
+ }
+ }
+ }
+ // If we're only executing or nothing was selected
+ // we try the catchall dataType if not done already
+ if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
+ selection = inspectPrefiltersOrTransports(
+ structure, options, originalOptions, jqXHR, "*", inspected );
+ }
+ // unnecessary when only executing (prefilters)
+ // but it'll be ignored by the caller in that case
+ return selection;
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+ var key, deep,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+}
+
+jQuery.fn.extend({
+ load: function( url, params, callback ) {
+ if ( typeof url !== "string" && _load ) {
+ return _load.apply( this, arguments );
+
+ // Don't do a request if no elements are being requested
+ } else if ( !this.length ) {
+ return this;
+ }
+
+ var off = url.indexOf( " " );
+ if ( off >= 0 ) {
+ var selector = url.slice( off, url.length );
+ url = url.slice( 0, off );
+ }
+
+ // Default to a GET request
+ var type = "GET";
+
+ // If the second parameter was provided
+ if ( params ) {
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( typeof params === "object" ) {
+ params = jQuery.param( params, jQuery.ajaxSettings.traditional );
+ type = "POST";
+ }
+ }
+
+ var self = this;
+
+ // Request the remote document
+ jQuery.ajax({
+ url: url,
+ type: type,
+ dataType: "html",
+ data: params,
+ // Complete callback (responseText is used internally)
+ complete: function( jqXHR, status, responseText ) {
+ // Store the response as specified by the jqXHR object
+ responseText = jqXHR.responseText;
+ // If successful, inject the HTML into all the matched elements
+ if ( jqXHR.isResolved() ) {
+ // #4825: Get the actual response in case
+ // a dataFilter is present in ajaxSettings
+ jqXHR.done(function( r ) {
+ responseText = r;
+ });
+ // See if a selector was specified
+ self.html( selector ?
+ // Create a dummy div to hold the results
+ jQuery("<div>")
+ // inject the contents of the document in, removing the scripts
+ // to avoid any 'Permission Denied' errors in IE
+ .append(responseText.replace(rscript, ""))
+
+ // Locate the specified elements
+ .find(selector) :
+
+ // If not, just inject the full result
+ responseText );
+ }
+
+ if ( callback ) {
+ self.each( callback, [ responseText, status, jqXHR ] );
+ }
+ }
+ });
+
+ return this;
+ },
+
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+
+ serializeArray: function() {
+ return this.map(function(){
+ return this.elements ? jQuery.makeArray( this.elements ) : this;
+ })
+ .filter(function(){
+ return this.name && !this.disabled &&
+ ( this.checked || rselectTextarea.test( this.nodeName ) ||
+ rinput.test( this.type ) );
+ })
+ .map(function( i, elem ){
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val, i ){
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }).get();
+ }
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
+ jQuery.fn[ o ] = function( f ){
+ return this.on( o, f );
+ };
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+ // shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ return jQuery.ajax({
+ type: method,
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ };
+});
+
+jQuery.extend({
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ if ( settings ) {
+ // Building a settings object
+ ajaxExtend( target, jQuery.ajaxSettings );
+ } else {
+ // Extending ajaxSettings
+ settings = target;
+ target = jQuery.ajaxSettings;
+ }
+ ajaxExtend( target, settings );
+ return target;
+ },
+
+ ajaxSettings: {
+ url: ajaxLocation,
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+ global: true,
+ type: "GET",
+ contentType: "application/x-www-form-urlencoded",
+ processData: true,
+ async: true,
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ xml: "application/xml, text/xml",
+ html: "text/html",
+ text: "text/plain",
+ json: "application/json, text/javascript",
+ "*": allTypes
+ },
+
+ contents: {
+ xml: /xml/,
+ html: /html/,
+ json: /json/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText"
+ },
+
+ // List of data converters
+ // 1) key format is "source_type destination_type" (a single space in-between)
+ // 2) the catchall symbol "*" can be used for source_type
+ converters: {
+
+ // Convert anything to text
+ "* text": window.String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ context: true,
+ url: true
+ }
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+ // Callbacks context
+ callbackContext = s.context || s,
+ // Context for global events
+ // It's the callbackContext if one was provided in the options
+ // and if it's a DOM node or a jQuery collection
+ globalEventContext = callbackContext !== s &&
+ ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
+ jQuery( callbackContext ) : jQuery.event,
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks( "once memory" ),
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+ // ifModified key
+ ifModifiedKey,
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+ // Response headers
+ responseHeadersString,
+ responseHeaders,
+ // transport
+ transport,
+ // timeout handle
+ timeoutTimer,
+ // Cross-domain detection vars
+ parts,
+ // The jqXHR state
+ state = 0,
+ // To know if global events are to be dispatched
+ fireGlobals,
+ // Loop variable
+ i,
+ // Fake xhr
+ jqXHR = {
+
+ readyState: 0,
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ if ( !state ) {
+ var lname = name.toLowerCase();
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( state === 2 ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while( ( match = rheaders.exec( responseHeadersString ) ) ) {
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match === undefined ? null : match;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( !state ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ statusText = statusText || "abort";
+ if ( transport ) {
+ transport.abort( statusText );
+ }
+ done( 0, statusText );
+ return this;
+ }
+ };
+
+ // Callback for when everything is done
+ // It is defined here because jslint complains if it is declared
+ // at the end of the function (which would be more logical and readable)
+ function done( status, nativeStatusText, responses, headers ) {
+
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
+
+ // State is "done" now
+ state = 2;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ var isSuccess,
+ success,
+ error,
+ statusText = nativeStatusText,
+ response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
+ lastModified,
+ etag;
+
+ // If successful, handle type chaining
+ if ( status >= 200 && status < 300 || status === 304 ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+
+ if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
+ jQuery.lastModified[ ifModifiedKey ] = lastModified;
+ }
+ if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
+ jQuery.etag[ ifModifiedKey ] = etag;
+ }
+ }
+
+ // If not modified
+ if ( status === 304 ) {
+
+ statusText = "notmodified";
+ isSuccess = true;
+
+ // If we have data
+ } else {
+
+ try {
+ success = ajaxConvert( s, response );
+ statusText = "success";
+ isSuccess = true;
+ } catch(e) {
+ // We have a parsererror
+ statusText = "parsererror";
+ error = e;
+ }
+ }
+ } else {
+ // We extract error from statusText
+ // then normalize statusText and status for non-aborts
+ error = statusText;
+ if ( !statusText || status ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = "" + ( nativeStatusText || statusText );
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ }
+ }
+
+ // Attach deferreds
+ deferred.promise( jqXHR );
+ jqXHR.success = jqXHR.done;
+ jqXHR.error = jqXHR.fail;
+ jqXHR.complete = completeDeferred.add;
+
+ // Status-dependent callbacks
+ jqXHR.statusCode = function( map ) {
+ if ( map ) {
+ var tmp;
+ if ( state < 2 ) {
+ for ( tmp in map ) {
+ statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
+ }
+ } else {
+ tmp = map[ jqXHR.status ];
+ jqXHR.then( tmp, tmp );
+ }
+ }
+ return this;
+ };
+
+ // Remove hash character (#7531: and string promotion)
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
+
+ // Determine if a cross-domain request is in order
+ if ( s.crossDomain == null ) {
+ parts = rurl.exec( s.url.toLowerCase() );
+ s.crossDomain = !!( parts &&
+ ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
+ );
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefiler, stop there
+ if ( state === 2 ) {
+ return false;
+ }
+
+ // We can fire global events as of now if asked to
+ fireGlobals = s.global;
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger( "ajaxStart" );
+ }
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Get ifModifiedKey before adding the anti-cache parameter
+ ifModifiedKey = s.url;
+
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
+
+ var ts = jQuery.now(),
+ // try replacing _= if it is there
+ ret = s.url.replace( rts, "$1_=" + ts );
+
+ // if nothing was replaced, add timestamp to the end
+ s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ ifModifiedKey = ifModifiedKey || s.url;
+ if ( jQuery.lastModified[ ifModifiedKey ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
+ }
+ if ( jQuery.etag[ ifModifiedKey ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
+ }
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+ // Abort if not done already
+ jqXHR.abort();
+ return false;
+
+ }
+
+ // Install callbacks on deferreds
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
+ jqXHR[ i ]( s[ i ] );
+ }
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = setTimeout( function(){
+ jqXHR.abort( "timeout" );
+ }, s.timeout );
+ }
+
+ try {
+ state = 1;
+ transport.send( requestHeaders, done );
+ } catch (e) {
+ // Propagate exception as error if not done
+ if ( state < 2 ) {
+ done( -1, e );
+ // Simply rethrow otherwise
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ // Serialize an array of form elements or a set of
+ // key/values into a query string
+ param: function( a, traditional ) {
+ var s = [],
+ add = function( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction( value ) ? value() : value;
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+ };
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( var prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" ).replace( r20, "+" );
+ }
+});
+
+function buildParams( prefix, obj, traditional, add ) {
+ if ( jQuery.isArray( obj ) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+ // If array item is non-scalar (array or object), encode its
+ // numeric index to resolve deserialization ambiguity issues.
+ // Note that rack (as of 1.0.0) can't currently deserialize
+ // nested arrays properly, and attempting to do so may cause
+ // a server error. Possible fixes are to modify rack's
+ // deserialization algorithm or to provide an option or flag
+ // to force array serialization to be shallow.
+ buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
+ }
+ });
+
+ } else if ( !traditional && obj != null && typeof obj === "object" ) {
+ // Serialize object item.
+ for ( var name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+
+// This is still on the jQuery object... for now
+// Want to move this to jQuery.ajax some day
+jQuery.extend({
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {}
+
+});
+
+/* Handles responses to an ajax request:
+ * - sets all responseXXX fields accordingly
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+ var contents = s.contents,
+ dataTypes = s.dataTypes,
+ responseFields = s.responseFields,
+ ct,
+ type,
+ finalDataType,
+ firstDataType;
+
+ // Fill responseXXX fields
+ for ( type in responseFields ) {
+ if ( type in responses ) {
+ jqXHR[ responseFields[type] ] = responses[ type ];
+ }
+ }
+
+ // Remove auto dataType and get content-type in the process
+ while( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+// Chain conversions given the request and the original response
+function ajaxConvert( s, response ) {
+
+ // Apply the dataFilter if provided
+ if ( s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ var dataTypes = s.dataTypes,
+ converters = {},
+ i,
+ key,
+ length = dataTypes.length,
+ tmp,
+ // Current and previous dataTypes
+ current = dataTypes[ 0 ],
+ prev,
+ // Conversion expression
+ conversion,
+ // Conversion function
+ conv,
+ // Conversion functions (transitive conversion)
+ conv1,
+ conv2;
+
+ // For each dataType in the chain
+ for ( i = 1; i < length; i++ ) {
+
+ // Create converters map
+ // with lowercased keys
+ if ( i === 1 ) {
+ for ( key in s.converters ) {
+ if ( typeof key === "string" ) {
+ converters[ key.toLowerCase() ] = s.converters[ key ];
+ }
+ }
+ }
+
+ // Get the dataTypes
+ prev = current;
+ current = dataTypes[ i ];
+
+ // If current is auto dataType, update it to prev
+ if ( current === "*" ) {
+ current = prev;
+ // If no auto and dataTypes are actually different
+ } else if ( prev !== "*" && prev !== current ) {
+
+ // Get the converter
+ conversion = prev + " " + current;
+ conv = converters[ conversion ] || converters[ "* " + current ];
+
+ // If there is no direct converter, search transitively
+ if ( !conv ) {
+ conv2 = undefined;
+ for ( conv1 in converters ) {
+ tmp = conv1.split( " " );
+ if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
+ conv2 = converters[ tmp[1] + " " + current ];
+ if ( conv2 ) {
+ conv1 = converters[ conv1 ];
+ if ( conv1 === true ) {
+ conv = conv2;
+ } else if ( conv2 === true ) {
+ conv = conv1;
+ }
+ break;
+ }
+ }
+ }
+ }
+ // If we found no converter, dispatch an error
+ if ( !( conv || conv2 ) ) {
+ jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
+ }
+ // If found converter is not an equivalence
+ if ( conv !== true ) {
+ // Convert with 1 or 2 converters accordingly
+ response = conv ? conv( response ) : conv2( conv1(response) );
+ }
+ }
+ }
+ return response;
+}
+
+
+
+
+var jsc = jQuery.now(),
+ jsre = /(\=)\?(&|$)|\?\?/i;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+ jsonp: "callback",
+ jsonpCallback: function() {
+ return jQuery.expando + "_" + ( jsc++ );
+ }
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
+ ( typeof s.data === "string" );
+
+ if ( s.dataTypes[ 0 ] === "jsonp" ||
+ s.jsonp !== false && ( jsre.test( s.url ) ||
+ inspectData && jsre.test( s.data ) ) ) {
+
+ var responseContainer,
+ jsonpCallback = s.jsonpCallback =
+ jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
+ previous = window[ jsonpCallback ],
+ url = s.url,
+ data = s.data,
+ replace = "$1" + jsonpCallback + "$2";
+
+ if ( s.jsonp !== false ) {
+ url = url.replace( jsre, replace );
+ if ( s.url === url ) {
+ if ( inspectData ) {
+ data = data.replace( jsre, replace );
+ }
+ if ( s.data === data ) {
+ // Add callback manually
+ url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
+ }
+ }
+ }
+
+ s.url = url;
+ s.data = data;
+
+ // Install callback
+ window[ jsonpCallback ] = function( response ) {
+ responseContainer = [ response ];
+ };
+
+ // Clean-up function
+ jqXHR.always(function() {
+ // Set callback back to previous value
+ window[ jsonpCallback ] = previous;
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( previous ) ) {
+ window[ jsonpCallback ]( responseContainer[ 0 ] );
+ }
+ });
+
+ // Use data converter to retrieve json after script execution
+ s.converters["script json"] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( jsonpCallback + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Delegate to script
+ return "script";
+ }
+});
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup({
+ accepts: {
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /javascript|ecmascript/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ s.global = false;
+ }
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+
+ var script,
+ head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
+
+ return {
+
+ send: function( _, callback ) {
+
+ script = document.createElement( "script" );
+
+ script.async = "async";
+
+ if ( s.scriptCharset ) {
+ script.charset = s.scriptCharset;
+ }
+
+ script.src = s.url;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+
+ // Remove the script
+ if ( head && script.parentNode ) {
+ head.removeChild( script );
+ }
+
+ // Dereference the script
+ script = undefined;
+
+ // Callback if not abort
+ if ( !isAbort ) {
+ callback( 200, "success" );
+ }
+ }
+ };
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+ // This arises when a base node is used (#2709 and #4378).
+ head.insertBefore( script, head.firstChild );
+ },
+
+ abort: function() {
+ if ( script ) {
+ script.onload( 0, 1 );
+ }
+ }
+ };
+ }
+});
+
+
+
+
+var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
+ xhrOnUnloadAbort = window.ActiveXObject ? function() {
+ // Abort all pending requests
+ for ( var key in xhrCallbacks ) {
+ xhrCallbacks[ key ]( 0, 1 );
+ }
+ } : false,
+ xhrId = 0,
+ xhrCallbacks;
+
+// Functions to create xhrs
+function createStandardXHR() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch( e ) {}
+}
+
+function createActiveXHR() {
+ try {
+ return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+ } catch( e ) {}
+}
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject ?
+ /* Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+ function() {
+ return !this.isLocal && createStandardXHR() || createActiveXHR();
+ } :
+ // For all other browsers, use the standard XMLHttpRequest object
+ createStandardXHR;
+
+// Determine support properties
+(function( xhr ) {
+ jQuery.extend( jQuery.support, {
+ ajax: !!xhr,
+ cors: !!xhr && ( "withCredentials" in xhr )
+ });
+})( jQuery.ajaxSettings.xhr() );
+
+// Create transport if the browser can provide an xhr
+if ( jQuery.support.ajax ) {
+
+ jQuery.ajaxTransport(function( s ) {
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( !s.crossDomain || jQuery.support.cors ) {
+
+ var callback;
+
+ return {
+ send: function( headers, complete ) {
+
+ // Get a new xhr
+ var xhr = s.xhr(),
+ handle,
+ i;
+
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if ( s.username ) {
+ xhr.open( s.type, s.url, s.async, s.username, s.password );
+ } else {
+ xhr.open( s.type, s.url, s.async );
+ }
+
+ // Apply custom fields if provided
+ if ( s.xhrFields ) {
+ for ( i in s.xhrFields ) {
+ xhr[ i ] = s.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( s.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( s.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
+ headers[ "X-Requested-With" ] = "XMLHttpRequest";
+ }
+
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+ } catch( _ ) {}
+
+ // Do send the request
+ // This may raise an exception which is actually
+ // handled in jQuery.ajax (so no try/catch here)
+ xhr.send( ( s.hasContent && s.data ) || null );
+
+ // Listener
+ callback = function( _, isAbort ) {
+
+ var status,
+ statusText,
+ responseHeaders,
+ responses,
+ xml;
+
+ // Firefox throws exceptions when accessing properties
+ // of an xhr when a network error occured
+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:...
+ try {
+
+ // Was never called and is aborted or complete
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+ // Only called once
+ callback = undefined;
+
+ // Do not keep as active anymore
+ if ( handle ) {
+ xhr.onreadystatechange = jQuery.noop;
+ if ( xhrOnUnloadAbort ) {
+ delete xhrCallbacks[ handle ];
+ }
+ }
+
+ // If it's an abort
+ if ( isAbort ) {
+ // Abort it manually if needed
+ if ( xhr.readyState !== 4 ) {
+ xhr.abort();
+ }
+ } else {
+ status = xhr.status;
+ responseHeaders = xhr.getAllResponseHeaders();
+ responses = {};
+ xml = xhr.responseXML;
+
+ // Construct response list
+ if ( xml && xml.documentElement /* #4958 */ ) {
+ responses.xml = xml;
+ }
+ responses.text = xhr.responseText;
+
+ // Firefox throws an exception when accessing
+ // statusText for faulty cross-domain requests
+ try {
+ statusText = xhr.statusText;
+ } catch( e ) {
+ // We normalize with Webkit giving an empty statusText
+ statusText = "";
+ }
+
+ // Filter status for non standard behaviors
+
+ // If the request is local and we have data: assume a success
+ // (success with no data won't get notified, that's the best we
+ // can do given current implementations)
+ if ( !status && s.isLocal && !s.crossDomain ) {
+ status = responses.text ? 200 : 404;
+ // IE - #1450: sometimes returns 1223 when it should be 204
+ } else if ( status === 1223 ) {
+ status = 204;
+ }
+ }
+ }
+ } catch( firefoxAccessException ) {
+ if ( !isAbort ) {
+ complete( -1, firefoxAccessException );
+ }
+ }
+
+ // Call complete if needed
+ if ( responses ) {
+ complete( status, statusText, responses, responseHeaders );
+ }
+ };
+
+ // if we're in sync mode or it's in cache
+ // and has been retrieved directly (IE6 & IE7)
+ // we need to manually fire the callback
+ if ( !s.async || xhr.readyState === 4 ) {
+ callback();
+ } else {
+ handle = ++xhrId;
+ if ( xhrOnUnloadAbort ) {
+ // Create the active xhrs callbacks list if needed
+ // and attach the unload handler
+ if ( !xhrCallbacks ) {
+ xhrCallbacks = {};
+ jQuery( window ).unload( xhrOnUnloadAbort );
+ }
+ // Add to list of active xhrs callbacks
+ xhrCallbacks[ handle ] = callback;
+ }
+ xhr.onreadystatechange = callback;
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback(0,1);
+ }
+ }
+ };
+ }
+ });
+}
+
+
+
+
+var elemdisplay = {},
+ iframe, iframeDoc,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
+ timerId,
+ fxAttrs = [
+ // height animations
+ [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+ // width animations
+ [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+ // opacity animations
+ [ "opacity" ]
+ ],
+ fxNow;
+
+jQuery.fn.extend({
+ show: function( speed, easing, callback ) {
+ var elem, display;
+
+ if ( speed || speed === 0 ) {
+ return this.animate( genFx("show", 3), speed, easing, callback );
+
+ } else {
+ for ( var i = 0, j = this.length; i < j; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.style ) {
+ display = elem.style.display;
+
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
+ display = elem.style.display = "";
+ }
+
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( display === "" && jQuery.css(elem, "display") === "none" ) {
+ jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
+ }
+ }
+ }
+
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( i = 0; i < j; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.style ) {
+ display = elem.style.display;
+
+ if ( display === "" || display === "none" ) {
+ elem.style.display = jQuery._data( elem, "olddisplay" ) || "";
+ }
+ }
+ }
+
+ return this;
+ }
+ },
+
+ hide: function( speed, easing, callback ) {
+ if ( speed || speed === 0 ) {
+ return this.animate( genFx("hide", 3), speed, easing, callback);
+
+ } else {
+ var elem, display,
+ i = 0,
+ j = this.length;
+
+ for ( ; i < j; i++ ) {
+ elem = this[i];
+ if ( elem.style ) {
+ display = jQuery.css( elem, "display" );
+
+ if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) {
+ jQuery._data( elem, "olddisplay", display );
+ }
+ }
+ }
+
+ // Set the display of the elements in a second loop
+ // to avoid the constant reflow
+ for ( i = 0; i < j; i++ ) {
+ if ( this[i].style ) {
+ this[i].style.display = "none";
+ }
+ }
+
+ return this;
+ }
+ },
+
+ // Save the old toggle function
+ _toggle: jQuery.fn.toggle,
+
+ toggle: function( fn, fn2, callback ) {
+ var bool = typeof fn === "boolean";
+
+ if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
+ this._toggle.apply( this, arguments );
+
+ } else if ( fn == null || bool ) {
+ this.each(function() {
+ var state = bool ? fn : jQuery(this).is(":hidden");
+ jQuery(this)[ state ? "show" : "hide" ]();
+ });
+
+ } else {
+ this.animate(genFx("toggle", 3), fn, fn2, callback);
+ }
+
+ return this;
+ },
+
+ fadeTo: function( speed, to, easing, callback ) {
+ return this.filter(":hidden").css("opacity", 0).show().end()
+ .animate({opacity: to}, speed, easing, callback);
+ },
+
+ animate: function( prop, speed, easing, callback ) {
+ var optall = jQuery.speed( speed, easing, callback );
+
+ if ( jQuery.isEmptyObject( prop ) ) {
+ return this.each( optall.complete, [ false ] );
+ }
+
+ // Do not change referenced properties as per-property easing will be lost
+ prop = jQuery.extend( {}, prop );
+
+ function doAnimation() {
+ // XXX 'this' does not always have a nodeName when running the
+ // test suite
+
+ if ( optall.queue === false ) {
+ jQuery._mark( this );
+ }
+
+ var opt = jQuery.extend( {}, optall ),
+ isElement = this.nodeType === 1,
+ hidden = isElement && jQuery(this).is(":hidden"),
+ name, val, p, e,
+ parts, start, end, unit,
+ method;
+
+ // will store per property easing and be used to determine when an animation is complete
+ opt.animatedProperties = {};
+
+ for ( p in prop ) {
+
+ // property name normalization
+ name = jQuery.camelCase( p );
+ if ( p !== name ) {
+ prop[ name ] = prop[ p ];
+ delete prop[ p ];
+ }
+
+ val = prop[ name ];
+
+ // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
+ if ( jQuery.isArray( val ) ) {
+ opt.animatedProperties[ name ] = val[ 1 ];
+ val = prop[ name ] = val[ 0 ];
+ } else {
+ opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
+ }
+
+ if ( val === "hide" && hidden || val === "show" && !hidden ) {
+ return opt.complete.call( this );
+ }
+
+ if ( isElement && ( name === "height" || name === "width" ) ) {
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE does not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
+
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height animated
+ if ( jQuery.css( this, "display" ) === "inline" &&
+ jQuery.css( this, "float" ) === "none" ) {
+
+ // inline-level elements accept inline-block;
+ // block-level elements need to be inline with layout
+ if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) {
+ this.style.display = "inline-block";
+
+ } else {
+ this.style.zoom = 1;
+ }
+ }
+ }
+ }
+
+ if ( opt.overflow != null ) {
+ this.style.overflow = "hidden";
+ }
+
+ for ( p in prop ) {
+ e = new jQuery.fx( this, opt, p );
+ val = prop[ p ];
+
+ if ( rfxtypes.test( val ) ) {
+
+ // Tracks whether to show or hide based on private
+ // data attached to the element
+ method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 );
+ if ( method ) {
+ jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
+ e[ method ]();
+ } else {
+ e[ val ]();
+ }
+
+ } else {
+ parts = rfxnum.exec( val );
+ start = e.cur();
+
+ if ( parts ) {
+ end = parseFloat( parts[2] );
+ unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
+
+ // We need to compute starting value
+ if ( unit !== "px" ) {
+ jQuery.style( this, p, (end || 1) + unit);
+ start = ( (end || 1) / e.cur() ) * start;
+ jQuery.style( this, p, start + unit);
+ }
+
+ // If a +=/-= token was provided, we're doing a relative animation
+ if ( parts[1] ) {
+ end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
+ }
+
+ e.custom( start, end, unit );
+
+ } else {
+ e.custom( start, val, "" );
+ }
+ }
+ }
+
+ // For JS strict compliance
+ return true;
+ }
+
+ return optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+
+ stop: function( type, clearQueue, gotoEnd ) {
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each(function() {
+ var index,
+ hadTimers = false,
+ timers = jQuery.timers,
+ data = jQuery._data( this );
+
+ // clear marker counters if we know they won't be
+ if ( !gotoEnd ) {
+ jQuery._unmark( true, this );
+ }
+
+ function stopQueue( elem, data, index ) {
+ var hooks = data[ index ];
+ jQuery.removeData( elem, index, true );
+ hooks.stop( gotoEnd );
+ }
+
+ if ( type == null ) {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && index.indexOf(".run") === index.length - 4 ) {
+ stopQueue( this, data, index );
+ }
+ }
+ } else if ( data[ index = type + ".run" ] && data[ index ].stop ){
+ stopQueue( this, data, index );
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+ if ( gotoEnd ) {
+
+ // force the next step to be the last
+ timers[ index ]( true );
+ } else {
+ timers[ index ].saveState();
+ }
+ hadTimers = true;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // start the next in the queue if the last step wasn't forced
+ // timers currently will call their complete callbacks, which will dequeue
+ // but only if they were gotoEnd
+ if ( !( gotoEnd && hadTimers ) ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ }
+
+});
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ setTimeout( clearFxNow, 0 );
+ return ( fxNow = jQuery.now() );
+}
+
+function clearFxNow() {
+ fxNow = undefined;
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, num ) {
+ var obj = {};
+
+ jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {
+ obj[ this ] = type;
+ });
+
+ return obj;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx( "show", 1 ),
+ slideUp: genFx( "hide", 1 ),
+ slideToggle: genFx( "toggle", 1 ),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+});
+
+jQuery.extend({
+ speed: function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+ // normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function( noUnmark ) {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ } else if ( noUnmark !== false ) {
+ jQuery._unmark( this );
+ }
+ };
+
+ return opt;
+ },
+
+ easing: {
+ linear: function( p, n, firstNum, diff ) {
+ return firstNum + diff * p;
+ },
+ swing: function( p, n, firstNum, diff ) {
+ return ( ( -Math.cos( p*Math.PI ) / 2 ) + 0.5 ) * diff + firstNum;
+ }
+ },
+
+ timers: [],
+
+ fx: function( elem, options, prop ) {
+ this.options = options;
+ this.elem = elem;
+ this.prop = prop;
+
+ options.orig = options.orig || {};
+ }
+
+});
+
+jQuery.fx.prototype = {
+ // Simple function for setting a style value
+ update: function() {
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ ( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );
+ },
+
+ // Get the current size
+ cur: function() {
+ if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {
+ return this.elem[ this.prop ];
+ }
+
+ var parsed,
+ r = jQuery.css( this.elem, this.prop );
+ // Empty strings, null, undefined and "auto" are converted to 0,
+ // complex values such as "rotate(1rad)" are returned as is,
+ // simple values such as "10px" are parsed to Float.
+ return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
+ },
+
+ // Start an animation from one number to another
+ custom: function( from, to, unit ) {
+ var self = this,
+ fx = jQuery.fx;
+
+ this.startTime = fxNow || createFxNow();
+ this.end = to;
+ this.now = this.start = from;
+ this.pos = this.state = 0;
+ this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
+
+ function t( gotoEnd ) {
+ return self.step( gotoEnd );
+ }
+
+ t.queue = this.options.queue;
+ t.elem = this.elem;
+ t.saveState = function() {
+ if ( self.options.hide && jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) {
+ jQuery._data( self.elem, "fxshow" + self.prop, self.start );
+ }
+ };
+
+ if ( t() && jQuery.timers.push(t) && !timerId ) {
+ timerId = setInterval( fx.tick, fx.interval );
+ }
+ },
+
+ // Simple 'show' function
+ show: function() {
+ var dataShow = jQuery._data( this.elem, "fxshow" + this.prop );
+
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );
+ this.options.show = true;
+
+ // Begin the animation
+ // Make sure that we start at a small width/height to avoid any flash of content
+ if ( dataShow !== undefined ) {
+ // This show is picking up where a previous hide or show left off
+ this.custom( this.cur(), dataShow );
+ } else {
+ this.custom( this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur() );
+ }
+
+ // Start by showing the element
+ jQuery( this.elem ).show();
+ },
+
+ // Simple 'hide' function
+ hide: function() {
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[ this.prop ] = jQuery._data( this.elem, "fxshow" + this.prop ) || jQuery.style( this.elem, this.prop );
+ this.options.hide = true;
+
+ // Begin the animation
+ this.custom( this.cur(), 0 );
+ },
+
+ // Each step of an animation
+ step: function( gotoEnd ) {
+ var p, n, complete,
+ t = fxNow || createFxNow(),
+ done = true,
+ elem = this.elem,
+ options = this.options;
+
+ if ( gotoEnd || t >= options.duration + this.startTime ) {
+ this.now = this.end;
+ this.pos = this.state = 1;
+ this.update();
+
+ options.animatedProperties[ this.prop ] = true;
+
+ for ( p in options.animatedProperties ) {
+ if ( options.animatedProperties[ p ] !== true ) {
+ done = false;
+ }
+ }
+
+ if ( done ) {
+ // Reset the overflow
+ if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
+
+ jQuery.each( [ "", "X", "Y" ], function( index, value ) {
+ elem.style[ "overflow" + value ] = options.overflow[ index ];
+ });
+ }
+
+ // Hide the element if the "hide" operation was done
+ if ( options.hide ) {
+ jQuery( elem ).hide();
+ }
+
+ // Reset the properties, if the item has been hidden or shown
+ if ( options.hide || options.show ) {
+ for ( p in options.animatedProperties ) {
+ jQuery.style( elem, p, options.orig[ p ] );
+ jQuery.removeData( elem, "fxshow" + p, true );
+ // Toggle data is no longer needed
+ jQuery.removeData( elem, "toggle" + p, true );
+ }
+ }
+
+ // Execute the complete function
+ // in the event that the complete function throws an exception
+ // we must ensure it won't be called twice. #5684
+
+ complete = options.complete;
+ if ( complete ) {
+
+ options.complete = false;
+ complete.call( elem );
+ }
+ }
+
+ return false;
+
+ } else {
+ // classical easing cannot be used with an Infinity duration
+ if ( options.duration == Infinity ) {
+ this.now = t;
+ } else {
+ n = t - this.startTime;
+ this.state = n / options.duration;
+
+ // Perform the easing function, defaults to swing
+ this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );
+ this.now = this.start + ( (this.end - this.start) * this.pos );
+ }
+ // Perform the next step of the animation
+ this.update();
+ }
+
+ return true;
+ }
+};
+
+jQuery.extend( jQuery.fx, {
+ tick: function() {
+ var timer,
+ timers = jQuery.timers,
+ i = 0;
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ },
+
+ interval: 13,
+
+ stop: function() {
+ clearInterval( timerId );
+ timerId = null;
+ },
+
+ speeds: {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+ },
+
+ step: {
+ opacity: function( fx ) {
+ jQuery.style( fx.elem, "opacity", fx.now );
+ },
+
+ _default: function( fx ) {
+ if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
+ fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+ } else {
+ fx.elem[ fx.prop ] = fx.now;
+ }
+ }
+ }
+});
+
+// Adds width/height step functions
+// Do not set anything below 0
+jQuery.each([ "width", "height" ], function( i, prop ) {
+ jQuery.fx.step[ prop ] = function( fx ) {
+ jQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );
+ };
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+ };
+}
+
+// Try to restore the default display value of an element
+function defaultDisplay( nodeName ) {
+
+ if ( !elemdisplay[ nodeName ] ) {
+
+ var body = document.body,
+ elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
+ display = elem.css( "display" );
+ elem.remove();
+
+ // If the simple way fails,
+ // get element's real default display by attaching it to a temp iframe
+ if ( display === "none" || display === "" ) {
+ // No iframe to use yet, so create it
+ if ( !iframe ) {
+ iframe = document.createElement( "iframe" );
+ iframe.frameBorder = iframe.width = iframe.height = 0;
+ }
+
+ body.appendChild( iframe );
+
+ // Create a cacheable copy of the iframe document on first call.
+ // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
+ // document to it; WebKit & Firefox won't allow reusing the iframe document.
+ if ( !iframeDoc || !iframe.createElement ) {
+ iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
+ iframeDoc.write( ( document.compatMode === "CSS1Compat" ? "<!doctype html>" : "" ) + "<html><body>" );
+ iframeDoc.close();
+ }
+
+ elem = iframeDoc.createElement( nodeName );
+
+ iframeDoc.body.appendChild( elem );
+
+ display = jQuery.css( elem, "display" );
+ body.removeChild( iframe );
+ }
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
+ }
+
+ return elemdisplay[ nodeName ];
+}
+
+
+
+
+var rtable = /^t(?:able|d|h)$/i,
+ rroot = /^(?:body|html)$/i;
+
+if ( "getBoundingClientRect" in document.documentElement ) {
+ jQuery.fn.offset = function( options ) {
+ var elem = this[0], box;
+
+ if ( options ) {
+ return this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ if ( !elem || !elem.ownerDocument ) {
+ return null;
+ }
+
+ if ( elem === elem.ownerDocument.body ) {
+ return jQuery.offset.bodyOffset( elem );
+ }
+
+ try {
+ box = elem.getBoundingClientRect();
+ } catch(e) {}
+
+ var doc = elem.ownerDocument,
+ docElem = doc.documentElement;
+
+ // Make sure we're not dealing with a disconnected DOM node
+ if ( !box || !jQuery.contains( docElem, elem ) ) {
+ return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
+ }
+
+ var body = doc.body,
+ win = getWindow(doc),
+ clientTop = docElem.clientTop || body.clientTop || 0,
+ clientLeft = docElem.clientLeft || body.clientLeft || 0,
+ scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop,
+ scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
+ top = box.top + scrollTop - clientTop,
+ left = box.left + scrollLeft - clientLeft;
+
+ return { top: top, left: left };
+ };
+
+} else {
+ jQuery.fn.offset = function( options ) {
+ var elem = this[0];
+
+ if ( options ) {
+ return this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ if ( !elem || !elem.ownerDocument ) {
+ return null;
+ }
+
+ if ( elem === elem.ownerDocument.body ) {
+ return jQuery.offset.bodyOffset( elem );
+ }
+
+ var computedStyle,
+ offsetParent = elem.offsetParent,
+ prevOffsetParent = elem,
+ doc = elem.ownerDocument,
+ docElem = doc.documentElement,
+ body = doc.body,
+ defaultView = doc.defaultView,
+ prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
+ top = elem.offsetTop,
+ left = elem.offsetLeft;
+
+ while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+ if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
+ break;
+ }
+
+ computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
+ top -= elem.scrollTop;
+ left -= elem.scrollLeft;
+
+ if ( elem === offsetParent ) {
+ top += elem.offsetTop;
+ left += elem.offsetLeft;
+
+ if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+ }
+
+ prevOffsetParent = offsetParent;
+ offsetParent = elem.offsetParent;
+ }
+
+ if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+ }
+
+ prevComputedStyle = computedStyle;
+ }
+
+ if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
+ top += body.offsetTop;
+ left += body.offsetLeft;
+ }
+
+ if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
+ top += Math.max( docElem.scrollTop, body.scrollTop );
+ left += Math.max( docElem.scrollLeft, body.scrollLeft );
+ }
+
+ return { top: top, left: left };
+ };
+}
+
+jQuery.offset = {
+
+ bodyOffset: function( body ) {
+ var top = body.offsetTop,
+ left = body.offsetLeft;
+
+ if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
+ top += parseFloat( jQuery.css(body, "marginTop") ) || 0;
+ left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
+ }
+
+ return { top: top, left: left };
+ },
+
+ setOffset: function( elem, options, i ) {
+ var position = jQuery.css( elem, "position" );
+
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ var curElem = jQuery( elem ),
+ curOffset = curElem.offset(),
+ curCSSTop = jQuery.css( elem, "top" ),
+ curCSSLeft = jQuery.css( elem, "left" ),
+ calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
+ props = {}, curPosition = {}, curTop, curLeft;
+
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+
+jQuery.fn.extend({
+
+ position: function() {
+ if ( !this[0] ) {
+ return null;
+ }
+
+ var elem = this[0],
+
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent(),
+
+ // Get correct offsets
+ offset = this.offset(),
+ parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+ // Subtract element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
+ offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
+
+ // Add offsetParent borders
+ parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
+ parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
+
+ // Subtract the two offsets
+ return {
+ top: offset.top - parentOffset.top,
+ left: offset.left - parentOffset.left
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || document.body;
+ while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent;
+ });
+ }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ["Left", "Top"], function( i, name ) {
+ var method = "scroll" + name;
+
+ jQuery.fn[ method ] = function( val ) {
+ var elem, win;
+
+ if ( val === undefined ) {
+ elem = this[ 0 ];
+
+ if ( !elem ) {
+ return null;
+ }
+
+ win = getWindow( elem );
+
+ // Return the scroll offset
+ return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
+ jQuery.support.boxModel && win.document.documentElement[ method ] ||
+ win.document.body[ method ] :
+ elem[ method ];
+ }
+
+ // Set the scroll offset
+ return this.each(function() {
+ win = getWindow( this );
+
+ if ( win ) {
+ win.scrollTo(
+ !i ? val : jQuery( win ).scrollLeft(),
+ i ? val : jQuery( win ).scrollTop()
+ );
+
+ } else {
+ this[ method ] = val;
+ }
+ });
+ };
+});
+
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
+
+
+
+
+// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function( i, name ) {
+
+ var type = name.toLowerCase();
+
+ // innerHeight and innerWidth
+ jQuery.fn[ "inner" + name ] = function() {
+ var elem = this[0];
+ return elem ?
+ elem.style ?
+ parseFloat( jQuery.css( elem, type, "padding" ) ) :
+ this[ type ]() :
+ null;
+ };
+
+ // outerHeight and outerWidth
+ jQuery.fn[ "outer" + name ] = function( margin ) {
+ var elem = this[0];
+ return elem ?
+ elem.style ?
+ parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
+ this[ type ]() :
+ null;
+ };
+
+ jQuery.fn[ type ] = function( size ) {
+ // Get window width or height
+ var elem = this[0];
+ if ( !elem ) {
+ return size == null ? null : this;
+ }
+
+ if ( jQuery.isFunction( size ) ) {
+ return this.each(function( i ) {
+ var self = jQuery( this );
+ self[ type ]( size.call( this, i, self[ type ]() ) );
+ });
+ }
+
+ if ( jQuery.isWindow( elem ) ) {
+ // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+ // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
+ var docElemProp = elem.document.documentElement[ "client" + name ],
+ body = elem.document.body;
+ return elem.document.compatMode === "CSS1Compat" && docElemProp ||
+ body && body[ "client" + name ] || docElemProp;
+
+ // Get document width or height
+ } else if ( elem.nodeType === 9 ) {
+ // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+ return Math.max(
+ elem.documentElement["client" + name],
+ elem.body["scroll" + name], elem.documentElement["scroll" + name],
+ elem.body["offset" + name], elem.documentElement["offset" + name]
+ );
+
+ // Get or set width or height on the element
+ } else if ( size === undefined ) {
+ var orig = jQuery.css( elem, type ),
+ ret = parseFloat( orig );
+
+ return jQuery.isNumeric( ret ) ? ret : orig;
+
+ // Set the width or height on the element (default to pixels if value is unitless)
+ } else {
+ return this.css( type, typeof size === "string" ? size : size + "px" );
+ }
+ };
+
+});
+
+
+
+
+// Expose jQuery to the global object
+window.jQuery = window.$ = jQuery;
+
+// Expose jQuery as an AMD module, but only for AMD loaders that
+// understand the issues with loading multiple versions of jQuery
+// in a page that all might call define(). The loader will indicate
+// they have special allowances for multiple jQuery versions by
+// specifying define.amd.jQuery = true. Register as a named module,
+// since jQuery can be concatenated with other files that may use define,
+// but not use a proper concatenation script that understands anonymous
+// AMD modules. A named AMD is safest and most robust way to register.
+// Lowercase jquery is used because AMD module names are derived from
+// file names, and jQuery is normally delivered in a lowercase file name.
+// Do this after creating the global so that if an AMD module wants to call
+// noConflict to hide this version of jQuery, it will work.
+if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
+ define( "jquery", [], function () { return jQuery; } );
+}
+
+
+
+})( window );
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/js/resource_tree.js b/modules/enterprise/gui/rest-war/src/main/webapp/js/resource_tree.js
index b8f570b..a43eee5 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/js/resource_tree.js
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/js/resource_tree.js
@@ -17,8 +17,7 @@ var r = 960 / 2;
// d3.json("/rest/1/resource/10702/hierarchy.json", function(json) {
d3.json("/rest/1/resource/" + resourceId + "/hierarchy.json", function(json) {
- var inner = json.resourceWithChildren;
- var nodes = tree.nodes(inner);
+ var nodes = tree.nodes(json);
var link = vis.selectAll("path.link")
.data(tree.links(nodes))
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/js/rhq.js b/modules/enterprise/gui/rest-war/src/main/webapp/js/rhq.js
new file mode 100644
index 0000000..0f1c5e6
--- /dev/null
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/js/rhq.js
@@ -0,0 +1,120 @@
+var rhq = {
+
+dashboard : function() {
+ // get all platforms
+ $.get('/rest/1/resource/platforms', function(data) {
+
+ var table = $("#table");
+ for (var i = 0; i < data.length ; i++ ) {
+ var resource = data[i];
+
+ var rowId = "tr" + i ;
+ table.append('<tr id="'+ rowId + '">');
+
+ // Now get the schedules for this resource
+ var resId = resource.resourceId;
+ console.log(resId);
+
+ $.getJSON("/rest/1/resource/"+resId+"/schedules.json?type=metric&enabledOnly=true", function (json2) {
+
+ var tr = $("#" + rowId);
+ for ( var n = 0 ; n < json2.length ; n ++ ) {
+ var tdid = "td_" + i + "_" + n;
+ var schedule = json2[n];
+ var td = tr.append('<td id="'+tdid+'">');
+ $("#"+tdid).html(schedule.displayName + " (" + schedule.scheduleId + ')<br/><div id="d' + tdid +'"/>');
+ rhq.whisker(schedule.scheduleId,tdid,180,90);
+ }
+ })
+ }
+ })
+ },
+whisker: function(scheduleId,divId,w,h) {
+
+ d3.json(
+ '/rest/1/metric/data/'+scheduleId+'.json?hideEmpty=true',
+ function (jsondata) {
+// console.log(scheduleId +", "+ divId);
+ var svg = d3.select("body").select("#"+divId);
+ svg=svg.append("svg:svg")
+ .attr("width", w)
+ .attr("height", h);
+
+ var points = jsondata.dataPoints;
+ var minVal = jsondata.min;
+ var maxVal = jsondata.max;
+ var avgVal = jsondata.avg;
+ var minTs = jsondata.minTimeStamp;
+ var maxTs = jsondata.maxTimeStamp;
+
+ var minTsD = new Date(minTs);
+ var maxTsD = new Date(maxTs);
+
+ // X axis goes from lowest to highest timestamp
+ var x = d3.time.scale().domain([minTsD,maxTsD]).range([0,w]);
+ // Y axis goes from lowest to highest value
+ var y = d3.scale.linear().domain([minVal, maxVal]).rangeRound([0,h]);
+
+
+ // Line for the average
+ var avgLine = svg.append("svg:line")
+ .attr("x1", x(new Date(minTs)))
+ .attr("y1", h - y(avgVal))
+ .attr("x2", x(new Date(maxTs)))
+ .attr("y2", h - y(avgVal))
+ .attr("stroke", "lightgrey")
+ .attr("stroke-dasharray", "2,4");
+
+ // TODO if present add lines for baselines
+
+ // data() loops over all entries in 'points' above for the remaining statements
+ var bars = svg.selectAll("bars").data(points);
+
+ var currX = function(d) {
+ return x(new Date(d.timeStamp))
+ };
+
+ var group = bars.enter().append("svg:g");
+
+ var line = group.append("svg:line")
+ .attr("x1", currX)
+ .attr("x2", currX)
+ .attr("y1", function(d) {
+ return h - y(d.low)
+ })
+ .attr("y2", function(d) {
+ return h - y(d.high)
+ })
+ .attr("stroke", "lightblue");
+
+ var circleLow = group.append("svg:circle")
+ .attr("cx", currX)
+ .attr("cy", function(d) {
+ return h - y(d.low)
+ })
+ .attr("r", 1)
+ .attr("stroke", "green")
+ .attr("fill", "lightgreen");
+
+ var circleHigh = group.append("svg:circle")
+ .attr("cx", currX)
+ .attr("cy", function(d) {
+ return h - y(d.high)
+ })
+ .attr("r", 1)
+ .attr("stroke", "green")
+ .attr("fill", "lightblue");
+
+ var circleVal = group.append("svg:circle")
+ .attr("cx", currX)
+ .attr("cy", function(d) {
+ return h - y(d.value)
+ })
+ .attr("r", 1.5)
+ .attr("stroke", "blue")
+ .attr("fill", "lightpink");
+
+ });
+} // whisker
+
+};//var rhq
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/js/whisker.js b/modules/enterprise/gui/rest-war/src/main/webapp/js/whisker.js
deleted file mode 100644
index 6f23669..0000000
--- a/modules/enterprise/gui/rest-war/src/main/webapp/js/whisker.js
+++ /dev/null
@@ -1,92 +0,0 @@
-function whisker(scheduleId,divId) {
-// Width and height of the chart to print
- var w = 240,
- h = 125;
-
-// div#one is the div with the id 'one' ( <div id="one"/>)
- var svg = d3.select("body").select("div#"+divId).append("svg:svg")
- .attr("width", w)
- .attr("height", h);
-// .append("svg:g");
-// .attr("transform", "translate(" + p[3] + "," + (h - p[2]) + ")");
- d3.json(
- '/rest/1/metric/data/'+scheduleId+'.json?hideEmpty=true',
- function (jsondata) {
-
- var points = jsondata.dataPoints;
- var minVal = jsondata.min;
- var maxVal = jsondata.max;
- var avgVal = jsondata.avg;
- var minTs = jsondata.minTimeStamp;
- var maxTs = jsondata.maxTimeStamp;
-
- var minTsD = new Date(minTs);
- var maxTsD = new Date(maxTs);
- console.log(minTs, minTsD, maxTs, maxTsD);
-
- // X axis goes from lowest to highest timestamp
- var x = d3.time.scale().domain([minTsD,maxTsD]).range([0,w]);
- // Y axis goes from lowest to highest value
- var y = d3.scale.linear().domain([minVal, maxVal]).rangeRound([0,h]);
-
-
- // Line for the average
- var avgLine = svg.append("svg:line")
- .attr("x1", x(new Date(minTs)))
- .attr("y1", h - y(avgVal))
- .attr("x2", x(new Date(maxTs)))
- .attr("y2", h - y(avgVal))
- .attr("stroke", "lightgrey")
- .attr("stroke-dasharray", "2,4");
-
- // TODO if present add lines for baselines
-
- // data() loops over all entries in 'points' above for the remaining statements
- var bars = svg.selectAll("bars").data(points);
-
- var currX = function(d) {
- return x(new Date(d.timeStamp))
- };
-
- var group = bars.enter().append("svg:g");
-
- var line = group.append("svg:line")
- .attr("x1", currX)
- .attr("x2", currX)
- .attr("y1", function(d) {
- return h - y(d.low)
- })
- .attr("y2", function(d) {
- return h - y(d.high)
- })
- .attr("stroke", "lightblue");
-
- var circleLow = group.append("svg:circle")
- .attr("cx", currX)
- .attr("cy", function(d) {
- return h - y(d.low)
- })
- .attr("r", 1)
- .attr("stroke", "green")
- .attr("fill", "lightgreen");
-
- var circleHigh = group.append("svg:circle")
- .attr("cx", currX)
- .attr("cy", function(d) {
- return h - y(d.high)
- })
- .attr("r", 1)
- .attr("stroke", "green")
- .attr("fill", "lightblue");
-
- var circleVal = group.append("svg:circle")
- .attr("cx", currX)
- .attr("cy", function(d) {
- return h - y(d.value)
- })
- .attr("r", 1.5)
- .attr("stroke", "blue")
- .attr("fill", "lightpink");
-
- });
-}
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/stacked1.html b/modules/enterprise/gui/rest-war/src/main/webapp/stacked1.html
index 549a3ff..9413b70 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/stacked1.html
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/stacked1.html
@@ -5,6 +5,7 @@
<script type="text/javascript" src="js/d3.js"></script>
<script type="text/javascript" src="js/d3.layout.js"></script>
<script type="text/javascript" src="js/d3.time.js"></script>
+ <script type="text/javascript" src="js/jquery.js"></script>
<style type="text/css">
svg {
@@ -18,33 +19,50 @@ svg {
</style>
</head>
<body>
- <h2>Stacked metrics (schedule 10003)</h2>
- Upper edge of green is low, upper edge of blue is the value and upper edge of pink is high.
- <br/>
- <script type="text/javascript">
-
-var w = 960,
- h = 500,
- p = [20, 50, 30, 20],
- x = d3.scale.ordinal().rangeRoundBands([0, w - p[1] - p[3]]),
- y = d3.scale.linear().range([0, h - p[0] - p[2]]),
- z = d3.scale.ordinal().range(["lightgreen", "darkblue", "lightpink"]),
- format = d3.time.format("%H:%M");
-
-var svg = d3.select("body").append("svg:svg")
- .attr("width", w)
- .attr("height", h)
- .append("svg:g")
- .attr("transform", "translate(" + p[3] + "," + (h - p[2]) + ")");
-
-
-d3.json(
- '/rest/1/metric/data/10003.json',
- function (jsondata) {
-
- var points = jsondata.metricAggregate.dataPoints;
- var min = jsondata.metricAggregate.min;
- var max = jsondata.metricAggregate.max;
+
+
+<h1 id="resId">Resource</h1>
+Upper edge of green is low, upper edge of blue is the value and upper edge of pink is high.
+<br/>
+<h2 id="header">Schedule</h2>
+ <script type="text/javascript">
+
+// Get the platforms and then the first one
+$.getJSON('/rest/1/resource/platforms.json', function (json) {
+ var res = json[0];
+ var rid = res.resourceId;
+ $("#resId").text("Resource " + rid + " (" + res.resourceName + ")");
+
+ // Now get the metrical schedules of the platform
+ $.getJSON("/rest/1/resource/"+rid+"/schedules.json?type=metric", function (json2) {
+
+ // Take the first
+ var schId = json2[0].scheduleId;
+ $("#header").text("Schedule " + schId + " (" + json2[0].scheduleName + ")");
+
+ // And call d3 graphing on it
+ d3.json(
+ '/rest/1/metric/data/'+schId+'.json',
+ function (jsondata) {
+
+ var w = 960,
+ h = 500,
+ p = [20, 50, 30, 20],
+ x = d3.scale.ordinal().rangeRoundBands([0, w - p[1] - p[3]]),
+ y = d3.scale.linear().range([0, h - p[0] - p[2]]),
+ z = d3.scale.ordinal().range(["lightgreen", "darkblue", "lightpink"]),
+ format = d3.time.format("%H:%M");
+
+ var svg = d3.select("body").append("svg:svg")
+ .attr("width", w)
+ .attr("height", h)
+ .append("svg:g")
+ .attr("transform", "translate(" + p[3] + "," + (h - p[2]) + ")");
+
+
+ var points = jsondata.dataPoints;
+ var min = jsondata.min;
+ var max = jsondata.max;
var metrics = d3.layout.stack()(["low","value","high"].map(function (point) {
return points.map(function (d) {
@@ -119,6 +137,8 @@ d3.json(
.attr("dy", ".35em")
.text(d3.format(",d"));
});
+ });
+});
</script>
</body>
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/stacked2.html b/modules/enterprise/gui/rest-war/src/main/webapp/stacked2.html
index d3f8b4d..e622f2c 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/stacked2.html
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/stacked2.html
@@ -5,6 +5,7 @@
<script type="text/javascript" src="js/d3.js"></script>
<script type="text/javascript" src="js/d3.layout.js"></script>
<script type="text/javascript" src="js/d3.time.js"></script>
+ <script type="text/javascript" src="js/jquery.js"></script>
<style type="text/css">
svg {
@@ -18,9 +19,10 @@ svg {
</style>
</head>
<body>
- <h2>Stacked metrics (schedule 10003)</h2>
+ <h1 id="resId">Resource</h1>
Upper edge of green is low, upper edge of blue is the value and upper edge of pink is high.
<br/>
+ <h2 id="header">Schedule</h2>
<script type="text/javascript">
var w = 960,
@@ -37,89 +39,101 @@ var svg = d3.select("body").append("svg:svg")
.append("svg:g")
.attr("transform", "translate(" + p[3] + "," + (h - p[2]) + ")");
-
-d3.json(
- '/rest/1/metric/data/10003.json',
- function (jsondata) {
-
- var points = jsondata.metricAggregate.dataPoints;
- var min = jsondata.metricAggregate.min;
- var max = jsondata.metricAggregate.max;
-
- var metrics = d3.layout.stack()(["low","value","high"].map(function (point) {
- return points.map(function (d) {
- var tmp;
- if (point == "low")
- tmp = d["low"] - min;
- if (point == "value") {
- var va = d["value"];
- var lo = d["low"];
- tmp = va-lo;
- }
- if (point == "high")
- tmp = (d["high"]-d["value"]);
-
- if (tmp < 0 ) {
-// console.log(point);
- tmp=0;
- }
-
- return {x: new Date(d.timeStamp), y: tmp};
- });
- }));
-
-// console.log(metrics);
-
-
- // Compute the x-domain (by date) and y-domain (by top).
- x.domain(metrics[0].map(function(d) { return d.x; }));
- y.domain([0, d3.max(metrics[metrics.length - 1], function(d) { return d.y0 + d.y; })]);
-
- // Add a group for each cause.
- var cause = svg.selectAll("g.cause")
- .data(metrics)
- .enter().append("svg:g")
- .attr("class", "cause")
- .style("fill", function(d, i) { return z(i); })
- .style("stroke", function(d, i) { return d3.rgb(z(i)).darker(); });
-
- // Add a rect for each date.
- var rect = cause.selectAll("rect")
- .data(Object)
- .enter().append("svg:rect")
- .attr("x", function(d) { return x(d.x); })
- .attr("y", function(d) { return -y(d.y0) - y(d.y); })
- .attr("height", function(d) { return 5; }) // <<<--- HERE
- .attr("width", x.rangeBand());
-
- // Add a label per date.
- var label = svg.selectAll("text")
- .data(x.domain())
- .enter().append("svg:text")
- .attr("x", function(d) { return x(d) + x.rangeBand() / 2; })
- .attr("y", 6)
- .attr("text-anchor", "middle")
- .attr("dy", ".71em")
- .text(format);
-
- // Add y-axis rules.
- var rule = svg.selectAll("g.rule")
- .data(y.ticks(5))
- .enter().append("svg:g")
- .attr("class", "rule")
- .attr("transform", function(d) { return "translate(0," + -y(d) + ")"; });
-
- rule.append("svg:line")
- .attr("x2", w - p[1] - p[3])
- .style("stroke", function(d) { return d ? "#fff" : "#000"; })
- .style("stroke-opacity", function(d) { return d ? .7 : null; });
-
- rule.append("svg:text")
- .attr("x", w - p[1] - p[3] + 6)
- .attr("dy", ".35em")
- .text(d3.format(",d"));
-});
-
+// Get the platforms and then the first one
+$.getJSON('/rest/1/resource/platforms.json', function (json) {
+ var res = json[0];
+ var rid = res.resourceId;
+ $("#resId").text("Resource " + rid + " (" + res.resourceName + ")");
+
+ // Now get the metrical schedules of the platform
+ $.getJSON("/rest/1/resource/"+rid+"/schedules.json?type=metric", function (json2) {
+
+ // Take the first
+ var schId = json2[0].scheduleId;
+ $("#header").text("Schedule " + schId + " (" + json2[0].scheduleName + ")");
+
+ // And call d3 graphing on it
+ d3.json(
+ '/rest/1/metric/data/'+schId+'.json',
+ function (jsondata) {
+
+ var points = jsondata.dataPoints;
+ var min = jsondata.min;
+ var max = jsondata.max;
+
+ var metrics = d3.layout.stack()(["low","value","high"].map(function (point) {
+ return points.map(function (d) {
+ var tmp;
+ if (point == "low")
+ tmp = d["low"] - min;
+ if (point == "value") {
+ var va = d["value"];
+ var lo = d["low"];
+ tmp = va-lo;
+ }
+ if (point == "high")
+ tmp = (d["high"]-d["value"]);
+
+ if (tmp < 0 ) {
+ tmp=0;
+ }
+
+ return {x: new Date(d.timeStamp), y: tmp};
+ });
+ }));
+
+
+ // Compute the x-domain (by date) and y-domain (by top).
+ x.domain(metrics[0].map(function(d) { return d.x; }));
+ y.domain([0, d3.max(metrics[metrics.length - 1], function(d) { return d.y0 + d.y; })]);
+
+ // Add a group for each cause.
+ var cause = svg.selectAll("g.cause")
+ .data(metrics)
+ .enter().append("svg:g")
+ .attr("class", "cause")
+ .style("fill", function(d, i) { return z(i); })
+ .style("stroke", function(d, i) { return d3.rgb(z(i)).darker(); });
+
+ // Add a rect for each date.
+ var rect = cause.selectAll("rect")
+ .data(Object)
+ .enter().append("svg:rect")
+ .attr("x", function(d) { return x(d.x); })
+ .attr("y", function(d) { return -y(d.y0) - y(d.y); })
+ .attr("height", function(d) { return 5; }) // <<<--- HERE
+ .attr("width", x.rangeBand());
+
+ // Add a label per date.
+ var label = svg.selectAll("text")
+ .data(x.domain())
+ .enter().append("svg:text")
+ .attr("x", function(d) { return x(d) + x.rangeBand() / 2; })
+ .attr("y", 6)
+ .attr("text-anchor", "middle")
+ .attr("dy", ".71em")
+ .text(format);
+
+ // Add y-axis rules.
+ var rule = svg.selectAll("g.rule")
+ .data(y.ticks(5))
+ .enter().append("svg:g")
+ .attr("class", "rule")
+ .attr("transform", function(d) { return "translate(0," + -y(d) + ")"; });
+
+ rule.append("svg:line")
+ .attr("x2", w - p[1] - p[3])
+ .style("stroke", function(d) { return d ? "#fff" : "#000"; })
+ .style("stroke-opacity", function(d) { return d ? .7 : null; });
+
+ rule.append("svg:text")
+ .attr("x", w - p[1] - p[3] + 6)
+ .attr("dy", ".35em")
+ .text(d3.format(",d"));
+ });
+
+ })
+})
</script>
</body>
</html>
\ No newline at end of file
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/whisker.html b/modules/enterprise/gui/rest-war/src/main/webapp/whisker.html
index dc37e35..2b03349 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/whisker.html
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/whisker.html
@@ -5,6 +5,8 @@
<script type="text/javascript" src="js/d3.js"></script>
<script type="text/javascript" src="js/d3.layout.js"></script>
<script type="text/javascript" src="js/d3.time.js"></script>
+ <script type="text/javascript" src="js/jquery.js"></script>
+ <script type="text/javascript" src="js/rhq.js"></script>
<style type="text/css">
svg {
@@ -18,91 +20,33 @@ svg {
</style>
</head>
<body>
- <h2> (schedule 10003)</h2>
+ <h1 id="resId">Resource</h1>
+ <h2 id="header">Schedule</h2>
- <br/>
- <div id="one"/>
+ <div id="one"></div>
<script type="text/javascript">
// Width and height of the chart to print
var w = 800,
h = 600;
-// div#one is the div with the id 'one' ( <div id="one"/>)
-var svg = d3.select("body").select("div#one").append("svg:svg")
- .attr("width", w)
- .attr("height", h);
-// .append("svg:g");
-// .attr("transform", "translate(" + p[3] + "," + (h - p[2]) + ")");
+// Get the platforms and then the first one
+$.getJSON('/rest/1/resource/platforms.json', function (json) {
+ var res = json[0];
+ var rid = res.resourceId;
+ $("#resId").text("Resource " + rid + " (" + res.resourceName + ")");
+ // Now get the metrical schedules of the platform
+ $.getJSON("/rest/1/resource/"+rid+"/schedules.json?type=metric", function (json2) {
-d3.json(
- '/rest/1/metric/data/10003.json?hideEmpty=true',
- function (jsondata) {
+ // Take the first and render it
+ var schId = json2[0].scheduleId;
+ $("#header").text("Schedule " + schId + " (" + json2[0].scheduleName + ")");
+ rhq.whisker(schId,"one",w,h);
+ })
+})
- var points = jsondata.metricAggregate.dataPoints;
- var minVal = jsondata.metricAggregate.min;
- var maxVal = jsondata.metricAggregate.max;
- var avgVal = jsondata.metricAggregate.avg;
- var minTs = jsondata.metricAggregate.minTimeStamp;
- var maxTs = jsondata.metricAggregate.maxTimeStamp;
- var minTsD = new Date(minTs);
- var maxTsD = new Date(maxTs);
- console.log(minTs, minTsD, maxTs, maxTsD);
-
- // X axis goes from lowest to highest timestamp
- var x = d3.time.scale().domain([minTsD,maxTsD]).range([0,w]);
- // Y axis goes from lowest to highest value
- var y = d3.scale.linear().domain([minVal, maxVal]).rangeRound([0,h]);
-
-// console.log(jsondata.metricAggregate);
-
-
- // Line for the average
- var avgLine = svg.append("svg:line")
- .attr("x1",x(new Date(minTs)))
- .attr("y1",h-y(avgVal))
- .attr("x2",x(new Date(maxTs)))
- .attr("y2",h-y(avgVal))
- .attr("stroke","lighgrey")
- .attr("stroke-dasharray","2,2");
-
- // TODO if present add lines for baselines
-
- // data() loops over all entries in 'points' above for the remaining statements
- var bars = svg.selectAll("bars").data(points);
-
- var currX = function(d) { return x(new Date(d.timeStamp)) };
-
- var circleLow = bars.enter().append("svg:circle")
- .attr("cx",currX)
- .attr("cy",function(d) {return h-y(d.low)})
- .attr("r",2)
- .attr("stroke","lightgreen")
- .attr("fill","lightgreen");
-
- var circleHigh = bars.enter().append("svg:circle")
- .attr("cx",currX)
- .attr("cy",function(d) {return h-y(d.high)})
- .attr("r",2)
- .attr("stroke","lightgreen")
- .attr("fill","lightgreen");
-
- var circleVal = bars.enter().append("svg:circle")
- .attr("cx",currX)
- .attr("cy",function(d) {return h-y(d.value)})
- .attr("r",3)
- .attr("stroke","lightpink")
- .attr("fill","lightpink");
-
- var line = bars.enter().append("svg:line")
- .attr("x1",currX)
- .attr("x2",currX)
- .attr("y1",function(d) {return h-y(d.low)})
- .attr("y2",function(d) {return h-y(d.high)})
- .attr("stroke","blue");
-});
</script>
</body>
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/whisker2.html b/modules/enterprise/gui/rest-war/src/main/webapp/whisker2.html
index d523acd..67340d5 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/whisker2.html
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/whisker2.html
@@ -1,17 +1,18 @@
<!DOCTYPE html>
<html>
<head>
- <title>(free mem, schedule 10003)</title>
+ <title>Dashboard</title>
<script type="text/javascript" src="js/d3.js"></script>
<script type="text/javascript" src="js/d3.layout.js"></script>
<script type="text/javascript" src="js/d3.time.js"></script>
- <script type="text/javascript" src="js/whisker.js"></script>
+ <script type="text/javascript" src="js/jquery.js"></script>
+ <script type="text/javascript" src="js/rhq.js"></script>
<style type="text/css">
svg {
- width: 240px;
- height: 125px;
+ width: 182px;
+ height: 92px;
border: solid 1px #ccc;
font: 10px sans-serif;
shape-rendering: crispEdges;
@@ -20,51 +21,15 @@ svg {
</style>
</head>
<body>
- <h2>Various metrics</h2>
- <table>
- <tr>
- <td>
- Schedule 10003<br/>
- <div id="two">
- <script>whisker(10003,'two')</script>
- </div>
- </td>
- <td>
- Schedule 10004<br/>
- <div id="three">
- <script>whisker(10004,'three')</script>
- </div>
- </td>
-
- <td>
- Schedule 10007<br/>
- <div id="four">
- <script>whisker(10007,'four')</script>
- </div>
- </td>
- </tr>
- <tr>
- <td>
- Schedule 10011<br/>
- <div id="five">
- <script>whisker(10011,'five')</script>
- </div>
- </td>
- <td>
- Schedule 10009<br/>
- <div id="six">
- <script>whisker(10009,'six')</script>
- </div>
- </td>
- <td>
- Schedule 10010<br/>
- <div id="seven">
- <script>whisker(10010,'seven')</script>
- </div>
- </td>
- </tr>
+ <h2>Dashboard</h2>
+<script>
+ $(document).ready(function() {
+ rhq.dashboard();
+ })
+</script>
+ <table id="table">
</table>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 91ed23a..59efeba 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -31,6 +31,8 @@ import java.util.Set;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.GenericEntity;
@@ -192,6 +194,7 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
public Response getSchedules(int resourceId,
String scheduleType,
+ boolean enabledOnly,
@Context Request request,
@Context HttpHeaders headers,
@Context UriInfo uriInfo) {
@@ -200,7 +203,7 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
if (scheduleType.equals("metric"))
scheduleType=DataType.MEASUREMENT.toString().toLowerCase();
- Resource res = resMgr.getResource(caller,resourceId); // Don't fetch(), as this would yield a LazyLoadException
+ Resource res = resMgr.getResource(caller, resourceId); // Don't fetch(), as this would yield a LazyLoadException
Set<MeasurementSchedule> schedules = res.getSchedules();
List<MetricSchedule> ret = new ArrayList<MetricSchedule>(schedules.size());
@@ -212,26 +215,28 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
if ("all".equals(scheduleType) ||
scheduleType.toLowerCase().equals(definition.getDataType().toString().toLowerCase()) ) {
- MetricSchedule ms = new MetricSchedule(schedule.getId(), definition.getName(), definition.getDisplayName(),
- schedule.isEnabled(),schedule.getInterval(), definition.getUnits().toString(),
- definition.getDataType().toString());
- UriBuilder uriBuilder;
- URI uri;
- if (definition.getDataType()== DataType.MEASUREMENT) {
+ if (!enabledOnly || (enabledOnly && schedule.isEnabled() )) {
+ MetricSchedule ms = new MetricSchedule(schedule.getId(), definition.getName(), definition.getDisplayName(),
+ schedule.isEnabled(),schedule.getInterval(), definition.getUnits().toString(),
+ definition.getDataType().toString());
+ UriBuilder uriBuilder;
+ URI uri;
+ if (definition.getDataType()== DataType.MEASUREMENT) {
+ uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/metric/data/{id}");
+ uri = uriBuilder.build(schedule.getId());
+ Link metricLink = new Link("metric",uri.toString());
+ ms.addLink(metricLink);
+ }
+ // create link to the resource
uriBuilder = uriInfo.getBaseUriBuilder();
- uriBuilder.path("/metric/data/{id}");
- uri = uriBuilder.build(schedule.getId());
- Link metricLink = new Link("metric",uri.toString());
- ms.addLink(metricLink);
+ uriBuilder.path("resource/" + schedule.getResource().getId());
+ uri = uriBuilder.build();
+ Link link = new Link("resource",uri.toString());
+ ms.addLink(link);
+
+ ret.add(ms);
}
- // create link to the resource
- uriBuilder = uriInfo.getBaseUriBuilder();
- uriBuilder.path("resource/" + schedule.getResource().getId());
- uri = uriBuilder.build();
- Link link = new Link("resource",uri.toString());
- ms.addLink(link);
-
- ret.add(ms);
}
}
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 08a1905..ab9ea62 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
@@ -87,6 +87,7 @@ public interface ResourceHandlerLocal {
@Cache(isPrivate = true,maxAge = 60)
Response getSchedules(@PathParam("id") int resourceId,
@QueryParam("type") @DefaultValue("all") String scheduleType,
+ @QueryParam("enabledOnly") @DefaultValue("true") boolean enabledOnly,
@Context Request request,
@Context HttpHeaders headers,
@Context UriInfo uriInfo);
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 d426e06..58af399 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
@@ -24,7 +24,7 @@
<script type="text/javascript" src="/rest/js/d3.js"></script>
<script type="text/javascript" src="/rest/js/d3.layout.js"></script>
<script type="text/javascript" src="/rest/js/d3.time.js"></script>
- <script type="text/javascript" src="/rest/js/whisker.js"></script>
+ <script type="text/javascript" src="/rest/js/rhq.js"></script>
<table border=1>
<thead>
<tr>
@@ -44,7 +44,7 @@
<td>Max</td><td>${var.max}</td>
</tr>
<tr>
- <td><a align="top" href="javascript:whisker(${sched?c},'one')">DataPoints</a></td><td>
+ <td><a align="top" href="javascript:rhq.whisker(${sched?c},'one',400,200)">DataPoints</a></td><td>
<table>
<thead>
<tr>
commit ffa3c7f3e181f62107036844dacc4aef413ade80
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Sat Nov 26 19:27:37 2011 +0100
Get system status from the SystemInfoManager
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 0f2a0ed..a6fce0c 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
@@ -18,9 +18,12 @@
*/
package org.rhq.enterprise.server.rest;
+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;
@@ -39,6 +42,7 @@ import org.rhq.enterprise.server.alert.AlertManagerLocal;
import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.rest.domain.Status;
+import org.rhq.enterprise.server.system.SystemInfoManagerLocal;
/**
* Return system status
@@ -50,48 +54,14 @@ public class StatusHandlerBean extends AbstractRestBean implements StatusHandler
@EJB
- MeasurementScheduleManagerLocal scheduleManager;
- @EJB
- ResourceManagerLocal resourceManager;
- @EJB
- AlertManagerLocal alertManager;
- @EJB
- AlertDefinitionManagerLocal alertDefinitionManager;
+ SystemInfoManagerLocal infoMgr;
@Override
public Response getStatus(HttpHeaders httpHeaders) {
+ Map<String,String> statusMap = infoMgr.getSystemInformation (caller);
Status status = new Status();
-
- ResourceCriteria criteria = new ResourceCriteria();
- criteria.addFilterResourceCategories(ResourceCategory.PLATFORM);
- criteria.setRestriction(Criteria.Restriction.COUNT_ONLY);
- PageList<Resource> resList = resourceManager.findResourcesByCriteria(caller,criteria);
- status.setPlatforms(resList.getTotalSize());
- criteria = new ResourceCriteria();
- criteria.addFilterResourceCategories(ResourceCategory.SERVER);
- criteria.setRestriction(Criteria.Restriction.COUNT_ONLY);
- resList = resourceManager.findResourcesByCriteria(caller,criteria);
- status.setServers(resList.getTotalSize());
- criteria = new ResourceCriteria();
- criteria.addFilterResourceCategories(ResourceCategory.SERVICE);
- criteria.setRestriction(Criteria.Restriction.COUNT_ONLY);
- resList = resourceManager.findResourcesByCriteria(caller,criteria);
- status.setServices(resList.getTotalSize());
-
- AlertCriteria alertCriteria = new AlertCriteria();
- alertCriteria.setRestriction(Criteria.Restriction.COUNT_ONLY);
- PageList<Alert> alertList = alertManager.findAlertsByCriteria(caller,alertCriteria);
- status.setAlerts(alertList.getTotalSize());
-
- AlertDefinitionCriteria alertDefinitionCriteria = new AlertDefinitionCriteria();
- alertDefinitionCriteria.setRestriction(Criteria.Restriction.COUNT_ONLY);
- PageList<AlertDefinition> defList = alertDefinitionManager.findAlertDefinitionsByCriteria(caller,alertDefinitionCriteria);
- status.setAlertDefinitions(defList.getTotalSize());
-
- status.setSchedules(-1); // TODO
-
- status.setMetricsMin(scheduleManager.getScheduledMeasurementsPerMinute());
+ status.setValues(statusMap);
MediaType mediaType = httpHeaders.getAcceptableMediaTypes().get(0);
Response.ResponseBuilder builder;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Status.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Status.java
index c0a4e10..dfb64ab 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Status.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Status.java
@@ -18,6 +18,9 @@
*/
package org.rhq.enterprise.server.rest.domain;
+import java.util.HashMap;
+import java.util.Map;
+
import javax.xml.bind.annotation.XmlRootElement;
/**
@@ -27,70 +30,15 @@ import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Status {
- int platforms;
- int servers;
- int services;
- int alerts;
- int alertDefinitions;
- int metricsMin;
- int schedules;
-
+ Map<String,String> values = new HashMap<String, String>();
public Status() {
}
- public int getPlatforms() {
- return platforms;
- }
-
- public void setPlatforms(int platforms) {
- this.platforms = platforms;
- }
-
- public int getServers() {
- return servers;
- }
-
- public void setServers(int servers) {
- this.servers = servers;
- }
-
- public int getServices() {
- return services;
- }
-
- public void setServices(int services) {
- this.services = services;
- }
-
- public int getAlerts() {
- return alerts;
- }
-
- public void setAlerts(int alerts) {
- this.alerts = alerts;
- }
-
- public int getAlertDefinitions() {
- return alertDefinitions;
- }
-
- public void setAlertDefinitions(int alertDefinitions) {
- this.alertDefinitions = alertDefinitions;
- }
-
- public int getMetricsMin() {
- return metricsMin;
- }
-
- public void setMetricsMin(int metricsMin) {
- this.metricsMin = metricsMin;
- }
-
- public int getSchedules() {
- return schedules;
+ public Map<String, String> getValues() {
+ return values;
}
- public void setSchedules(int schedules) {
- this.schedules = schedules;
+ public void setValues(Map<String, String> values) {
+ this.values = values;
}
}
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/status.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/status.ftl
index f4adb30..6569373 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/status.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/status.ftl
@@ -2,7 +2,7 @@
<#--
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2011 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -27,23 +27,10 @@
<td>Name</td><td>Value</td>
</tr>
</thead>
+ <#list var.values?keys as key>
<tr>
- <td>Alert definitions</td><td>${var.alertDefinitions}</td>
- </tr>
- <tr>
- <td>Alerts</td><td>${var.alerts}</td>
- </tr>
- <tr>
- <td>Platforms</td><td>${var.platforms}</td>
- </tr>
- <tr>
- <td>Servers</td><td>${var.servers}</td>
- </tr>
- <tr>
- <td>Services</td><td>${var.services}</td>
- </tr>
- <tr>
- <td>Metrics/min</td><td>${var.metricsMin}</td>
+ <td>${key}</td><td>${var.values[key]}</td>
</tr>
+ </#list>
</table>
</html>
commit 4ab4f01ace074d2d0ed1457175173523988cd5ea
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Sat Nov 26 17:34:07 2011 +0100
Improve history handling and parameter passing.
Add link to self for the history item.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
index 536274a..be39ede 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -1,8 +1,27 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
package org.rhq.enterprise.server.rest;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import javax.ejb.EJB;
@@ -14,6 +33,7 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.HttpHeaders;
@@ -24,6 +44,8 @@ import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.Property;
+import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.configuration.definition.PropertyDefinition;
import org.rhq.core.domain.criteria.OperationHistoryCriteria;
@@ -40,6 +62,7 @@ import org.rhq.enterprise.server.operation.OperationManagerLocal;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.OperationDefinitionRest;
+import org.rhq.enterprise.server.rest.domain.OperationHistoryRest;
import org.rhq.enterprise.server.rest.domain.OperationRest;
/**
@@ -204,7 +227,13 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
// todo check params
// submit
- ResourceOperationSchedule sched = opsManager.scheduleResourceOperation(caller,operation.getResourceId(),operation.getName(),0,0,0,-1,new Configuration(),"TEst");
+
+ Configuration parameters = new Configuration();
+ for (Map.Entry<String,Object> entry : operation.getParams().entrySet()) {
+ parameters.put(new PropertySimple(entry.getKey(),entry.getValue())); // TODO honor more types
+ }
+ ResourceOperationSchedule sched = opsManager.scheduleResourceOperation(caller,operation.getResourceId(),operation.getName(),0,0,0,-1,
+ parameters,"TEst");
JobId jobId = new JobId(sched.getJobName(),sched.getJobGroup());
UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
uriBuilder.path("/operation/history/{id}");
@@ -242,27 +271,45 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
@Override
@GET
@Path("history/{id}")
- public Response outcome(@PathParam("id") String jobName) {
+ public Response outcome(@PathParam("id") String jobName, @Context UriInfo uriInfo) {
-/*
- ResourceOperationSchedule schedule = opsManager.getResourceOperationSchedule(caller,operationHistoryId);
- if (schedule==null)
- throw new StuffNotFoundException("OperationSchedule with id " + operationHistoryId);
-*/
ResourceOperationHistoryCriteria criteria = new ResourceOperationHistoryCriteria();
criteria.addFilterJobId(new JobId(jobName));
- OperationHistory history ;//= opsManager.getOperationHistoryByJobId(caller,jobName);
+ ResourceOperationHistory history ;//= opsManager.getOperationHistoryByJobId(caller,jobName);
List<ResourceOperationHistory> list = opsManager.findResourceOperationHistoriesByCriteria(caller,criteria);
- if (list==null || list.isEmpty())
+ if (list==null || list.isEmpty()) {
+ log.info("No history with id " + new HistoryJobId(jobName) + " found");
throw new StuffNotFoundException("OperationHistory with id " + new HistoryJobId(jobName));
+ }
history = list.get(0);
- String ret = history.getStatus().getDisplayName();
- // TODO get history.results with the help of the property definition
+ String status;
+ if (history.getStatus()==null)
+ status = " - no infomation yet -";
+ else
+ status = history.getStatus().getDisplayName();
+
+ OperationHistoryRest hist = new OperationHistoryRest();
+ hist.setStatus(status);
+ if (history.getErrorMessage()!=null)
+ hist.setErrorMessage(history.getErrorMessage());
+ if (history.getResults()!=null) {
+ Configuration results = history.getResults();
+ for (Property p : results.getProperties()) {
+ hist.getResult().put(p.getName(),p.toString());
+ }
+ }
+
+ UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/operation/history/{id}");
+ URI url = uriBuilder.build(new JobId(jobName));
+ Link self = new Link("self",url.toString());
+ hist.getLinks().add(self);
+
- return Response.ok(ret).build();
+ return Response.ok(hist).build();
}
}
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 1d2a9ed..79c20bb 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
@@ -1,3 +1,21 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
package org.rhq.enterprise.server.rest;
import java.util.List;
@@ -72,5 +90,5 @@ public interface OperationsHandlerLocal {
@GET
@Path("history/{id}")
- public Response outcome(@PathParam("id") String jobName);
+ public Response outcome(@PathParam("id") String jobName, @Context UriInfo uriInfo);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationHistoryRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationHistoryRest.java
new file mode 100644
index 0000000..8249db6
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationHistoryRest.java
@@ -0,0 +1,72 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.server.rest.domain;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * An operations history item
+ * @author Heiko W. Rupp
+ */
+@XmlRootElement
+public class OperationHistoryRest {
+
+ String status;
+ String errorMessage;
+
+ Map<String,Object> result = new HashMap<String, Object>();
+ List<Link> links = new ArrayList<Link>();
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public Map<String, Object> getResult() {
+ return result;
+ }
+
+ public void setResult(Map<String, Object> result) {
+ this.result = result;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+
+ public List<Link> getLinks() {
+ return links;
+ }
+
+ public void setLinks(List<Link> links) {
+ this.links = links;
+ }
+}
commit 7eed6555906199687c5f9f5d6c8cf50c15970d0d
Merge: 096cb99 b9ef6c8
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Sat Nov 26 11:31:39 2011 +0100
Merge branch 'master' into feature/rest
commit 096cb99394259a950b92c81781405ad87fb206f6
Merge: 123ac05 90081e7
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri Nov 25 17:56:43 2011 +0100
Merge branch 'master' into feature/rest
Conflicts:
modules/enterprise/server/container/pom.xml
modules/enterprise/server/ear/pom.xml
diff --cc modules/enterprise/server/ear/pom.xml
index b792ab8,258a946e..941c88a
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@@ -95,7 -89,11 +89,11 @@@
<groupId>org.rhq</groupId>
<artifactId>rhq-core-domain</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>javassist</groupId>
+ <artifactId>javassist</artifactId>
+ </exclusion>
- </exclusions>
+ </exclusions>
</dependency>
<dependency>
diff --cc modules/jopr/modules-plugins-pom.xml
index dc1fa28,3b602ea..1bb52cf
--- a/modules/jopr/modules-plugins-pom.xml
+++ b/modules/jopr/modules-plugins-pom.xml
@@@ -1,83 -1,74 +1,74 @@@
--<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-- <modelVersion>4.0.0</modelVersion>
--
-- <parent>
-- <groupId>org.jboss.on</groupId>
-- <artifactId>jopr-modules-parent</artifactId>
-- <version>2.4.0-SNAPSHOT</version>
-- </parent>
--
-- <!-- Plugin poms should not set their parent pom to this artifact. Instead, set to "jopr-modules-parent". This is due to
-- the fact that this pom runs integration tests *on* the plugins. This pom must process in the reactor after the
-- plugins themselves, as such, it can't be their parent. -->
-- <groupId>org.jboss.on</groupId>
-- <artifactId>jopr-plugins-parent</artifactId>
-- <version>2.3.0.EmbJopr.1.3.0-1</version>
-- <packaging>pom</packaging>
-- <name>Jopr Plugins</name>
-- <description>parent POM for all Jopr plugins</description>
--
- <scm>
- <connection>scm:svn:http://svn.jboss.org/repos/jopr/tags/Jopr_2_3_0_EmbJopr_1_3_0-1/m...</connection>
- <developerConnection>scm:svn:https://svn.jboss.org/repos/jopr/tags/Jopr_2_3_0_EmbJopr_1_3_0-1/...</developerConnection>
- </scm>
-
- <properties>
- <scm.module.path>modules/plugins/</scm.module.path>
- </properties>
-
-- <dependencies>
-- <dependency>
-- <groupId>${rhq.groupId}</groupId>
-- <artifactId>rhq-jmx-plugin</artifactId>
-- <version>${rhq.version}</version>
-- <scope>test</scope>
-- </dependency>
-- </dependencies>
--
-- <!-- plugins - order is important -->
-- <modules>
-- <module>tomcat</module>
-- <module>jboss-as</module>
-- <module>hibernate</module>
-- <module>rhq-server</module>
-- <module>jboss-cache</module>
-- <module>jboss-as-5</module>
-- <module>jboss-cache-v3</module>
-- </modules>
--
-- <build>
-- <plugins>
-- <plugin>
-- <artifactId>maven-antrun-plugin</artifactId>
-- <executions>
-- <execution>
-- <phase>integration-test</phase>
-- <configuration>
-- <tasks>
-- <property name="test.classpath" refid="maven.test.classpath" />
-- <echo>Validating plugins...</echo>
-- <java classname="org.rhq.core.pc.plugin.PluginValidator" failonerror="true" fork="true">
-- <classpath>
-- <pathelement path="${test.classpath}" />
-- <pathelement location="hibernate/target/jopr-hibernate-plugin-${project.version}.jar" />
-- <pathelement location="tomcat/target/jopr-tomcat-plugin-${project.version}.jar" />
-- <pathelement location="jboss-as/target/jopr-jboss-as-plugin-${project.version}.jar" />
-- <!-- TODO: Figure out why this is causing NoClassDefFoundErrors and fix it. -->
-- <!--<pathelement location="jboss-as-5/target/jopr-jboss-as-5-plugin-${project.version}.jar" />-->
-- <pathelement location="rhq-server/target/jopr-rhq-server-plugin-${project.version}.jar" />
-- </classpath>
-- <sysproperty key="org.apache.commons.logging.Log" value="org.apache.commons.logging.impl.SimpleLog" />
-- </java>
-- </tasks>
-- </configuration>
-- <goals>
-- <goal>run</goal>
-- </goals>
-- </execution>
-- </executions>
-- </plugin>
-- </plugins>
-- </build>
--
--</project>
++<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
++ <modelVersion>4.0.0</modelVersion>
++
++ <parent>
++ <groupId>org.jboss.on</groupId>
++ <artifactId>jopr-modules-parent</artifactId>
++ <version>2.4.0-SNAPSHOT</version>
++ </parent>
++
++ <!-- Plugin poms should not set their parent pom to this artifact. Instead, set to "jopr-modules-parent". This is due to
++ the fact that this pom runs integration tests *on* the plugins. This pom must process in the reactor after the
++ plugins themselves, as such, it can't be their parent. -->
++ <groupId>org.jboss.on</groupId>
++ <artifactId>jopr-plugins-parent</artifactId>
++ <version>2.3.0.EmbJopr.1.3.0-1</version>
++ <packaging>pom</packaging>
++ <name>Jopr Plugins</name>
++ <description>parent POM for all Jopr plugins</description>
++
++ <dependencies>
++ <dependency>
++ <groupId>${rhq.groupId}</groupId>
++ <artifactId>rhq-jmx-plugin</artifactId>
++ <version>${rhq.version}</version>
++ <scope>test</scope>
++ </dependency>
++ </dependencies>
++
++ <!-- plugins - order is important -->
++ <modules>
++ <module>tomcat</module>
++ <module>jboss-as</module>
++ <module>hibernate</module>
++ <module>rhq-server</module>
++ <module>jboss-cache</module>
++ <module>jboss-as-5</module>
++ <module>jboss-cache-v3</module>
++ </modules>
++
++ <build>
++ <plugins>
++ <plugin>
++ <artifactId>maven-antrun-plugin</artifactId>
++ <executions>
++ <execution>
++ <phase>integration-test</phase>
++ <configuration>
++ <tasks>
++ <property name="test.classpath" refid="maven.test.classpath" />
++ <echo>Validating plugins...</echo>
++ <java classname="org.rhq.core.pc.plugin.PluginValidator" failonerror="true" fork="true">
++ <classpath>
++ <pathelement path="${test.classpath}" />
++ <pathelement location="hibernate/target/jopr-hibernate-plugin-${project.version}.jar" />
++ <pathelement location="tomcat/target/jopr-tomcat-plugin-${project.version}.jar" />
++ <pathelement location="jboss-as/target/jopr-jboss-as-plugin-${project.version}.jar" />
++ <!-- TODO: Figure out why this is causing NoClassDefFoundErrors and fix it. -->
++ <!--<pathelement location="jboss-as-5/target/jopr-jboss-as-5-plugin-${project.version}.jar" />-->
++ <pathelement location="rhq-server/target/jopr-rhq-server-plugin-${project.version}.jar" />
++ </classpath>
++ <sysproperty key="org.apache.commons.logging.Log" value="org.apache.commons.logging.impl.SimpleLog" />
++ </java>
++ </tasks>
++ </configuration>
++ <goals>
++ <goal>run</goal>
++ </goals>
++ </execution>
++ </executions>
++ </plugin>
++ </plugins>
++ </build>
++
++</project>
diff --cc modules/jopr/modules-pom.xml
index 7571c50,67e763b..de9ca10
--- a/modules/jopr/modules-pom.xml
+++ b/modules/jopr/modules-pom.xml
@@@ -1,131 -1,124 +1,124 @@@
--<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
--
-- <modelVersion>4.0.0</modelVersion>
--
-- <parent>
-- <groupId>org.jboss.on</groupId>
-- <artifactId>jopr-parent</artifactId>
-- <version>2.4.0-SNAPSHOT</version>
-- </parent>
--
-- <groupId>org.jboss.on</groupId>
-- <artifactId>jopr-modules-parent</artifactId>
-- <packaging>pom</packaging>
--
-- <name>Jopr Modules</name>
-- <description>parent POM for all Jopr modules</description>
--
- <scm>
- <connection>scm:svn:http://svn.jboss.org/repos/jopr/trunk/modules/</connection>
- <developerConnection>scm:svn:https://svn.jboss.org/repos/jopr/trunk/modules/</developerConnection>
- </scm>
-
-- <properties>
- <scm.module.path>modules/</scm.module.path>
-
-- <!-- dependency versions -->
-- <hibernate-all.version>1.0.0.Alpha9</hibernate-all.version>
-- <persistence-api.version>1.0</persistence-api.version>
-- </properties>
--
-- <!-- These dependencies are (mostly) common to the plugin artifacts built under the
-- Jopr umbrella. They are not specific to the build a one particular artifact but
-- placed here to simplify the child poms. -->
-- <dependencies>
--
-- <dependency>
-- <groupId>${rhq.groupId}</groupId>
-- <artifactId>rhq-core-util</artifactId>
-- <version>${rhq.version}</version>
-- <scope>provided</scope> <!-- by PC -->
-- </dependency>
--
-- <dependency>
-- <groupId>${rhq.groupId}</groupId>
-- <artifactId>rhq-core-domain</artifactId>
-- <version>${rhq.version}</version>
-- <scope>provided</scope> <!-- by PC -->
-- </dependency>
--
-- <dependency>
-- <groupId>${rhq.groupId}</groupId>
-- <artifactId>rhq-core-plugin-api</artifactId>
-- <version>${rhq.version}</version>
-- <scope>provided</scope> <!-- by PC -->
-- </dependency>
--
-- <dependency>
-- <groupId>${rhq.groupId}</groupId>
-- <artifactId>rhq-core-native-system</artifactId>
-- <version>${rhq.version}</version>
-- <scope>provided</scope> <!-- by PC -->
-- </dependency>
--
-- <dependency>
-- <groupId>${rhq.groupId}</groupId>
-- <artifactId>rhq-core-plugin-container</artifactId>
-- <version>${rhq.version}</version>
-- <scope>test</scope>
-- </dependency>
--
-- <!-- Third-party libs -->
-- <dependency>
-- <groupId>javax.xml.bind</groupId>
-- <artifactId>jaxb-api</artifactId>
-- <scope>provided</scope>
-- </dependency>
--
-- <dependency>
-- <groupId>com.sun.xml.bind</groupId>
-- <artifactId>jaxb-impl</artifactId>
-- <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-- <scope>provided</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. -->
-- <dependency>
-- <groupId>javax.persistence</groupId>
-- <artifactId>persistence-api</artifactId>
-- <version>${persistence-api.version}</version>
-- <scope>provided</scope> <!-- by ON container -->
-- </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. -->
-- <dependency>
-- <groupId>jboss.jboss-embeddable-ejb3</groupId>
-- <artifactId>hibernate-all</artifactId>
-- <version>${hibernate-all.version}</version>
-- <scope>provided</scope> <!-- by ON container -->
-- </dependency>
--
-- </dependencies>
--
-- <modules>
-- <module>common</module>
-- <module>plugins</module>
-- </modules>
--
-- <profiles>
--
-- <!-- enterprise-only stuff -->
-- <profile>
-- <id>enterprise</id>
-- <activation>
-- <activeByDefault>true</activeByDefault>
-- </activation>
-- <modules>
-- <module>serverplugins</module>
-- </modules>
-- </profile>
--
-- <!-- same as enterprise profile, except includes dist -->
-- <profile>
-- <id>dist</id>
-- <modules>
-- <module>serverplugins</module>
-- <module>dist</module>
-- </modules>
-- </profile>
--
-- </profiles>
--</project>
++<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
++
++ <modelVersion>4.0.0</modelVersion>
++
++ <parent>
++ <groupId>org.jboss.on</groupId>
++ <artifactId>jopr-parent</artifactId>
++ <version>2.4.0-SNAPSHOT</version>
++ </parent>
++
++ <groupId>org.jboss.on</groupId>
++ <artifactId>jopr-modules-parent</artifactId>
++ <packaging>pom</packaging>
++
++ <name>Jopr Modules</name>
++ <description>parent POM for all Jopr modules</description>
++
++ <properties>
++ <!-- dependency versions -->
++ <hibernate-all.version>1.0.0.Alpha9</hibernate-all.version>
++ <persistence-api.version>1.0</persistence-api.version>
++ </properties>
++
++ <!-- These dependencies are (mostly) common to the plugin artifacts built under the
++ Jopr umbrella. They are not specific to the build a one particular artifact but
++ placed here to simplify the child poms. -->
++ <dependencies>
++
++ <dependency>
++ <groupId>${rhq.groupId}</groupId>
++ <artifactId>rhq-core-util</artifactId>
++ <version>${rhq.version}</version>
++ <scope>provided</scope> <!-- by PC -->
++ </dependency>
++
++ <dependency>
++ <groupId>${rhq.groupId}</groupId>
++ <artifactId>rhq-core-domain</artifactId>
++ <version>${rhq.version}</version>
++ <scope>provided</scope> <!-- by PC -->
++ </dependency>
++
++ <dependency>
++ <groupId>${rhq.groupId}</groupId>
++ <artifactId>rhq-core-plugin-api</artifactId>
++ <version>${rhq.version}</version>
++ <scope>provided</scope> <!-- by PC -->
++ </dependency>
++
++ <dependency>
++ <groupId>${rhq.groupId}</groupId>
++ <artifactId>rhq-core-native-system</artifactId>
++ <version>${rhq.version}</version>
++ <scope>provided</scope> <!-- by PC -->
++ </dependency>
++
++ <dependency>
++ <groupId>${rhq.groupId}</groupId>
++ <artifactId>rhq-core-plugin-container</artifactId>
++ <version>${rhq.version}</version>
++ <scope>test</scope>
++ </dependency>
++
++ <!-- Third-party libs -->
++ <dependency>
++ <groupId>javax.xml.bind</groupId>
++ <artifactId>jaxb-api</artifactId>
++ <scope>provided</scope>
++ </dependency>
++
++ <dependency>
++ <groupId>com.sun.xml.bind</groupId>
++ <artifactId>jaxb-impl</artifactId>
++ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
++ <scope>provided</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. -->
++ <dependency>
++ <groupId>javax.persistence</groupId>
++ <artifactId>persistence-api</artifactId>
++ <version>${persistence-api.version}</version>
++ <scope>provided</scope> <!-- by ON container -->
++ </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. -->
++ <dependency>
++ <groupId>jboss.jboss-embeddable-ejb3</groupId>
++ <artifactId>hibernate-all</artifactId>
++ <version>${hibernate-all.version}</version>
++ <scope>provided</scope> <!-- by ON container -->
++ </dependency>
++
++ </dependencies>
++
++ <modules>
++ <module>common</module>
++ <module>plugins</module>
++ </modules>
++
++ <profiles>
++
++ <!-- enterprise-only stuff -->
++ <profile>
++ <id>enterprise</id>
++ <activation>
++ <activeByDefault>true</activeByDefault>
++ </activation>
++ <modules>
++ <module>serverplugins</module>
++ </modules>
++ </profile>
++
++ <!-- same as enterprise profile, except includes dist -->
++ <profile>
++ <id>dist</id>
++ <modules>
++ <module>serverplugins</module>
++ <module>dist</module>
++ </modules>
++ </profile>
++
++ </profiles>
++</project>
commit 123ac05d5c93d5f66961e435ccfb67d907c86287
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri Nov 25 10:23:05 2011 +0100
Turn down logging. Prevent a LazyLoadException for schedules.
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 e670afb..ce4dd43 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
@@ -146,7 +146,7 @@ public class AbstractRestBean {
protected <T>T getFromCache(Fqn fqn,Class<T> clazz) {
Object o=null;
if (treeCache.exists(fqn)) {
- log.info("Hit for " + fqn.toString());
+ log.debug("Hit for " + fqn.toString());
try{
Node n = treeCache.get(fqn);
Set<Integer> readers= (Set<Integer>) n.get("readers");
@@ -154,11 +154,10 @@ public class AbstractRestBean {
o = n.get("item");
}
else {
- log.info("No object for caller " +caller.toString() + " found");
+ log.debug("No object for caller " +caller.toString() + " found");
}
} catch (CacheException e) {
- e.printStackTrace(); // TODO: Customise this generated block
- log.info("Miss for " + fqn.toString());
+ log.debug("Miss for " + fqn.toString());
}
}
return (T)o;
@@ -187,9 +186,9 @@ public class AbstractRestBean {
treeCache.put(fqn,"readers",readers);
treeCache.put(fqn,"item",o);
success = true;
- log.info("Put " + fqn);
+ log.debug("Put " + fqn);
} catch (CacheException e) {
- e.printStackTrace(); // TODO: Customise this generated block
+ log.warn(e.getMessage());
}
return success;
}
@@ -235,7 +234,7 @@ public class AbstractRestBean {
childParentMap.put(res.getId(), pid);
treeCache.put(resourceMeta,"childParentMap",childParentMap);
} catch (CacheException e) {
- e.printStackTrace(); // TODO: Customise this generated block
+ log.warn(e.getMessage());
}
}
@@ -269,7 +268,7 @@ public class AbstractRestBean {
ret.add(getFromCache(resId, Resource.class));
}
} catch (CacheException e) {
- e.printStackTrace(); // TODO: Customise this generated block
+ log.warn(e.getMessage());
}
}
@@ -287,7 +286,7 @@ public class AbstractRestBean {
if (visibleResources.contains(resourceid))
res = getFromCache(resourceid,Resource.class);
} catch (CacheException e) {
- e.printStackTrace(); // TODO: Customise this generated block
+ log.warn(e.getMessage());
}
}
@@ -316,7 +315,7 @@ public class AbstractRestBean {
if (treeCache.exists(fqn)) {
try {
treeCache.remove(fqn);
- log.info("Cancel " + fqn);
+ log.debug("Cancel " + fqn);
return true;
} catch (CacheException e) {
return false;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index e500a33..91ed23a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -200,7 +200,7 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
if (scheduleType.equals("metric"))
scheduleType=DataType.MEASUREMENT.toString().toLowerCase();
- Resource res = fetchResource(resourceId);
+ Resource res = resMgr.getResource(caller,resourceId); // Don't fetch(), as this would yield a LazyLoadException
Set<MeasurementSchedule> schedules = res.getSchedules();
List<MetricSchedule> ret = new ArrayList<MetricSchedule>(schedules.size());
@@ -290,6 +290,7 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
Link link = new Link();
link.setRel("alert");
link.setHref("/alert/" + al.getId());
+ links.add(link);
}
return links;
}
commit cfbb12d5a736b1f01415ef33fbe7a0b0f8078380
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Nov 21 10:46:18 2011 +0100
Tried to do some stuff wrt caching, simple operations can now be scheduled.
Fix operation history retrieval
Tiny cleanup.
diff --git a/modules/enterprise/server/container/src/main/resources/jbossas/server/default/deploy/rhq-cache-service.xml b/modules/enterprise/server/container/src/main/resources/jbossas/server/default/deploy/rhq-cache-service.xml
index f458a8e..4381fbb 100644
--- a/modules/enterprise/server/container/src/main/resources/jbossas/server/default/deploy/rhq-cache-service.xml
+++ b/modules/enterprise/server/container/src/main/resources/jbossas/server/default/deploy/rhq-cache-service.xml
@@ -123,8 +123,8 @@
<attribute name="wakeUpIntervalSeconds">5</attribute>
<!-- Cache wide default -->
<region name="/_default_">
- <attribute name="maxNodes">5000</attribute>
- <attribute name="timeToLiveSeconds">1000</attribute>
+ <attribute name="maxNodes">50000</attribute>
+ <attribute name="timeToLiveSeconds">3600</attribute>
</region>
<region name="/schedules">
<attribute name="maxNodes">5000</attribute>
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 1be4db0..e670afb 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
@@ -25,12 +25,14 @@ package org.rhq.enterprise.server.rest;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URI;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Set;
-import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
@@ -51,6 +53,7 @@ import org.jboss.cache.Node;
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.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.ResourceWithType;
@@ -61,7 +64,7 @@ import org.rhq.enterprise.server.rest.domain.ResourceWithType;
* @author Heiko W. Rupp
*/
@Stateless
-@Resource(name="cache",type= TreeCacheMBean.class,mappedName = "RhqCache")
+(a)javax.annotation.Resource(name="cache",type= TreeCacheMBean.class,mappedName = "RhqCache")
public class AbstractRestBean {
Log log = LogFactory.getLog(getClass().getName());
@@ -70,7 +73,7 @@ public class AbstractRestBean {
Subject caller;
/** The cache to use */
- @Resource(name="cache")
+ @javax.annotation.Resource(name="cache")
TreeCacheMBean treeCache;
/**
@@ -204,6 +207,94 @@ public class AbstractRestBean {
return putToCache(fqn,o);
}
+ protected void putResourceToCache(Resource res) {
+ putToCache(res.getId(),Resource.class,res);
+
+ Fqn callerFqn = new Fqn(new String[]{"user", String.valueOf(caller.getId()),"resources"});
+ Set<Integer> visibleResources;
+ try {
+ if (treeCache.exists(callerFqn)) {
+ Node n = treeCache.get(callerFqn);
+ visibleResources = (Set<Integer>) n.get("visibleResources");
+ }
+ else {
+ visibleResources = new HashSet<Integer>();
+ }
+ visibleResources.add(res.getId());
+ treeCache.put(callerFqn,"visibleResources",visibleResources);
+
+ Fqn resourceMeta = new Fqn(new String[] { "resourceMeta"});
+ Map<Integer,Integer> childParentMap;
+ if (treeCache.exists(resourceMeta)) {
+ childParentMap = (Map<Integer, Integer>) treeCache.get(resourceMeta,"childParentMap");
+ }
+ else {
+ childParentMap = new HashMap<Integer,Integer>();
+ }
+ int pid = res.getParentResource() == null ? 0 : res.getParentResource().getId();
+ childParentMap.put(res.getId(), pid);
+ treeCache.put(resourceMeta,"childParentMap",childParentMap);
+ } catch (CacheException e) {
+ e.printStackTrace(); // TODO: Customise this generated block
+ }
+ }
+
+ protected List<Resource> getResourcesFromCacheByParentId(int pid) {
+ List<Integer> candidateIds = new ArrayList<Integer>();
+ List<Resource> ret = new ArrayList<Resource>();
+
+ // First determine candidate children
+ Map<Integer,Integer> childParentMap;
+ Fqn resourceMeta = new Fqn(new String[] { "resourceMeta"});
+ if (treeCache.exists(resourceMeta)) {
+ try {
+ childParentMap = (Map<Integer, Integer>) treeCache.get(resourceMeta,"childParentMap");
+ for (Map.Entry<Integer,Integer> entry : childParentMap.entrySet()) {
+ if (entry.getValue() == pid)
+ candidateIds.add(entry.getKey());
+ }
+ // then see if the current user can see them
+ Fqn callerFqn = new Fqn(new String[]{"user", String.valueOf(caller.getId()),"resources"});
+ Set<Integer> visibleResources = (Set<Integer>) treeCache.get(callerFqn,"visibleResources");
+ Iterator<Integer> iter = candidateIds.iterator();
+ while (iter.hasNext()) {
+ Integer resId = iter.next();
+ if (!visibleResources.contains(resId)) {
+ iter.remove();
+ }
+ }
+
+ // Last but not least, get the resources and return them
+ for (Integer resId : candidateIds) {
+ ret.add(getFromCache(resId, Resource.class));
+ }
+ } catch (CacheException e) {
+ e.printStackTrace(); // TODO: Customise this generated block
+ }
+
+ }
+ return ret;
+ }
+
+ protected Resource getResourceFromCache(int resourceid) {
+
+ Resource res = null;
+ // check if the current user can see the resource
+ Fqn callerFqn = new Fqn(new String[]{"user", String.valueOf(caller.getId()),"resources"});
+ if (treeCache.exists(callerFqn)) {
+ try {
+ Set<Integer> visibleResources = (Set<Integer>) treeCache.get(callerFqn,"visibleResources");
+ if (visibleResources.contains(resourceid))
+ res = getFromCache(resourceid,Resource.class);
+ } catch (CacheException e) {
+ e.printStackTrace(); // TODO: Customise this generated block
+ }
+ }
+
+ return res;
+ }
+
+
/**
* Construct a Fqn object from the passed data
* @param id Id of the target object
@@ -244,6 +335,8 @@ public class AbstractRestBean {
if (parent!=null) {
rwt.setParentId(parent.getId());
}
+ else
+ rwt.setParentId(0);
UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
uriBuilder.path("/operation/definitions");
uriBuilder.queryParam("resourceId",res.getId());
@@ -251,6 +344,38 @@ public class AbstractRestBean {
Link link = new Link("operationDefinitions",uri.toString());
rwt.addLink(link);
+/*
+ for (Resource child : getResourcesFromCacheByParentId(res.getId())) {
+ uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/resource/{id}");
+ uri = uriBuilder.build(child.getId());
+ link = new Link("child",uri.toString());
+ rwt.addLink(link);
+ }
+*/
+ uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/resource/{id}");
+ uri = uriBuilder.build(res.getId());
+ link = new Link("self",uri.toString());
+ rwt.addLink(link);
+ uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/resource/{id}/schedules");
+ uri = uriBuilder.build(res.getId());
+ link = new Link("schedules",uri.toString());
+ rwt.addLink(link);
+ uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/resource/{id}/children");
+ uri = uriBuilder.build(res.getId());
+ link = new Link("children",uri.toString());
+ rwt.addLink(link);
+ if (parent!=null) {
+ uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/resource/{id}/");
+ uri = uriBuilder.build(parent.getId());
+ link = new Link("parent",uri.toString());
+ rwt.addLink(link);
+ }
+
return rwt;
}
}
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 627c22b..d742139 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
@@ -1,7 +1,5 @@
package org.rhq.enterprise.server.rest;
-import java.util.List;
-
import javax.ejb.Local;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
@@ -10,7 +8,6 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
@@ -18,9 +15,9 @@ import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
-import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.jboss.resteasy.annotations.cache.Cache;
+
import org.rhq.enterprise.server.rest.domain.GroupRest;
-import org.rhq.enterprise.server.rest.domain.ResourceWithType;
/**
* Handler for Group related things
@@ -36,6 +33,7 @@ public interface GroupHandlerLocal {
public Response getGroups(@Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo);
+ @Cache(isPrivate = true,maxAge = 60)
@GET
@Path("{id}")
public Response getGroup(@PathParam("id") int id,@Context Request request, @Context HttpHeaders headers,
@@ -61,6 +59,7 @@ public interface GroupHandlerLocal {
@GET
@Path("{id}/resources")
+ @Cache(isPrivate = true,maxAge = 60)
public Response getResources(@PathParam("id") int id, @Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
index 2a4f7df..536274a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -9,12 +9,13 @@ import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
@@ -22,9 +23,17 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
+import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.configuration.definition.PropertyDefinition;
+import org.rhq.core.domain.criteria.OperationHistoryCriteria;
+import org.rhq.core.domain.criteria.ResourceOperationHistoryCriteria;
+import org.rhq.core.domain.operation.HistoryJobId;
+import org.rhq.core.domain.operation.JobId;
import org.rhq.core.domain.operation.OperationDefinition;
+import org.rhq.core.domain.operation.OperationHistory;
+import org.rhq.core.domain.operation.ResourceOperationHistory;
+import org.rhq.core.domain.operation.bean.ResourceOperationSchedule;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.enterprise.server.operation.OperationManagerLocal;
@@ -86,19 +95,14 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
}
- CacheControl cc = new CacheControl();
- cc.setMaxAge(1200); // Definitions are very stable, so caching for 20mins is ok
- cc.setPrivate(false);
builder.tag(eTag);
- builder.cacheControl(cc);
return builder.build();
}
@Override
- // TODO find out why a return type of Response lets this fail for XML (even with @Wrapped annotation
- public List<OperationDefinitionRest> getOperationDefinitions(Integer resourceId, UriInfo uriInfo, Request request) {
+ public Response getOperationDefinitions(Integer resourceId, UriInfo uriInfo, Request request) {
if (resourceId == null)
throw new ParameterMissingException("resourceId");
@@ -109,16 +113,15 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
ResourceType resourceType = res.getResourceType();
-/*
EntityTag eTag = new EntityTag(Integer.toHexString(resourceType.hashCode()));
Response.ResponseBuilder builder = request.evaluatePreconditions(eTag);
if (builder==null) {
-*/
Set<OperationDefinition> opDefList = resourceType.getOperationDefinitions();
List<OperationDefinitionRest> resultList = new ArrayList<OperationDefinitionRest>(opDefList.size());
for (OperationDefinition def : opDefList) {
+ putToCache(def.getId(),OperationDefinition.class,def);
OperationDefinitionRest odr = new OperationDefinitionRest();
odr.setId(def.getId());
odr.setName(def.getName());
@@ -130,21 +133,13 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
resultList.add(odr);
}
- return resultList;
-
-/*
- builder = Response.ok(resultList);
+ GenericEntity<List<OperationDefinitionRest>> entity = new GenericEntity<List<OperationDefinitionRest>>(resultList){};
+ builder = Response.ok(entity);
}
- CacheControl cc = new CacheControl();
- cc.setMaxAge(1200); // Definitions are very stable, so caching for 20mins is ok
- cc.setPrivate(false);
builder.tag(eTag);
- builder.cacheControl(cc);
-
return builder.build();
-*/
}
@@ -203,19 +198,30 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
if (operation.getState().equals("creating") && operation.getDefinitionId()>0 && !operation.getName().isEmpty()) {
// TODO check all the required parameters for persence before allowing to submit
- Link link = new Link("submit","TODO");
- operation.addLink(link);
-
+ operation.setState("ready");
}
- UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
- uriBuilder.path("/operation/{id}");
- URI uri = uriBuilder.build(operation.getId());
- Link editLink = new Link("edit",uri.toString());
- operation.addLink(editLink);
+ if (operation.getState().equals("ready")) {
+ // todo check params
+
+ // submit
+ ResourceOperationSchedule sched = opsManager.scheduleResourceOperation(caller,operation.getResourceId(),operation.getName(),0,0,0,-1,new Configuration(),"TEst");
+ JobId jobId = new JobId(sched.getJobName(),sched.getJobGroup());
+ UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/operation/history/{id}");
+ URI uri = uriBuilder.build(jobId);
+ Link histLink = new Link("history",uri.toString());
+ operation.addLink(histLink);
+ }
+ else {
+ UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/operation/{id}");
+ URI uri = uriBuilder.build(operation.getId());
+ Link editLink = new Link("edit",uri.toString());
+ operation.addLink(editLink);
+ }
// Update item in cache
putToCache(operation.getId(),OperationRest.class,operation);
-
Response.ResponseBuilder builder = Response.ok(operation);
return builder.build();
}
@@ -233,4 +239,30 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
return null; // TODO: Customise this generated block
}
+ @Override
+ @GET
+ @Path("history/{id}")
+ public Response outcome(@PathParam("id") String jobName) {
+
+/*
+ ResourceOperationSchedule schedule = opsManager.getResourceOperationSchedule(caller,operationHistoryId);
+ if (schedule==null)
+ throw new StuffNotFoundException("OperationSchedule with id " + operationHistoryId);
+*/
+
+ ResourceOperationHistoryCriteria criteria = new ResourceOperationHistoryCriteria();
+ criteria.addFilterJobId(new JobId(jobName));
+
+ OperationHistory history ;//= opsManager.getOperationHistoryByJobId(caller,jobName);
+ List<ResourceOperationHistory> list = opsManager.findResourceOperationHistoriesByCriteria(caller,criteria);
+ if (list==null || list.isEmpty())
+ throw new StuffNotFoundException("OperationHistory with id " + new HistoryJobId(jobName));
+
+ history = list.get(0);
+ String ret = history.getStatus().getDisplayName();
+ // TODO get history.results with the help of the property definition
+
+ return Response.ok(ret).build();
+
+ }
}
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 5ab7366..1d2a9ed 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
@@ -19,6 +19,8 @@ import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
+import org.jboss.resteasy.annotations.cache.Cache;
+
import org.rhq.enterprise.server.rest.domain.OperationDefinitionRest;
import org.rhq.enterprise.server.rest.domain.OperationRest;
@@ -28,12 +30,13 @@ import org.rhq.enterprise.server.rest.domain.OperationRest;
*/
@Local
@Path("/operation")
+(a)Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public interface OperationsHandlerLocal {
@GET
@Path("definition/{id}")
- @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
+ @Cache(maxAge = 1200)
public Response getOperationDefinition(@PathParam("id") int definitionId,
@QueryParam("resourceId") Integer resourceId,
@Context UriInfo uriInfo,
@@ -42,33 +45,32 @@ public interface OperationsHandlerLocal {
@GET
@Path("definitions")
- @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
- public List<OperationDefinitionRest> getOperationDefinitions(@QueryParam("resourceId") Integer resourceId,
+ @Cache(maxAge = 1200)
+ public Response getOperationDefinitions(@QueryParam("resourceId") Integer resourceId,
@Context UriInfo uriInfo,
@Context Request request
);
@POST
@Path("definition/{id}")
- @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public Response createOperation(@PathParam("id") int definitionId,
@QueryParam("resourceId") Integer resourceId,
@Context UriInfo uriInfo);
@GET
@Path("{id}")
- @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public Response getOperation(@PathParam("id") int operationId);
@PUT
@Path("{id}")
- @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
@Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public Response updateOperation(@PathParam("id") int operationId, OperationRest operation, @Context UriInfo uriInfo);
@DELETE
@Path("{id}")
- @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public Response cancelOperation(@PathParam("id") int operationId);
+ @GET
+ @Path("history/{id}")
+ public Response outcome(@PathParam("id") String jobName);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index f90143a..e500a33 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -31,7 +31,6 @@ import java.util.Set;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
-import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.GenericEntity;
@@ -42,8 +41,6 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
-import com.arjuna.ats.internal.jdbc.drivers.modifiers.list;
-
import org.rhq.core.domain.alert.Alert;
import org.rhq.core.domain.criteria.AlertCriteria;
import org.rhq.core.domain.measurement.Availability;
@@ -85,29 +82,14 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
public Response getResource(int id, @Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo) {
- // Create a cache control
- CacheControl cc = new CacheControl();
- cc.setMaxAge(300); // Resources are valid for 5 mins
- cc.setPrivate(false); // Proxies may cache this
-
Resource res;
- res = getFromCache(id,Resource.class);
- if (res==null) {
- res = resMgr.getResource(caller, id);
- if (res!=null)
- putToCache(id, Resource.class,res);
- else
- throw new StuffNotFoundException("Resource with id " + id);
- }
-
- Response.ResponseBuilder builder=null;
+ res = fetchResource(id);
long mtime = res.getMtime();
EntityTag eTag = new EntityTag(Long.toOctalString(res.hashCode()+ mtime)); // factor in mtime in etag
- builder = request.evaluatePreconditions(new Date(mtime),eTag);
+ Response.ResponseBuilder builder = request.evaluatePreconditions(new Date(mtime),eTag);
if (builder!=null) {
- builder.cacheControl(cc);
return builder.build();
}
@@ -218,7 +200,7 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
if (scheduleType.equals("metric"))
scheduleType=DataType.MEASUREMENT.toString().toLowerCase();
- Resource res = resMgr.getResource(caller, resourceId);
+ Resource res = fetchResource(resourceId);
Set<MeasurementSchedule> schedules = res.getSchedules();
List<MetricSchedule> ret = new ArrayList<MetricSchedule>(schedules.size());
@@ -273,18 +255,10 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
@Context UriInfo uriInfo) {
PageControl pc = new PageControl();
Resource parent;
- parent = getFromCache(id,Resource.class);
- if (parent==null) {
- parent = resMgr.getResource(caller,id);
- if (parent==null)
- throw new StuffNotFoundException("Resource with id " + id);
- else
- putToCache(id,Resource.class,parent);
- }
+ parent = fetchResource(id);
List<Resource> ret = resMgr.findResourceByParentAndInventoryStatus(caller,parent,InventoryStatus.COMMITTED,pc);
List<ResourceWithType> rwtList = new ArrayList<ResourceWithType>(ret.size());
for (Resource r: ret) {
- putToCache(r.getId(),Resource.class,r);
ResourceWithType rwt = fillRWT(r, uriInfo);
rwtList.add(rwt);
}
@@ -319,4 +293,18 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
}
return links;
}
+
+ private Resource fetchResource(int resourceId) {
+ Resource res;
+ res = getFromCache(resourceId,Resource.class);
+ if (res==null) {
+ res = resMgr.getResource(caller, resourceId);
+ if (res!=null)
+ putToCache(resourceId, Resource.class,res);
+ else
+ throw new StuffNotFoundException("Resource with id " + resourceId);
+ }
+ return res;
+ }
+
}
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 412b347..08a1905 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
@@ -34,6 +34,7 @@ import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
+import org.jboss.resteasy.annotations.cache.Cache;
import org.jboss.resteasy.links.AddLinks;
import org.jboss.resteasy.links.LinkResource;
import org.jboss.resteasy.links.LinkResources;
@@ -59,12 +60,13 @@ public interface ResourceHandlerLocal {
})
@GET
@Path("/{id}")
-
+ @Cache(isPrivate = true,maxAge = 120)
Response getResource(@PathParam("id") int id, @Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo);
@GET
@Path("/platforms")
+ @Cache(isPrivate = true,maxAge = 300)
Response getPlatforms(@Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo);
@@ -82,6 +84,7 @@ public interface ResourceHandlerLocal {
@GET
@Path("/{id}/schedules")
@LinkResource(rel="schedules",value = MetricSchedule.class)
+ @Cache(isPrivate = true,maxAge = 60)
Response getSchedules(@PathParam("id") int resourceId,
@QueryParam("type") @DefaultValue("all") String scheduleType,
@Context Request request,
commit 1527222e6a0c560401e29300ffc26e1ac807a1e9
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue Nov 15 10:22:42 2011 +0100
Use the correct data type as input for group creation. Add some more attributes to a group.
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 5ecbb86..76180d9 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
@@ -28,8 +28,11 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.criteria.ResourceGroupCriteria;
import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.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.rest.domain.GroupRest;
@@ -52,6 +55,9 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
@EJB
ResourceManagerLocal resourceManager;
+ @EJB
+ ResourceTypeManagerLocal resourceTypeManager;
+
public Response getGroups(@Context Request request, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
ResourceGroupCriteria criteria = new ResourceGroupCriteria();
@@ -104,19 +110,33 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
@Override
@POST
@Path("/")
- public Response createGroup(ResourceGroup group, @Context Request request, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
+ public Response createGroup(GroupRest group, @Context Request request, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
+
+ ResourceGroup newGroup = new ResourceGroup(group.getName());
+ if (group.getResourceTypeId()!=null) {
+
+ ResourceType resourceType = null;
+ try {
+ resourceType = resourceTypeManager.getResourceTypeById(caller,group.getResourceTypeId());
+ newGroup.setResourceType(resourceType);
+ } catch (ResourceTypeNotFoundException e) {
+ e.printStackTrace(); // TODO: Customise this generated block
+ throw new StuffNotFoundException("ResourceType with id " + group.getResourceTypeId());
+ }
+ }
Response.ResponseBuilder builder;
try {
- ResourceGroup newGroup = resourceGroupManager.createResourceGroup(caller,group);
+ newGroup = resourceGroupManager.createResourceGroup(caller,newGroup);
UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
uriBuilder.path("/group/{id}");
URI uri = uriBuilder.build(newGroup.getId());
builder=Response.created(uri);
+ putToCache(newGroup.getId(),ResourceGroup.class,newGroup);
} catch (Exception e) {
e.printStackTrace(); // TODO: Customise this generated block
- builder=Response.serverError();
+ builder=Response.status(Response.Status.NOT_ACCEPTABLE);
}
return builder.build();
}
@@ -135,6 +155,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
try {
resourceGroup = resourceGroupManager.updateResourceGroup(caller,resourceGroup);
builder=Response.ok(fillGroup(resourceGroup,uriInfo));
+ putToCache(resourceGroup.getId(),ResourceGroup.class,resourceGroup);
}
catch (Exception e) {
builder = Response.status(Response.Status.NOT_ACCEPTABLE); // TODO correct?
@@ -150,6 +171,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
try {
resourceGroupManager.deleteResourceGroup(caller,id);
+ removeFromCache(id,ResourceGroup.class);
return Response.ok().build();
} catch (ResourceGroupDeleteException e) {
e.printStackTrace(); // TODO: Customise this generated block
@@ -196,8 +218,13 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
if (res==null)
throw new StuffNotFoundException("Resource with id " + resourceId);
- // TODO do we want/ need to check that the group category stays the same?
+ // A resource type is set for the group, so only allow to add resources with the same type.
+ if (resourceGroup.getResourceType()!=null) {
+ if (!res.getResourceType().equals(resourceGroup.getResourceType()))
+ return Response.status(Response.Status.NOT_ACCEPTABLE).build();
+ }
+ // TODO if comp group and no resourceTypeId set, shall we allow to have it change to a mixed group?
resourceGroup.addExplicitResource(res);
return Response.ok().build(); // TODO right code?
@@ -246,6 +273,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
GroupRest gr = new GroupRest(group.getName());
gr.setId(group.getId());
gr.setCategory(group.getGroupCategory());
+ gr.setRecursive(group.isRecursive());
UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
uriBuilder.path("/group/{id}");
URI uri = uriBuilder.build(group.getId());
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 88a3610..627c22b 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
@@ -44,7 +44,7 @@ public interface GroupHandlerLocal {
@POST
@Path("/")
- public Response createGroup(ResourceGroup group, @Context Request request, @Context HttpHeaders headers,
+ public Response createGroup(GroupRest group, @Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo);
@PUT
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java
index c55223d..4c9079b 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java
@@ -18,6 +18,8 @@ public class GroupRest {
int id;
private String name;
+ private Integer resourceTypeId;
+ private boolean recursive;
private GroupCategory category;
List<Link> links = new ArrayList<Link>();
@@ -45,6 +47,22 @@ public class GroupRest {
this.name = name;
}
+ public Integer getResourceTypeId() {
+ return resourceTypeId;
+ }
+
+ public void setResourceTypeId(Integer resourceTypeId) {
+ this.resourceTypeId = resourceTypeId;
+ }
+
+ public boolean isRecursive() {
+ return recursive;
+ }
+
+ public void setRecursive(boolean recursive) {
+ this.recursive = recursive;
+ }
+
public GroupCategory getCategory() {
return category;
}
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 90bbfac..6edaf99 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
@@ -36,6 +36,14 @@
<tr>
<td>Category</td><td>${var.category}</td>
</tr>
+ <#if var.resourceTypeId??>
+ <tr>
+ <td>ResourceType id</td><td></td>
+ </tr>
+ </#if>
+ <tr>
+ <td>Recursive</td><td>${var.recursive?string("Yes","No")}</td>
+ </tr>
</table>
<a href="/rest/1/group/${var.id?c}/resources.html">Resources</a><br/>
</html>
commit 7317b864fa22275d1784edb410d37ef65c84c6d2
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Nov 14 22:55:17 2011 +0100
Do some caching of the group.
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 ea3d2ec..5ecbb86 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
@@ -228,9 +228,14 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
* @throws StuffNotFoundException if the group is not found (or not accessible by the caller)
*/
private ResourceGroup fetchGroup(int groupId) {
- ResourceGroup resourceGroup = resourceGroupManager.getResourceGroup(caller, groupId);
- if (resourceGroup==null)
- throw new StuffNotFoundException("Group with id " + groupId);
+ ResourceGroup resourceGroup;
+ resourceGroup = getFromCache(groupId,ResourceGroup.class);
+ if (resourceGroup==null) {
+ resourceGroup = resourceGroupManager.getResourceGroup(caller, groupId);
+ if (resourceGroup==null)
+ throw new StuffNotFoundException("Group with id " + groupId);
+ putToCache(groupId,ResourceGroup.class,resourceGroup);
+ }
return resourceGroup;
}
commit 2920cb4967c49b083198111032d62bc8e8426b4e
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Nov 14 21:55:30 2011 +0100
Allow updates to the group name.
Remove non-needed method.
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 a227a18..ea3d2ec 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
@@ -124,9 +124,22 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
@Override
@PUT
@Path("{id}")
- public Response updateGroup(@PathParam("id") int id, @Context Request request, @Context HttpHeaders headers,
+ public Response updateGroup(@PathParam("id") int id, GroupRest in, @Context Request request,
+ @Context HttpHeaders headers,
@Context UriInfo uriInfo) {
- return null; // TODO: Customise this generated block
+
+ ResourceGroup resourceGroup = fetchGroup(id);
+ resourceGroup.setName(in.getName());
+ Response.ResponseBuilder builder;
+
+ try {
+ resourceGroup = resourceGroupManager.updateResourceGroup(caller,resourceGroup);
+ builder=Response.ok(fillGroup(resourceGroup,uriInfo));
+ }
+ catch (Exception e) {
+ builder = Response.status(Response.Status.NOT_ACCEPTABLE); // TODO correct?
+ }
+ return builder.build();
}
@Override
@@ -172,18 +185,6 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
}
-
- @Override
- @GET
- @Path("{id}/resource/{resourceId}")
- public Response getResource(@PathParam("id") int id, @PathParam("resourceId") int resourceId,
- @Context Request request, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
-
-
-
- return null; // TODO: Customise this generated block
- }
-
@Override
@PUT
@Path("{id}/resource/{resourceId}")
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 6c91fbe..88a3610 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
@@ -19,6 +19,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.enterprise.server.rest.domain.GroupRest;
import org.rhq.enterprise.server.rest.domain.ResourceWithType;
/**
@@ -48,8 +49,9 @@ public interface GroupHandlerLocal {
@PUT
@Path("{id}")
- public Response updateGroup(@PathParam("id") int id,@Context Request request, @Context HttpHeaders headers,
- @Context UriInfo uriInfo);
+ public Response updateGroup(@PathParam("id") int id, GroupRest in, @Context Request request,
+ @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
@DELETE
@Path("{id}")
@@ -63,12 +65,6 @@ public interface GroupHandlerLocal {
@Context UriInfo uriInfo);
- @GET
- @Path("{id}/resource/{resourceId}")
- public Response getResource(@PathParam("id") int id, @PathParam("resourceId") int resourceId,
- @Context Request request, @Context HttpHeaders headers,
- @Context UriInfo uriInfo);
-
@PUT
@Path("{id}/resource/{resourceId}")
public Response addResource(@PathParam("id") int id, @PathParam("resourceId") int resourceId,
commit 6f207bc8f0ec6126d94342f4f76ae6817b426320
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Nov 14 21:36:05 2011 +0100
Improvements in group handling.
Make resource id an element and not an attribute.
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/index.html b/modules/enterprise/gui/rest-war/src/main/webapp/index.html
index 7c28583..76aa220 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/index.html
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/index.html
@@ -10,6 +10,7 @@ See also <a href="http://rhq-project.org/display/RHQ/Design-REST">the RHQ wiki</
mobile client (Android) of the API.
<ul>
<li><a href="1/resource/platforms.html">Platforms</a></li>
+ <li><a href="1/group/">Groups</a></li>
<li><a href="1/alert/">Alerts</a></li>
<li><a href="1/status.html">System status</a> </li>
</ul>
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 6f2c6b0..a227a18 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
@@ -15,7 +15,9 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
+import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
@@ -24,13 +26,14 @@ import javax.ws.rs.core.UriInfo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.rhq.core.domain.authz.Role;
+import org.rhq.core.domain.criteria.ResourceGroupCriteria;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.resource.group.ResourceGroupDeleteException;
import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.rest.domain.GroupRest;
+import org.rhq.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.ResourceWithType;
/**
@@ -49,15 +52,28 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
@EJB
ResourceManagerLocal resourceManager;
- @Override
- @GET
- @Path("/")
public Response getGroups(@Context Request request, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
- Set<Role> roles = caller.getRoles();
+ ResourceGroupCriteria criteria = new ResourceGroupCriteria();
+ List<ResourceGroup> groups = resourceGroupManager.findResourceGroupsByCriteria(caller,criteria);
+
+ List<GroupRest> list = new ArrayList<GroupRest>(groups.size());
+ for (ResourceGroup group : groups) {
+ list.add(fillGroup(group, uriInfo));
+ }
+
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+ Response.ResponseBuilder builder;
+
+ if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+ builder = Response.ok(renderTemplate("listGroup", list), mediaType);
+ }
+ else {
+ GenericEntity<List<GroupRest>> ret = new GenericEntity<List<GroupRest>>(list) {};
+ builder = Response.ok(ret);
+ }
-// resourceGroupManager.findAvailableResourceGroupsForRole(caller,roleId,new int[]{}, PageControl.SIZE_UNLIMITED);
- return null; // TODO
+ return builder.build();
}
@@ -69,8 +85,18 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
ResourceGroup group = fetchGroup(id);
- GroupRest groupRest = fillGroup(group);
- Response.ResponseBuilder builder = Response.ok(groupRest);
+ GroupRest groupRest = fillGroup(group, uriInfo);
+
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+
+ Response.ResponseBuilder builder;
+
+ if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+ builder = Response.ok(renderTemplate("group", groupRest), mediaType);
+ }
+ else {
+ builder = Response.ok(groupRest,mediaType);
+ }
return builder.build();
}
@@ -121,7 +147,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
@Override
@GET
@Path("{id}/resources") // TODO introduce paging through the list
- public List<ResourceWithType> getResources(@PathParam("id") int id, @Context Request request, @Context HttpHeaders headers,
+ public Response getResources(@PathParam("id") int id, @Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo) {
ResourceGroup resourceGroup = fetchGroup(id);
@@ -131,10 +157,19 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
for (Resource res: resources) {
rwtList.add(fillRWT(res,uriInfo));
}
- Response.ResponseBuilder builder = Response.ok(rwtList);
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+ Response.ResponseBuilder builder;
+
+ if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+ builder = Response.ok(renderTemplate("listResourceWithType", rwtList), mediaType);
+ }
+ else {
+ GenericEntity<List<ResourceWithType>> list = new GenericEntity<List<ResourceWithType>>(rwtList){};
+ builder = Response.ok(list);
+ }
+
+ return builder.build();
-// return builder.build();
- return rwtList;
}
@@ -200,10 +235,17 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
- private GroupRest fillGroup(ResourceGroup group) {
+ private GroupRest fillGroup(ResourceGroup group, UriInfo uriInfo) {
GroupRest gr = new GroupRest(group.getName());
+ gr.setId(group.getId());
gr.setCategory(group.getGroupCategory());
+ 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);
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 79052f5..6c91fbe 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
@@ -59,8 +59,8 @@ public interface GroupHandlerLocal {
@GET
@Path("{id}/resources")
- public List<ResourceWithType> getResources(@PathParam("id") int id,@Context Request request, @Context HttpHeaders headers,
- @Context UriInfo uriInfo);
+ public Response getResources(@PathParam("id") int id, @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
@GET
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 8b02ad8..f90143a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -34,6 +34,7 @@ import javax.interceptor.Interceptors;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
@@ -41,6 +42,8 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
+import com.arjuna.ats.internal.jdbc.drivers.modifiers.list;
+
import org.rhq.core.domain.alert.Alert;
import org.rhq.core.domain.criteria.AlertCriteria;
import org.rhq.core.domain.measurement.Availability;
@@ -145,7 +148,8 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
builder = Response.ok(renderTemplate("listResourceWithType", rwtList), mediaType);
}
else {
- builder = Response.ok(rwtList);
+ GenericEntity<List<ResourceWithType>> list = new GenericEntity<List<ResourceWithType>>(rwtList){};
+ builder = Response.ok(list);
}
return builder.build();
@@ -257,7 +261,8 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
builder = Response.ok(renderTemplate("listMetricSchedule", ret), mediaType);
}
else {
- builder = Response.ok(ret,mediaType);
+ GenericEntity<List<MetricSchedule>> list = new GenericEntity<List<MetricSchedule>>(ret){};
+ builder = Response.ok(list,mediaType);
}
return builder.build();
@@ -292,7 +297,8 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
builder = Response.ok(renderTemplate("listResourceWithType", rwtList), mediaType);
}
else {
- builder = Response.ok(rwtList);
+ GenericEntity<List<ResourceWithType>> list = new GenericEntity<List<ResourceWithType>>(rwtList){};
+ builder = Response.ok(list);
}
return builder.build();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java
index 3192ea2..c55223d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java
@@ -16,6 +16,7 @@ import org.rhq.core.domain.resource.group.GroupCategory;
public class GroupRest {
+ int id;
private String name;
private GroupCategory category;
@@ -28,6 +29,14 @@ public class GroupRest {
this.name = name;
}
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
public String getName() {
return name;
}
@@ -44,6 +53,7 @@ public class GroupRest {
this.category = category;
}
+ @XmlElementRef
public List<Link> getLinks() {
return links;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
index b7ee10a..132fc34 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
@@ -76,7 +76,6 @@ public class ResourceWithType {
this.resourceName = resourceName;
}
- @XmlAttribute
@XmlID
public String getResourceId() {
return String.valueOf(resourceId);
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
new file mode 100644
index 0000000..90bbfac
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl
@@ -0,0 +1,41 @@
+<#ftl >
+<#--
+/*
+ * 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.
+ */
+-->
+<#-- @ftlvariable name="var" type="org.rhq.enterprise.server.rest.domain.GroupRest" -->
+<html>
+ <table>
+ <thead>
+ <tr>
+ <td>Name</td><td>Value</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>Name</td><td>${var.name}</td>
+ </tr>
+ <tr>
+ <td>Id</td><td>${var.id}</td>
+ </tr>
+ <tr>
+ <td>Category</td><td>${var.category}</td>
+ </tr>
+ </table>
+ <a href="/rest/1/group/${var.id?c}/resources.html">Resources</a><br/>
+</html>
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/listGroup.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/listGroup.ftl
new file mode 100644
index 0000000..6f38801
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/listGroup.ftl
@@ -0,0 +1,32 @@
+<#ftl >
+<#--
+/*
+ * 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.
+ */
+-->
+<#-- @ftlvariable name="var" type="java.util.List<org.rhq.enterprise.server.rest.domain.GroupRest>" -->
+<html>
+<ul>
+ <#-- the next looks odd, but the incoming var is a list -->
+ <#list var as var>
+ <li>
+ <#include "group.ftl"/>
+ </li>
+ </#list>
+</ul>
+<html>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
index 9c3e435..f1ab4d2 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
@@ -2,7 +2,7 @@
<#--
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2011 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
commit 02a84e46915dfb47500233db99e534d4ef7973f8
Merge: a43fccf fdf91e1
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Nov 14 20:34:45 2011 +0100
Merge branch 'master' into feature/rest
commit a43fccf8118da8af2017933cbcbcd6733105b6fd
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Mon Nov 14 08:19:50 2011 +0100
Unify get schedules code, allow to limit the returned values to all,metric,trait
Fix return type for schedule update and only include the link to data for metric schedules.
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 f21a90c..8be8070 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
@@ -138,7 +138,7 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
builder = Response.ok(htmlString,mediaType);
}
else
- builder= Response.ok(res);
+ builder= Response.ok(res,mediaType);
builder.cacheControl(cc);
return builder.build();
@@ -178,8 +178,6 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
builder.cacheControl(cc);
return builder.build();
}
-
-
}
if (schedule==null) {
@@ -210,12 +208,17 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
if (builder==null) {
// preconditions not met, we need to send the resource
- // create link to metrics
- UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
- uriBuilder.path("metric/data/" + scheduleId);
- URI uri = uriBuilder.build();
- Link link = new Link("metrics",uri.toString());
- metricSchedule.addLink(link);
+ UriBuilder uriBuilder;
+ URI uri;
+ Link link;
+ if (definition.getDataType()==DataType.MEASUREMENT) {
+ // create link to metrics
+ uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("metric/data/" + scheduleId);
+ uri = uriBuilder.build();
+ link = new Link("metric",uri.toString());
+ metricSchedule.addLink(link);
+ }
// create link to the resource
uriBuilder = uriInfo.getBaseUriBuilder();
@@ -237,7 +240,7 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
builder = Response.ok(renderTemplate("metricSchedule", metricSchedule), mediaType);
}
else {
- builder = Response.ok(metricSchedule);
+ builder = Response.ok(metricSchedule,mediaType);
}
}
@@ -271,7 +274,7 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
}
@Override
- public MetricSchedule updateSchedule(int scheduleId, MetricSchedule in) {
+ public Response updateSchedule(int scheduleId, MetricSchedule in,HttpHeaders httpHeaders) {
if (in==null)
throw new StuffNotFoundException("Input is null"); // TODO other type of exception
if (in.getScheduleId()==null)
@@ -294,6 +297,6 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
MetricSchedule ret = new MetricSchedule(scheduleId,def.getName(),def.getDisplayName(),
schedule.isEnabled(),schedule.getInterval(),def.getUnits().toString(),def.getDataType().toString());
- return ret;
+ return Response.ok(ret,httpHeaders.getAcceptableMediaTypes().get(0)).build();
}
}
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 368ef36..44844ae 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
@@ -75,6 +75,6 @@ public interface MetricHandlerLocal {
@Path("/schedule/{id}")
@Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
- MetricSchedule updateSchedule(@PathParam("id") int scheduleId, MetricSchedule in);
+ Response updateSchedule(@PathParam("id") int scheduleId, MetricSchedule in,@Context HttpHeaders headers);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 4ae74f4..8b02ad8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -44,6 +44,7 @@ import javax.ws.rs.core.UriInfo;
import org.rhq.core.domain.alert.Alert;
import org.rhq.core.domain.criteria.AlertCriteria;
import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.measurement.DataType;
import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.measurement.MeasurementSchedule;
import org.rhq.core.domain.resource.InventoryStatus;
@@ -203,7 +204,15 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
return availabilityRest;
}
- public List<MetricSchedule> getSchedules(int resourceId, UriInfo uriInfo) {
+ public Response getSchedules(int resourceId,
+ String scheduleType,
+ @Context Request request,
+ @Context HttpHeaders headers,
+ @Context UriInfo uriInfo) {
+
+ // allow metric as input
+ if (scheduleType.equals("metric"))
+ scheduleType=DataType.MEASUREMENT.toString().toLowerCase();
Resource res = resMgr.getResource(caller, resourceId);
@@ -212,30 +221,46 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
for (MeasurementSchedule schedule : schedules) {
putToCache(schedule.getId(),MeasurementSchedule.class,schedule);
MeasurementDefinition definition = schedule.getDefinition();
- MetricSchedule ms = new MetricSchedule(schedule.getId(), definition.getName(), definition.getDisplayName(),
- schedule.isEnabled(),schedule.getInterval(), definition.getUnits().toString(),
- definition.getDataType().toString());
- UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
- uriBuilder.path("/metric/data/{id}");
- URI uri = uriBuilder.build(schedule.getId());
- Link metricLink = new Link("metric",uri.toString());
- ms.addLink(metricLink);
- // create link to the resource
- uriBuilder = uriInfo.getBaseUriBuilder();
- uriBuilder.path("resource/" + schedule.getResource().getId());
- uri = uriBuilder.build();
- Link link = new Link("resource",uri.toString());
- ms.addLink(link);
-
- ret.add(ms);
+
+ // user can opt to e.g. only get "measurement" or "trait" metrics
+
+ if ("all".equals(scheduleType) ||
+ scheduleType.toLowerCase().equals(definition.getDataType().toString().toLowerCase()) ) {
+ MetricSchedule ms = new MetricSchedule(schedule.getId(), definition.getName(), definition.getDisplayName(),
+ schedule.isEnabled(),schedule.getInterval(), definition.getUnits().toString(),
+ definition.getDataType().toString());
+ UriBuilder uriBuilder;
+ URI uri;
+ if (definition.getDataType()== DataType.MEASUREMENT) {
+ uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/metric/data/{id}");
+ uri = uriBuilder.build(schedule.getId());
+ Link metricLink = new Link("metric",uri.toString());
+ ms.addLink(metricLink);
+ }
+ // create link to the resource
+ uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("resource/" + schedule.getResource().getId());
+ uri = uriBuilder.build();
+ Link link = new Link("resource",uri.toString());
+ ms.addLink(link);
+
+ ret.add(ms);
+ }
}
- return ret;
- }
+ // What media type does the user request?
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+ Response.ResponseBuilder builder;
- public String getSchedulesHtml(int resourceId, UriInfo uriInfo) {
- List<MetricSchedule> list = getSchedules(resourceId, uriInfo);
- return renderTemplate("listMetricSchedule", list);
+ if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+ builder = Response.ok(renderTemplate("listMetricSchedule", ret), mediaType);
+ }
+ else {
+ builder = Response.ok(ret,mediaType);
+ }
+
+ return builder.build();
}
@Override
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 9d9a293..412b347 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
@@ -21,10 +21,12 @@ package org.rhq.enterprise.server.rest;
import java.util.List;
import javax.ejb.Local;
+import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
@@ -36,7 +38,6 @@ import org.jboss.resteasy.links.AddLinks;
import org.jboss.resteasy.links.LinkResource;
import org.jboss.resteasy.links.LinkResources;
-import org.rhq.core.domain.resource.Resource;
import org.rhq.enterprise.server.rest.domain.AvailabilityRest;
import org.rhq.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.MetricSchedule;
@@ -80,18 +81,13 @@ public interface ResourceHandlerLocal {
@GET
@Path("/{id}/schedules")
- @Produces({"application/json","application/xml"})
@LinkResource(rel="schedules",value = MetricSchedule.class)
- List<MetricSchedule> getSchedules(@PathParam("id") int resourceId,
+ Response getSchedules(@PathParam("id") int resourceId,
+ @QueryParam("type") @DefaultValue("all") String scheduleType,
+ @Context Request request,
+ @Context HttpHeaders headers,
@Context UriInfo uriInfo);
- @GET
- @Path("/{id}/schedules")
- @Produces("text/html")
- @LinkResource(rel="schedules",value = MetricSchedule.class)
- // TODO move to ScheduleManager, link from resource and pass the resource as query param
- String getSchedulesHtml(@PathParam("id") int resourceId,
- @Context UriInfo uriInfo);
@GET
@Path("/{id}/children")
commit 805c8af249272c4e93f06bb3710d74949ba5e6b3
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Sun Nov 13 22:53:54 2011 +0100
Update RESTeasy to 2.2.3
Start with Group related things
Use the jackson provider for nicer json
Cleanup getting the status
Fix compile errors
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
index 5d39d99..d607ea2 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
@@ -7,7 +7,7 @@
<context-param>
<param-name>resteasy.jndi.resources</param-name>
- <param-value>rhq/ResourceHandlerBean/local,rhq/MetricHandlerBean/local,rhq/UserHandlerBean/local,rhq/StatusHandlerBean/local,rhq/AlertHandlerBean/local,rhq/OperationsHandlerBean/local</param-value>
+ <param-value>rhq/ResourceHandlerBean/local,rhq/MetricHandlerBean/local,rhq/UserHandlerBean/local,rhq/StatusHandlerBean/local,rhq/AlertHandlerBean/local,rhq/OperationsHandlerBean/local,rhq/GroupHandlerBean/local</param-value>
<description>List of jndi names of EJBs local interfaces that define REST stuff</description>
</context-param>
<context-param>
@@ -22,7 +22,7 @@
</context-param>
<context-param>
<param-name>resteasy.media.type.mappings</param-name>
- <param-value>html : text/html, json : application/json, xml : application/xml</param-value>
+ <param-value>html : text/html, json : application/json, xml : application/xml, yaml: application/yaml</param-value>
</context-param>
<!--
diff --git a/modules/enterprise/server/container/pom.xml b/modules/enterprise/server/container/pom.xml
index e6fa762..4890488 100644
--- a/modules/enterprise/server/container/pom.xml
+++ b/modules/enterprise/server/container/pom.xml
@@ -117,18 +117,6 @@
<version>1.7.3</version>
</dependency>
- <dependency>
- <groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-jaxrs-all</artifactId>
- <scope>provided</scope>
- <version>${resteasy.version}</version>
- <type>pom</type>
- </dependency>
- <dependency>
- <groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-jettison-provider</artifactId>
- </dependency>
-
</dependencies>
<build>
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index a913b44..b792ab8 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -150,7 +150,7 @@
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-jettison-provider</artifactId>
+ <artifactId>resteasy-jackson-provider</artifactId>
<version>${resteasy.version}</version>
</dependency>
<dependency>
@@ -164,6 +164,32 @@
<version>${freemarker.version}</version>
<type>jar</type>
</dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-yaml-provider</artifactId>
+ <version>${resteasy.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.yaml</groupId>
+ <artifactId>snakeyaml</artifactId>
+ <version>1.8</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxb-provider</artifactId>
+ <version>${resteasy.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-impl</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.sun.xml.stream</groupId>
+ <artifactId>sjsxp</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
</dependencies>
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index 7206726..f14c91d 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -477,7 +477,7 @@
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
- <artifactId>resteasy-jettison-provider</artifactId>
+ <artifactId>resteasy-jackson-provider</artifactId>
<version>${resteasy.version}</version>
<scope>provided</scope> <!-- by container -->
</dependency>
@@ -488,6 +488,34 @@
<scope>provided</scope> <!-- by container -->
</dependency>
<dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-yaml-provider</artifactId>
+ <version>${resteasy.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxb-provider</artifactId>
+ <version>${resteasy.version}</version>
+ <scope>provided</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-impl</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.sun.xml.stream</groupId>
+ <artifactId>sjsxp</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.yaml</groupId>
+ <artifactId>snakeyaml</artifactId>
+ <version>1.8</version>
+ </dependency>
+ <dependency>
<groupId>org.jboss.el</groupId>
<artifactId>jboss-el</artifactId>
<version>2.0.1.GA</version>
@@ -806,7 +834,7 @@ Build-OS-Version=${os.version}
<property name="javadoc.outputDirectory" value="${javadoc.outputDirectory}" />
<property name="project.dir" value="./src/main/java/org/rhq/enterprise/server" />
<property name="maven.compile.classpath" refid="maven.compile.classpath" />
-
+
<mkdir dir="${javadoc.outputDirectory}/remote-api" />
<javadoc destdir="${javadoc.outputDirectory}/remote-api" author="false" version="true" windowtitle="RHQ ${project.version} Remote API" noindex="false">
<classpath>
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 124e12f..1be4db0 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
@@ -24,6 +24,7 @@ package org.rhq.enterprise.server.rest;
import java.io.IOException;
import java.io.StringWriter;
+import java.net.URI;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -31,6 +32,8 @@ import java.util.Set;
import javax.annotation.Resource;
import javax.ejb.Stateless;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
@@ -48,6 +51,9 @@ import org.jboss.cache.Node;
import org.jboss.cache.TreeCacheMBean;
import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.rest.domain.Link;
+import org.rhq.enterprise.server.rest.domain.ResourceWithType;
/**
* Abstract base class for EJB classes that implement REST methods.
@@ -227,4 +233,24 @@ public class AbstractRestBean {
}
return true;
}
+
+ public ResourceWithType fillRWT(org.rhq.core.domain.resource.Resource res, UriInfo uriInfo) {
+ ResourceType resourceType = res.getResourceType();
+ ResourceWithType rwt = new ResourceWithType(res.getName(),res.getId());
+ rwt.setTypeName(resourceType.getName());
+ rwt.setTypeId(resourceType.getId());
+ rwt.setPluginName(resourceType.getPlugin());
+ org.rhq.core.domain.resource.Resource parent = res.getParentResource();
+ if (parent!=null) {
+ rwt.setParentId(parent.getId());
+ }
+ UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/operation/definitions");
+ uriBuilder.queryParam("resourceId",res.getId());
+ URI uri = uriBuilder.build();
+ Link link = new Link("operationDefinitions",uri.toString());
+ rwt.addLink(link);
+
+ return rwt;
+ }
}
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
new file mode 100644
index 0000000..6f2c6b0
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
@@ -0,0 +1,210 @@
+package org.rhq.enterprise.server.rest;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+import javax.interceptor.Interceptors;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.domain.authz.Role;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.group.ResourceGroupDeleteException;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
+import org.rhq.enterprise.server.rest.domain.GroupRest;
+import org.rhq.enterprise.server.rest.domain.ResourceWithType;
+
+/**
+ * Deal with group related things.
+ * @author Heiko W. Rupp
+ */
+@Stateless
+(a)Interceptors(SetCallerInterceptor.class)
+public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLocal {
+
+ private final Log log = LogFactory.getLog(GroupHandlerBean.class);
+
+ @EJB
+ ResourceGroupManagerLocal resourceGroupManager;
+
+ @EJB
+ ResourceManagerLocal resourceManager;
+
+ @Override
+ @GET
+ @Path("/")
+ public Response getGroups(@Context Request request, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
+
+ Set<Role> roles = caller.getRoles();
+
+// resourceGroupManager.findAvailableResourceGroupsForRole(caller,roleId,new int[]{}, PageControl.SIZE_UNLIMITED);
+ return null; // TODO
+
+ }
+
+ @Override
+ @GET
+ @Path("{id}")
+ public Response getGroup(@PathParam("id") int id, @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo) {
+
+ ResourceGroup group = fetchGroup(id);
+
+ GroupRest groupRest = fillGroup(group);
+ Response.ResponseBuilder builder = Response.ok(groupRest);
+
+ return builder.build();
+ }
+
+ @Override
+ @POST
+ @Path("/")
+ public Response createGroup(ResourceGroup group, @Context Request request, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
+
+ Response.ResponseBuilder builder;
+ try {
+ ResourceGroup newGroup = resourceGroupManager.createResourceGroup(caller,group);
+ UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/group/{id}");
+ URI uri = uriBuilder.build(newGroup.getId());
+
+ builder=Response.created(uri);
+ } catch (Exception e) {
+ e.printStackTrace(); // TODO: Customise this generated block
+ builder=Response.serverError();
+ }
+ return builder.build();
+ }
+
+ @Override
+ @PUT
+ @Path("{id}")
+ public Response updateGroup(@PathParam("id") int id, @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo) {
+ return null; // TODO: Customise this generated block
+ }
+
+ @Override
+ @DELETE
+ @Path("{id}")
+ public Response deleteGroup(@PathParam("id") int id, @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo) {
+
+ try {
+ resourceGroupManager.deleteResourceGroup(caller,id);
+ return Response.ok().build();
+ } catch (ResourceGroupDeleteException e) {
+ e.printStackTrace(); // TODO: Customise this generated block
+ return Response.serverError().build(); // TODO what exactly ?
+ }
+ }
+
+ @Override
+ @GET
+ @Path("{id}/resources") // TODO introduce paging through the list
+ public List<ResourceWithType> getResources(@PathParam("id") int id, @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo) {
+
+ ResourceGroup resourceGroup = fetchGroup(id);
+
+ Set<Resource> resources = resourceGroup.getExplicitResources();
+ List<ResourceWithType> rwtList = new ArrayList<ResourceWithType>(resources.size());
+ for (Resource res: resources) {
+ rwtList.add(fillRWT(res,uriInfo));
+ }
+ Response.ResponseBuilder builder = Response.ok(rwtList);
+
+// return builder.build();
+ return rwtList;
+ }
+
+
+ @Override
+ @GET
+ @Path("{id}/resource/{resourceId}")
+ public Response getResource(@PathParam("id") int id, @PathParam("resourceId") int resourceId,
+ @Context Request request, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
+
+
+
+ return null; // TODO: Customise this generated block
+ }
+
+ @Override
+ @PUT
+ @Path("{id}/resource/{resourceId}")
+ public Response addResource(@PathParam("id") int id, @PathParam("resourceId") int resourceId,
+ @Context Request request, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
+
+ ResourceGroup resourceGroup = fetchGroup(id);
+ Resource res = resourceManager.getResource(caller,resourceId);
+ if (res==null)
+ throw new StuffNotFoundException("Resource with id " + resourceId);
+
+ // TODO do we want/ need to check that the group category stays the same?
+
+ resourceGroup.addExplicitResource(res);
+
+ return Response.ok().build(); // TODO right code?
+
+ }
+
+ @Override
+ @DELETE
+ @Path("{id}/resource/{resourceId}")
+ public Response removeResource(@PathParam("id") int id, @PathParam("resourceId") int resourceId,
+ @Context Request request, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
+
+ ResourceGroup resourceGroup = fetchGroup(id);
+ Resource res = resourceManager.getResource(caller,resourceId);
+ if (res==null)
+ throw new StuffNotFoundException("Resource with id " + resourceId);
+
+ resourceGroup.removeExplicitResource(res);
+
+ return Response.ok().build(); // TODO right code?
+
+ }
+
+ /**
+ * 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 = resourceGroupManager.getResourceGroup(caller, groupId);
+ if (resourceGroup==null)
+ throw new StuffNotFoundException("Group with id " + groupId);
+ return resourceGroup;
+ }
+
+
+
+ private GroupRest fillGroup(ResourceGroup group) {
+
+ GroupRest gr = new GroupRest(group.getName());
+ gr.setCategory(group.getGroupCategory());
+
+ 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
new file mode 100644
index 0000000..79052f5
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java
@@ -0,0 +1,83 @@
+package org.rhq.enterprise.server.rest;
+
+import java.util.List;
+
+import javax.ejb.Local;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.enterprise.server.rest.domain.ResourceWithType;
+
+/**
+ * Handler for Group related things
+ * @author Heiko W. Rupp
+ */
+@Local
+@Path("/group/")
+(a)Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML, "application/yaml"})
+public interface GroupHandlerLocal {
+
+ @GET
+ @Path("/")
+ public Response getGroups(@Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
+
+ @GET
+ @Path("{id}")
+ public Response getGroup(@PathParam("id") int id,@Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
+
+
+ @POST
+ @Path("/")
+ public Response createGroup(ResourceGroup group, @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
+
+ @PUT
+ @Path("{id}")
+ public Response updateGroup(@PathParam("id") int id,@Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
+
+ @DELETE
+ @Path("{id}")
+ public Response deleteGroup(@PathParam("id") int id,@Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
+
+
+ @GET
+ @Path("{id}/resources")
+ public List<ResourceWithType> getResources(@PathParam("id") int id,@Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
+
+
+ @GET
+ @Path("{id}/resource/{resourceId}")
+ public Response getResource(@PathParam("id") int id, @PathParam("resourceId") int resourceId,
+ @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
+
+ @PUT
+ @Path("{id}/resource/{resourceId}")
+ public Response addResource(@PathParam("id") int id, @PathParam("resourceId") int resourceId,
+ @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
+
+ @DELETE
+ @Path("{id}/resource/{resourceId}")
+ public Response removeResource(@PathParam("id") int id, @PathParam("resourceId") int resourceId,
+ @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
+}
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 46a7f86..5ab7366 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
@@ -19,8 +19,6 @@ import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
-import org.jboss.resteasy.annotations.providers.jaxb.Wrapped;
-
import org.rhq.enterprise.server.rest.domain.OperationDefinitionRest;
import org.rhq.enterprise.server.rest.domain.OperationRest;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index e656c24..4ae74f4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -49,7 +49,6 @@ import org.rhq.core.domain.measurement.MeasurementSchedule;
import org.rhq.core.domain.resource.InventoryStatus;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceCategory;
-import org.rhq.core.domain.resource.ResourceType;
import org.rhq.enterprise.server.alert.AlertManagerLocal;
import org.rhq.enterprise.server.rest.domain.AvailabilityRest;
import org.rhq.enterprise.server.rest.domain.Link;
@@ -204,26 +203,6 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
return availabilityRest;
}
- private ResourceWithType fillRWT(Resource res, UriInfo uriInfo) {
- ResourceType resourceType = res.getResourceType();
- ResourceWithType rwt = new ResourceWithType(res.getName(),res.getId());
- rwt.setTypeName(resourceType.getName());
- rwt.setTypeId(resourceType.getId());
- rwt.setPluginName(resourceType.getPlugin());
- Resource parent = res.getParentResource();
- if (parent!=null) {
- rwt.setParentId(parent.getId());
- }
- UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
- uriBuilder.path("/operation/definitions");
- uriBuilder.queryParam("resourceId",res.getId());
- URI uri = uriBuilder.build();
- Link link = new Link("operationDefinitions",uri.toString());
- rwt.addLink(link);
-
- return rwt;
- }
-
public List<MetricSchedule> getSchedules(int resourceId, UriInfo uriInfo) {
Resource res = resMgr.getResource(caller, resourceId);
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 d1cb0f2..9d9a293 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
@@ -36,6 +36,7 @@ import org.jboss.resteasy.links.AddLinks;
import org.jboss.resteasy.links.LinkResource;
import org.jboss.resteasy.links.LinkResources;
+import org.rhq.core.domain.resource.Resource;
import org.rhq.enterprise.server.rest.domain.AvailabilityRest;
import org.rhq.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.MetricSchedule;
@@ -46,7 +47,7 @@ import org.rhq.enterprise.server.rest.domain.ResourceWithType;
* Interface class that describes the REST interface
* @author Heiko W. Rupp
*/
-@Produces({"application/json","application/xml","text/html"})
+(a)Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
@Path("/resource")
@Local
public interface ResourceHandlerLocal {
@@ -57,13 +58,12 @@ public interface ResourceHandlerLocal {
})
@GET
@Path("/{id}")
- @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
+
Response getResource(@PathParam("id") int id, @Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo);
@GET
@Path("/platforms")
- @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
Response getPlatforms(@Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo);
@@ -95,7 +95,6 @@ public interface ResourceHandlerLocal {
@GET
@Path("/{id}/children")
- @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
@LinkResource(rel="children", value = ResourceWithType.class)
Response getChildren(@PathParam("id") int id, @Context Request request, @Context HttpHeaders headers,
@Context UriInfo uriInfo);
@@ -104,7 +103,6 @@ public interface ResourceHandlerLocal {
@AddLinks
@GET
@Path(("/{id}/alerts"))
-// @LinkResource(rel="alerts", value = AlertRest.class)
List<Link> getAlertsForResource(@PathParam("id") int resourceId); // TODO paging + status
}
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 cd68a72..0f2a0ed 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
@@ -21,13 +21,12 @@ package org.rhq.enterprise.server.rest;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
+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.content.composite.PackageListItemComposite;
import org.rhq.core.domain.criteria.AlertCriteria;
import org.rhq.core.domain.criteria.AlertDefinitionCriteria;
import org.rhq.core.domain.criteria.Criteria;
@@ -60,7 +59,7 @@ public class StatusHandlerBean extends AbstractRestBean implements StatusHandler
AlertDefinitionManagerLocal alertDefinitionManager;
@Override
- public Status getStatus() {
+ public Response getStatus(HttpHeaders httpHeaders) {
Status status = new Status();
@@ -94,12 +93,15 @@ public class StatusHandlerBean extends AbstractRestBean implements StatusHandler
status.setMetricsMin(scheduleManager.getScheduledMeasurementsPerMinute());
- return status;
- }
+ MediaType mediaType = httpHeaders.getAcceptableMediaTypes().get(0);
+ Response.ResponseBuilder builder;
+ if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+ String htmlString = renderTemplate("status",status);
+ builder = Response.ok(htmlString,mediaType);
+ } else {
+ builder = Response.ok(status, httpHeaders.getAcceptableMediaTypes().get(0));
+ }
- @Override
- public String getStatusHtml() {
- Status status = getStatus();
- return renderTemplate("status",status);
+ return builder.build();
}
}
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 5e1c3f4..838fbad 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
@@ -22,8 +22,9 @@ import javax.ejb.Local;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
-
-import org.rhq.enterprise.server.rest.domain.Status;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
/**
* Return some status information about the system
@@ -36,11 +37,5 @@ public interface StatusHandlerLocal {
@GET
@Path("/")
- @Produces({"application/json","application/xml"})
- Status getStatus();
-
- @GET
- @Path("/")
- @Produces("text/html")
- String getStatusHtml();
+ Response getStatus(@Context HttpHeaders httpHeaders);
}
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 d8b0c39..b644cd6 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
@@ -32,10 +32,13 @@ import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
+import javax.ws.rs.core.UriInfo;
import org.rhq.core.domain.configuration.Configuration;
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.rest.domain.ResourceWithType;
/**
@@ -66,15 +69,20 @@ public class UserHandlerBean extends AbstractRestBean implements UserHandlerLoca
@EJB
ResourceHandlerLocal resourceHandler;
+ @EJB
+ ResourceManagerLocal resourceManager;
+
@Override
@GET
@Path("favorites/r")
- public List<ResourceWithType> getFavorites() {
+ public List<ResourceWithType> getFavorites(UriInfo uriInfo) {
Set<Integer> favIds = getResourceIdsForFavorites();
List<ResourceWithType> ret = new ArrayList<ResourceWithType>();
for (Integer id : favIds) {
- ResourceWithType rwt = resourceHandler.getResource(id);
+ Resource res = resourceManager.getResource(caller,id);
+
+ ResourceWithType rwt = fillRWT(res,uriInfo);
ret.add(rwt);
}
return ret;
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 f80eb9e..9073f32 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
@@ -28,6 +28,8 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
import org.rhq.enterprise.server.rest.domain.ResourceWithType;
@@ -42,7 +44,7 @@ public interface UserHandlerLocal {
@GET
@Path("favorites/resource")
- public List<ResourceWithType> getFavorites();
+ public List<ResourceWithType> getFavorites(@Context UriInfo uriInfo);
@PUT
@Path("favorites/resource/{id}")
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java
index 073cab8..f8d1f88 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java
@@ -24,8 +24,6 @@ import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlRootElement;
-import org.jboss.resteasy.annotations.providers.jaxb.json.Mapped;
-import org.jboss.resteasy.annotations.providers.jaxb.json.XmlNsMap;
import org.jboss.resteasy.links.RESTServiceDiscovery;
import org.jboss.resteasy.spi.touri.URITemplate;
@@ -35,7 +33,6 @@ import org.jboss.resteasy.spi.touri.URITemplate;
*/
@URITemplate("/alert/definition/{id}")
@XmlRootElement
-@Mapped(namespaceMap = @XmlNsMap(jsonName = "atom", namespace = "http://www.w3.org/2005/Atom"))
public class AlertDefinitionRest {
int id;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertRest.java
index c540434..90fe925 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertRest.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertRest.java
@@ -26,8 +26,6 @@ import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlRootElement;
-import org.jboss.resteasy.annotations.providers.jaxb.json.Mapped;
-import org.jboss.resteasy.annotations.providers.jaxb.json.XmlNsMap;
import org.jboss.resteasy.links.AddLinks;
import org.jboss.resteasy.links.LinkResource;
import org.jboss.resteasy.links.RESTServiceDiscovery;
@@ -39,9 +37,7 @@ import org.jboss.resteasy.spi.touri.URITemplate;
*/
@URITemplate("/alert/{id}")
@XmlRootElement
-//@XmlType(propOrder = {"id","name","alertTime","description","alertDefinitionId","definitionEnabled","resourceId","resourceName","ackBy","ackTime","rest"})
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
-@Mapped(namespaceMap = @XmlNsMap(jsonName = "atom", namespace = "http://www.w3.org/2005/Atom"))
public class AlertRest {
private int id;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AvailabilityRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AvailabilityRest.java
index a0763dd..9f64f4b 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AvailabilityRest.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AvailabilityRest.java
@@ -22,8 +22,6 @@ import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
-import org.jboss.resteasy.annotations.providers.jaxb.json.Mapped;
-import org.jboss.resteasy.annotations.providers.jaxb.json.XmlNsMap;
import org.jboss.resteasy.links.RESTServiceDiscovery;
import org.rhq.core.domain.measurement.AvailabilityType;
@@ -33,7 +31,6 @@ import org.rhq.core.domain.measurement.AvailabilityType;
* @author Heiko W. Rupp
*/
@XmlRootElement(name = "availability")
-@Mapped(namespaceMap = @XmlNsMap(jsonName = "atom", namespace = "http://www.w3.org/2005/Atom"))
public class AvailabilityRest {
long since;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java
new file mode 100644
index 0000000..3192ea2
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java
@@ -0,0 +1,54 @@
+package org.rhq.enterprise.server.rest.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.rhq.core.domain.resource.group.GroupCategory;
+
+/**
+ * Representation of a resource group
+ * @author Heiko W. Rupp
+ */
+@XmlRootElement
+public class GroupRest {
+
+
+ private String name;
+ private GroupCategory category;
+
+ List<Link> links = new ArrayList<Link>();
+
+ public GroupRest() {
+ }
+
+ public GroupRest(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public GroupCategory getCategory() {
+ return category;
+ }
+
+ public void setCategory(GroupCategory category) {
+ this.category = category;
+ }
+
+ public List<Link> getLinks() {
+ return links;
+ }
+
+ public void setLinks(List<Link> links) {
+ this.links = links;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java
index 4333530..30a006b 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java
@@ -27,8 +27,6 @@ import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
-import org.jboss.resteasy.annotations.providers.jaxb.json.Mapped;
-import org.jboss.resteasy.annotations.providers.jaxb.json.XmlNsMap;
import org.jboss.resteasy.spi.touri.URITemplate;
/**
@@ -36,8 +34,6 @@ import org.jboss.resteasy.spi.touri.URITemplate;
* @author Heiko W. Rupp
*/
@XmlRootElement
-//@XmlType(propOrder = {"scheduleId","scheduleName","displayName","enabled","collectionInterval","unit","type"})
-@Mapped(namespaceMap = @XmlNsMap(jsonName = "atom", namespace = "http://www.w3.org/2005/Atom"))
@URITemplate("/metric/schedule/{id}")
public class MetricSchedule {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
index 1e5971c..b7ee10a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
@@ -33,19 +33,17 @@ import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlRootElement;
-import org.jboss.resteasy.annotations.providers.jaxb.json.Mapped;
-import org.jboss.resteasy.annotations.providers.jaxb.json.XmlNsMap;
import org.jboss.resteasy.spi.touri.URITemplate;
/**
* A (partial) resource with some type information
* @author Heiko W. Rupp
*/
-@Mapped(namespaceMap = @XmlNsMap(jsonName = "atom", namespace = "http://www.w3.org/2005/Atom"))
@XmlRootElement
+/*
@XmlAccessorType(XmlAccessType.NONE)
-//@XmlType(propOrder = {"resourceId","resourceName","parentId","parentName","typeId","typeName","pluginId","pluginName","rest"})
@URITemplate("{id}")
+*/
public class ResourceWithType {
String resourceName;
diff --git a/pom.xml b/pom.xml
index 9eae894..c01cf60 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.2.2.GA</resteasy.version>
+ <resteasy.version>2.2.3.GA</resteasy.version>
<freemarker.version>2.3.18</freemarker.version>
<rhq.db.admin.username>rhqadmin</rhq.db.admin.username>
commit e23db61ad37d962ce5ba746a2864854d1ce4fc78
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Sat Nov 5 21:40:57 2011 +0100
More REST work, consisting of:
Introduce a cache (at the moment for schedules) to reduce database load.
Map the cache int JNDI and have it injected by the container.
Check the caller when accessing cache entries, so that only entries are returned that the caller has access to.
Clean up some methods, add support for links to operation definitions for resources.
First cut at triggering operations.
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
index 9652232..5d39d99 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
@@ -7,7 +7,7 @@
<context-param>
<param-name>resteasy.jndi.resources</param-name>
- <param-value>rhq/ResourceHandlerBean/local,rhq/MetricHandlerBean/local,rhq/UserHandlerBean/local,rhq/StatusHandlerBean/local,rhq/AlertHandlerBean/local</param-value>
+ <param-value>rhq/ResourceHandlerBean/local,rhq/MetricHandlerBean/local,rhq/UserHandlerBean/local,rhq/StatusHandlerBean/local,rhq/AlertHandlerBean/local,rhq/OperationsHandlerBean/local</param-value>
<description>List of jndi names of EJBs local interfaces that define REST stuff</description>
</context-param>
<context-param>
@@ -64,6 +64,7 @@
<web-resource-collection>
<web-resource-name>REST</web-resource-name>
<url-pattern>/*</url-pattern>
+<!--
<http-method>DELETE</http-method>
<http-method>PUT</http-method>
<http-method>HEAD</http-method>
@@ -71,6 +72,7 @@
<http-method>TRACE</http-method>
<http-method>GET</http-method>
<http-method>POST</http-method>
+-->
</web-resource-collection>
<auth-constraint>
<role-name>all</role-name>
diff --git a/modules/enterprise/server/container/src/main/resources/jbossas/server/default/deploy/rhq-cache-service.xml b/modules/enterprise/server/container/src/main/resources/jbossas/server/default/deploy/rhq-cache-service.xml
new file mode 100644
index 0000000..f458a8e
--- /dev/null
+++ b/modules/enterprise/server/container/src/main/resources/jbossas/server/default/deploy/rhq-cache-service.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<server>
+
+ <mbean code="org.jboss.cache.TreeCache"
+ name="rhq.cache:service=cache">
+ <depends>jboss:service=TransactionManager</depends>
+
+ <!-- Configure the TransactionManager -->
+ <attribute name="TransactionManagerLookupClass">org.jboss.cache.JBossTransactionManagerLookup</attribute>
+
+ <!-- Isolation level : SERIALIZABLE
+ REPEATABLE_READ (default)
+ READ_COMMITTED
+ READ_UNCOMMITTED
+ NONE
+ -->
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!--
+ Node locking scheme:
+ OPTIMISTIC
+ PESSIMISTIC (default)
+ -->
+ <attribute name="NodeLockingScheme">OPTIMISTIC</attribute>
+
+ <!-- Valid modes are LOCAL, REPL_ASYNC and REPL_SYNC -->
+ <attribute name="CacheMode">REPL_ASYNC</attribute>
+
+ <!-- Just used for async repl: use a replication queue -->
+ <attribute name="UseReplQueue">false</attribute>
+
+ <!-- Replication interval for replication queue (in ms) -->
+ <attribute name="ReplQueueInterval">100</attribute>
+
+ <!-- Max number of elements which trigger replication -->
+ <attribute name="ReplQueueMaxElements">10</attribute>
+
+
+ <!-- Name of cluster. Needs to be the same for all clusters, in order
+ to find each other
+ -->
+ <attribute name="ClusterName">${jboss.partition.name:DefaultPartition}-RHQ-Cache</attribute>
+
+ <!-- JGroups protocol stack properties. Can also be a URL,
+ e.g. file:/home/bela/default.xml
+ <attribute name="ClusterProperties"></attribute>
+ -->
+ <attribute name="ClusterConfig">
+
+ <config>
+ <!-- UDP: if you have a multihomed machine,
+ set the bind_addr attribute to the appropriate NIC IP address, e.g bind_addr="192.168.0.2"
+ -->
+ <!-- UDP: On Windows machines, because of the media sense feature
+ being broken with multicast (even after disabling media sense)
+ set the loopback attribute to true
+
+ TODO need to parametrize and add to installer
+
+ -->
+ <UDP
+ mcast_addr="${jgroups.udp.mcast_addr:230.1.2.3}"
+ mcast_port="${jboss.alertcachepartition.mcast_port:48899}"
+ ip_ttl="${jgroups.udp.ip_ttl:2}"
+ bind_addr="${jgroups.bind_addr}"
+ ip_mcast="true"
+ tos="8"
+ mcast_send_buf_size="150000"
+ mcast_recv_buf_size="80000"
+ ucast_send_buf_size="150000"
+ ucast_recv_buf_size="80000"
+ loopback="${rhq.server.startup.partition.udpLoopback:false}" />
+ <PING timeout="2000"
+ num_initial_members="3"
+ up_thread="false"
+ down_thread="false" />
+ <MERGE2 min_interval="10000"
+ max_interval="20000" />
+ <FD_SOCK />
+ <VERIFY_SUSPECT timeout="1500"
+ up_thread="false"
+ down_thread="false" />
+ <pbcast.NAKACK gc_lag="50"
+ retransmit_timeout="600,1200,2400,4800"
+ max_xmit_size="8192"
+ up_thread="false"
+ down_thread="false" />
+ <UNICAST timeout="600,1200,2400"
+ down_thread="false" />
+ <pbcast.STABLE desired_avg_gossip="20000"
+ up_thread="false"
+ down_thread="false" />
+ <FRAG frag_size="8192" down_thread="false"
+ up_thread="false" />
+ <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
+ shun="true" print_local_addr="true" />
+ <pbcast.STATE_TRANSFER up_thread="true" down_thread="true" />
+ </config>
+ </attribute>
+
+ <!-- Whether or not to fetch state on joining a cluster -->
+ <attribute name="FetchStateOnStartup">true</attribute>
+
+ <!-- The max amount of time (in milliseconds) we wait until the
+ initial state (ie. the contents of the cache) are retrieved from
+ existing members in a clustered environment
+
+ -->
+ <attribute name="InitialStateRetrievalTimeout">5000</attribute>
+
+ <!-- Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">15000</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">10000</attribute>
+
+ <attribute name="EvictionPolicyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Specific eviction policy configurations. This is LRU -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <attribute name="maxNodes">5000</attribute>
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ </region>
+ <region name="/schedules">
+ <attribute name="maxNodes">5000</attribute>
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ </region>
+ <region name="/org/jboss/test/data">
+ <attribute name="maxNodes">5</attribute>
+ <attribute name="timeToLiveSeconds">4</attribute>
+ </region>
+ <region name="/test/">
+ <attribute name="maxNodes">10000</attribute>
+ <attribute name="timeToLiveSeconds">5</attribute>
+ </region>
+ <region name="/maxAgeTest/">
+ <attribute name="maxNodes">10000</attribute>
+ <attribute name="timeToLiveSeconds">8</attribute>
+ <attribute name="maxAgeSeconds">10</attribute>
+ </region>
+ </config>
+ </attribute>
+ </mbean>
+
+
+ <!-- Map the cache into JNDI -->
+ <mbean
+ code="org.jboss.invocation.jrmp.server.JRMPProxyFactory"
+ name="mydomain:service=proxyFactory,type=jrmp,target=factory">
+ <attribute name="InvokerName">jboss:service=invoker,type=jrmp</attribute>
+ <attribute name="TargetName">rhq.cache:service=cache</attribute>
+ <attribute name="JndiName">RhqCache</attribute>
+ <attribute name="InvokeTargetMethod">true</attribute>
+ <attribute name="ExportedInterface">org.jboss.cache.TreeCacheMBean</attribute>
+ <attribute name="ClientInterceptors">
+ <iterceptors>
+ <interceptor>org.jboss.proxy.ClientMethodInterceptor</interceptor>
+ <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
+ <interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>
+ </iterceptors>
+ </attribute>
+ <depends>jboss:service=invoker,type=jrmp</depends>
+ <depends>rhq.cache:service=cache</depends>
+ </mbean>
+</server>
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 d1d3c89..124e12f 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
@@ -25,7 +25,12 @@ package org.rhq.enterprise.server.rest;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.ejb.Stateless;
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
@@ -37,12 +42,20 @@ import freemarker.template.TemplateException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.TreeCacheMBean;
+
import org.rhq.core.domain.auth.Subject;
/**
* Abstract base class for EJB classes that implement REST methods.
+ * For the cache and its evicion policies see rhq-cache-service.xml
* @author Heiko W. Rupp
*/
+@Stateless
+@Resource(name="cache",type= TreeCacheMBean.class,mappedName = "RhqCache")
public class AbstractRestBean {
Log log = LogFactory.getLog(getClass().getName());
@@ -50,6 +63,10 @@ public class AbstractRestBean {
/** Subject of the caller that gets injected via {@link SetCallerInterceptor} */
Subject caller;
+ /** The cache to use */
+ @Resource(name="cache")
+ TreeCacheMBean treeCache;
+
/**
* Renders the passed object with the help of a freemarker template into a string. Freemarket templates
* are searched in the class path in a directory called "/rest_templates". In the usual Maven tree structure,
@@ -92,4 +109,122 @@ public class AbstractRestBean {
}
return null;
}
+
+ /**
+ * Retrieve an object from the cache. This is identified by its class and id
+ * @param id Id of the object to load.
+ * @param clazz Wanted return type
+ * @return Object if found and the caller has access to it.
+ * @see #getFqn(int, Class)
+ */
+ protected <T>T getFromCache(int id,Class<T> clazz) {
+ Fqn fqn = getFqn(id, clazz);
+ return getFromCache(fqn,clazz);
+ }
+
+
+ /**
+ * Retrieve an object from the cache if present or null otherwise.
+ * We need to be careful here as we must not return objects the current
+ * caller has no access to. We do this by checking the "readers" attribute
+ * of the selected node to see if the caller has put the object there
+ * @param fqn FullyQualified name (=path in cache) ot the object to retrieve
+ * @param clazz Return type
+ * @return The desired object if found and valid for the current caller. Null otherwise.
+ * @see #putToCache(org.jboss.cache.Fqn, Object)
+ */
+ @SuppressWarnings("unchecked")
+ protected <T>T getFromCache(Fqn fqn,Class<T> clazz) {
+ Object o=null;
+ if (treeCache.exists(fqn)) {
+ log.info("Hit for " + fqn.toString());
+ try{
+ Node n = treeCache.get(fqn);
+ Set<Integer> readers= (Set<Integer>) n.get("readers");
+ if (readers.contains(caller.getId())) {
+ o = n.get("item");
+ }
+ else {
+ log.info("No object for caller " +caller.toString() + " found");
+ }
+ } catch (CacheException e) {
+ e.printStackTrace(); // TODO: Customise this generated block
+ log.info("Miss for " + fqn.toString());
+ }
+ }
+ return (T)o;
+ }
+
+ /**
+ * Put an object into the cache. We need to record the caller so that we can later
+ * check if the caller can access that object or not.
+ * @param fqn Fully qualified name (=path to object)
+ * @param o Object to put
+ * @return true if put was successful
+ * @see #getFromCache(org.jboss.cache.Fqn, Class)
+ */
+ @SuppressWarnings("unchecked")
+ protected <T>boolean putToCache(Fqn fqn,T o) {
+ boolean success = false;
+ try {
+ Set<Integer> readers;
+ if (treeCache.exists(fqn)) {
+ Node n = treeCache.get(fqn);
+ readers = (Set<Integer>) n.get("readers");
+ } else {
+ readers = new HashSet<Integer>();
+ }
+ readers.add(caller.getId());
+ treeCache.put(fqn,"readers",readers);
+ treeCache.put(fqn,"item",o);
+ success = true;
+ log.info("Put " + fqn);
+ } catch (CacheException e) {
+ e.printStackTrace(); // TODO: Customise this generated block
+ }
+ return success;
+ }
+
+ /**
+ * Put an object into the cache identified by its type and id
+ * @param id Id of the object to put
+ * @param clazz Type to put in
+ * @param o Object to put
+ * @return true if put was successful
+ * @see #putToCache(org.jboss.cache.Fqn, Object)
+ */
+ protected <T>boolean putToCache(int id,Class<T> clazz,T o) {
+ Fqn fqn = getFqn(id, clazz);
+ return putToCache(fqn,o);
+ }
+
+ /**
+ * Construct a Fqn object from the passed data
+ * @param id Id of the target object
+ * @param clazz Type of object for that node
+ * @return Fqn object
+ */
+ protected <T> Fqn getFqn(int id, Class<T> clazz) {
+ return new Fqn(new Object[]{clazz.getName(), String.valueOf(id)});
+ }
+
+ /**
+ * Remove an item from the cache
+ * @param operationId Id of the item
+ * @param clazz Type of object for that node
+ * @return true if object is no longer in cache
+ */
+ protected <T> boolean removeFromCache(int operationId, Class<T> clazz) {
+ Fqn fqn = getFqn(operationId,clazz);
+ if (treeCache.exists(fqn)) {
+ try {
+ treeCache.remove(fqn);
+ log.info("Cancel " + fqn);
+ return true;
+ } catch (CacheException e) {
+ return false;
+ }
+ }
+ return true;
+ }
}
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 9908b7d..f21a90c 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
@@ -36,6 +36,8 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
+import org.jboss.cache.Fqn;
+
import org.rhq.core.domain.measurement.DataType;
import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.measurement.MeasurementSchedule;
@@ -80,7 +82,17 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
}
- MeasurementSchedule schedule = scheduleManager.getScheduleById(caller,scheduleId);
+ MeasurementSchedule schedule;
+ schedule = getFromCache(scheduleId,MeasurementSchedule.class);
+ if (schedule==null) {
+ schedule = scheduleManager.getScheduleById(caller,scheduleId);
+ if (schedule==null) {
+ throw new StuffNotFoundException("Schedule with id " + scheduleId);
+ }
+ else
+ putToCache(scheduleId,MeasurementSchedule.class,schedule);
+ }
+
if (schedule.getDefinition().getDataType()!= DataType.MEASUREMENT)
throw new IllegalArgumentException("Schedule [" + scheduleId + "] is not a (numerical) metric");
@@ -140,14 +152,43 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
* @param scheduleId ID of the schedule
* @param request the REST request - injected by the REST framework
* @param headers the REST request http headers - injected by the REST framework
- * @param uriInfo
+ * @param uriInfo info about the called uri to build links
* @return Schedule with respective headers
*/
public Response getSchedule(int scheduleId, Request request, HttpHeaders headers, UriInfo uriInfo) {
- MeasurementSchedule schedule = scheduleManager.getScheduleById(caller, scheduleId);
- if (schedule==null)
- throw new StuffNotFoundException("Schedule with id " + scheduleId);
+ MeasurementSchedule schedule=null;
+ Response.ResponseBuilder builder=null;
+
+ // Create a cache control
+ CacheControl cc = new CacheControl();
+ cc.setMaxAge(300); // Schedules are valid for 5 mins
+ cc.setPrivate(false); // Proxies may cache this
+
+
+ Fqn fqn = getFqn(scheduleId,MeasurementSchedule.class);
+ schedule = getFromCache(fqn,MeasurementSchedule.class);
+ if (schedule!=null) {
+ // If it is on cache, quickly return if match
+ long tim = schedule.getMtime() != null ? schedule.getMtime() : 0;
+ EntityTag eTag = new EntityTag(Long.toOctalString(schedule.hashCode()+tim)); // factor in mtime in etag
+ builder = request.evaluatePreconditions(new Date(tim),eTag);
+
+ if (builder!=null) {
+ builder.cacheControl(cc);
+ return builder.build();
+ }
+
+
+ }
+
+ if (schedule==null) {
+ schedule = scheduleManager.getScheduleById(caller, scheduleId);
+ if (schedule==null)
+ throw new StuffNotFoundException("Schedule with id " + scheduleId);
+ else
+ putToCache(fqn,schedule);
+ }
MeasurementDefinition definition = schedule.getDefinition();
MetricSchedule metricSchedule = new MetricSchedule(schedule.getId(), definition.getName(),
@@ -157,14 +198,14 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
if (schedule.getMtime()!=null)
metricSchedule.setMtime(schedule.getMtime());
- // What media type does the user request?
- MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
- // Check for conditional get
+ // Check for conditional get again
// Interestingly computing the hashCode of the original schedule is slower, as it also
// pulls in data from the definition and the resource
- EntityTag eTag = new EntityTag(Integer.toOctalString(metricSchedule.hashCode()));
- Response.ResponseBuilder builder = request.evaluatePreconditions(new Date(metricSchedule.getMtime()),eTag);
+ long tim = schedule.getMtime() != null ? schedule.getMtime() : 0;
+ EntityTag eTag = new EntityTag(Long.toOctalString(schedule.hashCode()+tim));
+ builder = request.evaluatePreconditions(new Date(tim),eTag); // factor in mtime in etag
+
if (builder==null) {
// preconditions not met, we need to send the resource
@@ -173,16 +214,24 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
uriBuilder.path("metric/data/" + scheduleId);
URI uri = uriBuilder.build();
-
Link link = new Link("metrics",uri.toString());
metricSchedule.addLink(link);
+ // create link to the resource
+ uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("resource/" + schedule.getResource().getId());
+ uri = uriBuilder.build();
+ link = new Link("resource",uri.toString());
+ metricSchedule.addLink(link);
+
// Link for updates
uriBuilder = uriInfo.getAbsolutePathBuilder();
uri = uriBuilder.build();
Link updateLink = new Link("edit",uri.toString());
metricSchedule.addLink(updateLink);
+ // What media type does the user request?
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
builder = Response.ok(renderTemplate("metricSchedule", metricSchedule), mediaType);
@@ -192,10 +241,6 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
}
}
- // Create a cache control
- CacheControl cc = new CacheControl();
- cc.setMaxAge(300); // Schedules are valid for 5 mins
- cc.setPrivate(false); // Proxies may cache this
builder.cacheControl(cc);
builder.tag(eTag);
@@ -208,6 +253,9 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
List<MeasurementSchedule> schedules = scheduleManager.findSchedulesForResourceAndType(caller,
resourceId, DataType.MEASUREMENT, null,false);
+ for (MeasurementSchedule sched: schedules) {
+ putToCache(sched.getId(),MeasurementSchedule.class,sched);
+ }
List<MetricAggregate> ret = new ArrayList<MetricAggregate>(schedules.size());
long now = System.currentTimeMillis();
@@ -239,6 +287,8 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
scheduleManager.updateSchedule(caller, schedule);
schedule = scheduleManager.getScheduleById(caller,scheduleId);
+ Fqn fqn = getFqn(scheduleId,MeasurementSchedule.class);
+ putToCache(fqn,schedule);
MeasurementDefinition def = schedule.getDefinition();
MetricSchedule ret = new MetricSchedule(scheduleId,def.getName(),def.getDisplayName(),
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 76c3f9d..368ef36 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
@@ -73,8 +73,8 @@ public interface MetricHandlerLocal {
@PUT
@Path("/schedule/{id}")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
+ @Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
MetricSchedule updateSchedule(@PathParam("id") int scheduleId, MetricSchedule in);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
new file mode 100644
index 0000000..2a4f7df
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -0,0 +1,236 @@
+package org.rhq.enterprise.server.rest;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+import javax.interceptor.Interceptors;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinition;
+import org.rhq.core.domain.operation.OperationDefinition;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.operation.OperationManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.rest.domain.Link;
+import org.rhq.enterprise.server.rest.domain.OperationDefinitionRest;
+import org.rhq.enterprise.server.rest.domain.OperationRest;
+
+/**
+ * Deal with operations
+ * @author Heiko W. Rupp
+ */
+@Stateless
+(a)Interceptors(SetCallerInterceptor.class)
+public class OperationsHandlerBean extends AbstractRestBean implements OperationsHandlerLocal {
+
+ @EJB
+ OperationManagerLocal opsManager;
+
+ @EJB
+ ResourceManagerLocal resourceManager;
+
+ @Override
+ public Response getOperationDefinition(int definitionId,
+ Integer resourceId,
+ UriInfo uriInfo,
+ Request request, HttpHeaders httpHeaders) {
+
+
+
+ OperationDefinition def;
+ def = getFromCache(definitionId, OperationDefinition.class);
+ if (def==null) {
+ def = opsManager.getOperationDefinition(caller,definitionId);
+ if (def==null)
+ throw new StuffNotFoundException("OperationDefinition with id " + definitionId);
+ else
+ putToCache(definitionId,OperationDefinition.class,def);
+ }
+
+ EntityTag eTag = new EntityTag(Integer.toHexString(def.hashCode()));
+ Response.ResponseBuilder builder = request.evaluatePreconditions(eTag);
+ if (builder==null) {
+
+ OperationDefinitionRest odr = new OperationDefinitionRest();
+ odr.setId(def.getId());
+ odr.setName(def.getName());
+
+ builder=Response.ok(odr);
+
+ // Add some links
+ if (resourceId!=null) {
+ UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/operation/definition/{id}");
+ uriBuilder.queryParam("resourceId",resourceId);
+ Link createLink = new Link("create",uriBuilder.build(definitionId).toString());
+ odr.addLink(createLink);
+ }
+
+ }
+
+ CacheControl cc = new CacheControl();
+ cc.setMaxAge(1200); // Definitions are very stable, so caching for 20mins is ok
+ cc.setPrivate(false);
+ builder.tag(eTag);
+ builder.cacheControl(cc);
+
+ return builder.build();
+
+ }
+
+ @Override
+ // TODO find out why a return type of Response lets this fail for XML (even with @Wrapped annotation
+ public List<OperationDefinitionRest> getOperationDefinitions(Integer resourceId, UriInfo uriInfo, Request request) {
+
+ if (resourceId == null)
+ throw new ParameterMissingException("resourceId");
+
+ Resource res =resourceManager.getResource(caller,resourceId);
+ if(res==null)
+ throw new StuffNotFoundException("resource with id " + resourceId);
+
+ ResourceType resourceType = res.getResourceType();
+
+/*
+ EntityTag eTag = new EntityTag(Integer.toHexString(resourceType.hashCode()));
+ Response.ResponseBuilder builder = request.evaluatePreconditions(eTag);
+ if (builder==null) {
+*/
+
+ Set<OperationDefinition> opDefList = resourceType.getOperationDefinitions();
+ List<OperationDefinitionRest> resultList = new ArrayList<OperationDefinitionRest>(opDefList.size());
+
+ for (OperationDefinition def : opDefList) {
+ OperationDefinitionRest odr = new OperationDefinitionRest();
+ odr.setId(def.getId());
+ odr.setName(def.getName());
+ UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/operation/definition/{id}");
+ uriBuilder.queryParam("resourceId",resourceId);
+ Link createLink = new Link("create",uriBuilder.build(def.getId()).toString());
+ odr.addLink(createLink);
+
+ resultList.add(odr);
+ }
+ return resultList;
+
+/*
+
+ builder = Response.ok(resultList);
+ }
+
+ CacheControl cc = new CacheControl();
+ cc.setMaxAge(1200); // Definitions are very stable, so caching for 20mins is ok
+ cc.setPrivate(false);
+ builder.tag(eTag);
+ builder.cacheControl(cc);
+
+ return builder.build();
+*/
+
+ }
+
+ @Override
+ public Response createOperation(@PathParam("id") int definitionId,
+ @QueryParam("resourceId") Integer resourceId,
+ UriInfo uriInfo) {
+
+ if (resourceId == null)
+ throw new ParameterMissingException("resourceId");
+
+ Resource res =resourceManager.getResource(caller,resourceId);
+ if(res==null)
+ throw new StuffNotFoundException("resource with id " + resourceId);
+
+
+ OperationDefinition opDef = opsManager.getOperationDefinition(caller,definitionId);
+ if (opDef==null) {
+ throw new StuffNotFoundException("Operation definition with id " + definitionId);
+ }
+ OperationRest operationRest = new OperationRest(resourceId,definitionId);
+ operationRest.setId((int)System.currentTimeMillis()); // TODO better id (?)(we need one for pUT later on)
+ operationRest.setState("creating");
+ operationRest.setName(opDef.getName());
+ ConfigurationDefinition paramDefinition = opDef.getParametersConfigurationDefinition();
+ if (paramDefinition != null) {
+ for (PropertyDefinition propDefs : paramDefinition.getNonGroupedProperties()) { // TODO extend to all properties ?
+ operationRest.getParams().put(propDefs.getName(),"TODO"); // TODO type and value of the value
+ }
+ }
+
+ UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/operation/{id}");
+ URI uri = uriBuilder.build(operationRest.getId());
+ Link editLink = new Link("edit",uri.toString());
+ operationRest.addLink(editLink);
+ Response.ResponseBuilder builder = Response.ok(operationRest);
+
+ putToCache(operationRest.getId(),OperationRest.class,operationRest);
+
+ return builder.build();
+
+ }
+
+ @Override
+ public Response getOperation(@PathParam("id") int operationId) {
+ OperationRest op = getFromCache(operationId,OperationRest.class);
+ if (op==null)
+ throw new StuffNotFoundException("Operation with id " + operationId);
+
+ return Response.ok(op).build();
+ }
+
+ @Override
+ public Response updateOperation(@PathParam("id") int operationId, OperationRest operation, UriInfo uriInfo) {
+
+ if (operation.getState().equals("creating") && operation.getDefinitionId()>0 && !operation.getName().isEmpty()) {
+ // TODO check all the required parameters for persence before allowing to submit
+ Link link = new Link("submit","TODO");
+ operation.addLink(link);
+
+ }
+ UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/operation/{id}");
+ URI uri = uriBuilder.build(operation.getId());
+ Link editLink = new Link("edit",uri.toString());
+ operation.addLink(editLink);
+
+ // Update item in cache
+ putToCache(operation.getId(),OperationRest.class,operation);
+
+ Response.ResponseBuilder builder = Response.ok(operation);
+ return builder.build();
+ }
+
+ @Override
+ @DELETE
+ @Path("{id}")
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ public Response cancelOperation(@PathParam("id") int operationId) {
+
+ log.info("Cancel called");
+
+ removeFromCache(operationId,OperationRest.class);
+
+ return null; // TODO: Customise this generated block
+ }
+
+}
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
new file mode 100644
index 0000000..46a7f86
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java
@@ -0,0 +1,76 @@
+package org.rhq.enterprise.server.rest;
+
+import java.util.List;
+
+import javax.ejb.Local;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.jboss.resteasy.annotations.providers.jaxb.Wrapped;
+
+import org.rhq.enterprise.server.rest.domain.OperationDefinitionRest;
+import org.rhq.enterprise.server.rest.domain.OperationRest;
+
+/**
+ * Service that deals with operations
+ * @author Heiko W. Rupp
+ */
+@Local
+@Path("/operation")
+public interface OperationsHandlerLocal {
+
+
+ @GET
+ @Path("definition/{id}")
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
+ public Response getOperationDefinition(@PathParam("id") int definitionId,
+ @QueryParam("resourceId") Integer resourceId,
+ @Context UriInfo uriInfo,
+ @Context Request request,
+ @Context HttpHeaders httpHeaders);
+
+ @GET
+ @Path("definitions")
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
+ public List<OperationDefinitionRest> getOperationDefinitions(@QueryParam("resourceId") Integer resourceId,
+ @Context UriInfo uriInfo,
+ @Context Request request
+ );
+
+ @POST
+ @Path("definition/{id}")
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
+ public Response createOperation(@PathParam("id") int definitionId,
+ @QueryParam("resourceId") Integer resourceId,
+ @Context UriInfo uriInfo);
+
+ @GET
+ @Path("{id}")
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
+ public Response getOperation(@PathParam("id") int operationId);
+
+ @PUT
+ @Path("{id}")
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
+ @Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
+ public Response updateOperation(@PathParam("id") int operationId, OperationRest operation, @Context UriInfo uriInfo);
+
+ @DELETE
+ @Path("{id}")
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
+ public Response cancelOperation(@PathParam("id") int operationId);
+
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 368efc0..e656c24 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -24,12 +24,20 @@ package org.rhq.enterprise.server.rest;
import java.net.URI;
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
+import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
@@ -71,44 +79,88 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
AlertManagerLocal alertManager;
@Override
- public ResourceWithType getResource(int id) {
+ public Response getResource(int id, @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo) {
- Resource res = resMgr.getResource(caller, id);
+ // Create a cache control
+ CacheControl cc = new CacheControl();
+ cc.setMaxAge(300); // Resources are valid for 5 mins
+ cc.setPrivate(false); // Proxies may cache this
- ResourceWithType rwt = fillRWT(res);
+ Resource res;
+ res = getFromCache(id,Resource.class);
+ if (res==null) {
+ res = resMgr.getResource(caller, id);
+ if (res!=null)
+ putToCache(id, Resource.class,res);
+ else
+ throw new StuffNotFoundException("Resource with id " + id);
+ }
- return rwt;
- }
+ Response.ResponseBuilder builder=null;
- @Override
- public String getResourceHtml(int id) {
- ResourceWithType rwt = getResource(id);
- return renderTemplate("resourceWithType.ftl", rwt);
+ long mtime = res.getMtime();
+ EntityTag eTag = new EntityTag(Long.toOctalString(res.hashCode()+ mtime)); // factor in mtime in etag
+ builder = request.evaluatePreconditions(new Date(mtime),eTag);
+
+ if (builder!=null) {
+ builder.cacheControl(cc);
+ return builder.build();
+ }
+
+
+ ResourceWithType rwt = fillRWT(res, uriInfo);
+
+ // What media type does the user request?
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+
+ if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+ builder = Response.ok(renderTemplate("resourceWithType", rwt), mediaType);
+ }
+ else {
+ builder = Response.ok(rwt);
+ }
+
+ return builder.build();
}
+
@Override
- public List<ResourceWithType> getPlatforms() {
+ public Response getPlatforms(@Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo) {
PageControl pc = new PageControl();
List<Resource> ret = resMgr.findResourcesByCategory(caller, ResourceCategory.PLATFORM, InventoryStatus.COMMITTED, pc) ;
List<ResourceWithType> rwtList = new ArrayList<ResourceWithType>(ret.size());
for (Resource r: ret) {
- ResourceWithType rwt = fillRWT(r);
+ putToCache(r.getId(),Resource.class,r);
+ ResourceWithType rwt = fillRWT(r, uriInfo);
rwtList.add(rwt);
}
- return rwtList;
- }
+ // What media type does the user request?
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+ Response.ResponseBuilder builder;
- @Override
- public String getPlatformsHtml() {
- List<ResourceWithType> list = getPlatforms();
- return renderTemplate("listResourceWithType", list);
+ if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+ builder = Response.ok(renderTemplate("listResourceWithType", rwtList), mediaType);
+ }
+ else {
+ builder = Response.ok(rwtList);
+ }
+
+ return builder.build();
}
@Override
public ResourceWithChildren getHierarchy(int baseResourceId) {
// TODO optimize to do less recursion
- Resource start = resMgr.getResource(caller,baseResourceId);
+ Resource start;
+ start = getFromCache(baseResourceId,Resource.class);
+ if (start==null) {
+ start = resMgr.getResource(caller,baseResourceId);
+ if (start!=null)
+ putToCache(start.getId(),Resource.class,start);
+ }
ResourceWithChildren rwc = getHierarchy(start);
/*new ResourceWithChildren(""+start.getId(),start.getName());
@@ -135,6 +187,7 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
for (Resource res : ret) {
ResourceWithChildren child = getHierarchy(res);
resList.add(child);
+ putToCache(res.getId(),Resource.class,res);
}
if (!resList.isEmpty())
rwc.setChildren(resList);
@@ -151,7 +204,7 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
return availabilityRest;
}
- private ResourceWithType fillRWT(Resource res) {
+ private ResourceWithType fillRWT(Resource res, UriInfo uriInfo) {
ResourceType resourceType = res.getResourceType();
ResourceWithType rwt = new ResourceWithType(res.getName(),res.getId());
rwt.setTypeName(resourceType.getName());
@@ -161,6 +214,13 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
if (parent!=null) {
rwt.setParentId(parent.getId());
}
+ UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/operation/definitions");
+ uriBuilder.queryParam("resourceId",res.getId());
+ URI uri = uriBuilder.build();
+ Link link = new Link("operationDefinitions",uri.toString());
+ rwt.addLink(link);
+
return rwt;
}
@@ -171,6 +231,7 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
Set<MeasurementSchedule> schedules = res.getSchedules();
List<MetricSchedule> ret = new ArrayList<MetricSchedule>(schedules.size());
for (MeasurementSchedule schedule : schedules) {
+ putToCache(schedule.getId(),MeasurementSchedule.class,schedule);
MeasurementDefinition definition = schedule.getDefinition();
MetricSchedule ms = new MetricSchedule(schedule.getId(), definition.getName(), definition.getDisplayName(),
schedule.isEnabled(),schedule.getInterval(), definition.getUnits().toString(),
@@ -180,6 +241,13 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
URI uri = uriBuilder.build(schedule.getId());
Link metricLink = new Link("metric",uri.toString());
ms.addLink(metricLink);
+ // create link to the resource
+ uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("resource/" + schedule.getResource().getId());
+ uri = uriBuilder.build();
+ Link link = new Link("resource",uri.toString());
+ ms.addLink(link);
+
ret.add(ms);
}
@@ -192,24 +260,42 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
}
@Override
- public List<ResourceWithType> getChildren(int id) {
+ public Response getChildren(int id, @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo) {
PageControl pc = new PageControl();
- Resource parent = resMgr.getResource(caller,id);
+ Resource parent;
+ parent = getFromCache(id,Resource.class);
+ if (parent==null) {
+ parent = resMgr.getResource(caller,id);
+ if (parent==null)
+ throw new StuffNotFoundException("Resource with id " + id);
+ else
+ putToCache(id,Resource.class,parent);
+ }
List<Resource> ret = resMgr.findResourceByParentAndInventoryStatus(caller,parent,InventoryStatus.COMMITTED,pc);
List<ResourceWithType> rwtList = new ArrayList<ResourceWithType>(ret.size());
for (Resource r: ret) {
- ResourceWithType rwt = fillRWT(r);
+ putToCache(r.getId(),Resource.class,r);
+ ResourceWithType rwt = fillRWT(r, uriInfo);
rwtList.add(rwt);
}
- return rwtList;
- }
+ // What media type does the user request?
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+ Response.ResponseBuilder builder;
+
+ if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+ builder = Response.ok(renderTemplate("listResourceWithType", rwtList), mediaType);
+ }
+ else {
+ builder = Response.ok(rwtList);
+ }
+
+ return builder.build();
- public String getChildrenHtml(int id) {
- List<ResourceWithType> list = getChildren(id);
- return renderTemplate("listResourceWithType", list);
}
+
@Override
public List<Link> getAlertsForResource(int resourceId) {
AlertCriteria criteria = new AlertCriteria();
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 c2e8698..d1cb0f2 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
@@ -26,6 +26,10 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.jboss.resteasy.links.AddLinks;
@@ -53,23 +57,15 @@ public interface ResourceHandlerLocal {
})
@GET
@Path("/{id}")
- @Produces({"application/json","application/xml"})
- ResourceWithType getResource(@PathParam("id") int id);
-
- @GET
- @Path("/{id}")
- @Produces("text/html")
- String getResourceHtml(@PathParam("id") int id);
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
+ Response getResource(@PathParam("id") int id, @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
@GET
@Path("/platforms")
- @Produces({"application/json","application/xml"})
- List<ResourceWithType> getPlatforms();
-
- @GET
- @Path("/platforms")
- @Produces("text/html")
- String getPlatformsHtml();
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
+ Response getPlatforms(@Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
@GET
@@ -93,20 +89,17 @@ public interface ResourceHandlerLocal {
@Path("/{id}/schedules")
@Produces("text/html")
@LinkResource(rel="schedules",value = MetricSchedule.class)
+ // TODO move to ScheduleManager, link from resource and pass the resource as query param
String getSchedulesHtml(@PathParam("id") int resourceId,
@Context UriInfo uriInfo);
@GET
@Path("/{id}/children")
- @Produces({"application/json","application/xml"})
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
@LinkResource(rel="children", value = ResourceWithType.class)
- List<ResourceWithType> getChildren(@PathParam("id") int id);
+ Response getChildren(@PathParam("id") int id, @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
- @GET
- @Path("/{id}/children")
- @Produces("text/html")
- @LinkResource(rel="children", value = ResourceWithType.class)
- String getChildrenHtml(@PathParam("id") int id);
@AddLinks
@GET
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationDefinitionRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationDefinitionRest.java
new file mode 100644
index 0000000..70f1a97
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationDefinitionRest.java
@@ -0,0 +1,52 @@
+package org.rhq.enterprise.server.rest.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Heiko W. Rupp
+ */
+@XmlRootElement
+public class OperationDefinitionRest {
+
+ public OperationDefinitionRest() {
+ }
+
+ String name;
+ int id;
+ List<Link> links = new ArrayList<Link>();
+ // TODO add parameters
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ @XmlElementRef
+ public List<Link> getLinks() {
+ return links;
+ }
+
+ public void setLinks(List<Link> links) {
+ this.links = links;
+ }
+
+ public void addLink(Link link) {
+ links.add(link);
+ }
+
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationRest.java
new file mode 100644
index 0000000..50332ae
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationRest.java
@@ -0,0 +1,117 @@
+package org.rhq.enterprise.server.rest.domain;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author Heiko W. Rupp
+ */
+@XmlRootElement
+public class OperationRest {
+
+ int id;
+ String name;
+ String state; // TODO Convert to enum
+ int resourceId;
+ int definitionId;
+ Map<String,Object> params = new HashMap<String, Object>();
+ List<Link> links = new ArrayList<Link>();
+
+ public OperationRest() {
+ }
+
+ public OperationRest(int resourceId, int definitionId) {
+ this.resourceId = resourceId;
+ this.definitionId = definitionId;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public int getResourceId() {
+ return resourceId;
+ }
+
+ public void setResourceId(int resourceId) {
+ this.resourceId = resourceId;
+ }
+
+ public int getDefinitionId() {
+ return definitionId;
+ }
+
+ public void setDefinitionId(int definitionId) {
+ this.definitionId = definitionId;
+ }
+
+ public Map<String, Object> getParams() {
+ return params;
+ }
+
+ public void setParams(Map<String, Object> params) {
+ this.params = params;
+ }
+
+ @XmlElementRef
+ public List<Link> getLinks() {
+ return links;
+ }
+
+ public void setLinks(List<Link> links) {
+ this.links = links;
+ }
+
+ public void addLink(Link link) {
+ links.add(link);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ OperationRest that = (OperationRest) o;
+
+ if (definitionId != that.definitionId) return false;
+ if (id != that.id) return false;
+ if (resourceId != that.resourceId) return false;
+ if (name != null ? !name.equals(that.name) : that.name != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (int) (id ^ (id >>> 32));
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ result = 31 * result + resourceId;
+ result = 31 * result + definitionId;
+ return result;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/metricSchedule.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/metricSchedule.ftl
index 26360e5..0a0f187 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/metricSchedule.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/metricSchedule.ftl
@@ -46,7 +46,10 @@
<td>Units</td><td>${var.unit}</td>
</tr>
</table>
- <a href="/rest/1/metric/data/${var.scheduleId}.html">Metric data</a>
- <br/>
-
+ Links<br/>
+ <ul>
+ <#list var.links as link>
+ <li><a href="${link.href}.html">${link.rel}</a> </li>
+ </#list>
+ </ul>
</html>
\ No newline at end of file
commit 001a8e84ccb27d43979c10ce2103a6106440dfea
Author: Heiko W. Rupp <pilhuhn(a)fedoraproject.org>
Date: Wed Nov 2 17:58:59 2011 +0100
Remove bogus import.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
index ff160e2..d951767 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
@@ -23,8 +23,6 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
-import sun.security.provider.certpath.OCSPResponse;
-
import org.rhq.enterprise.server.resource.ResourceNotFoundException;
/**
commit c6be98cee4043752d110f191a039a11bfe869465
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Nov 2 08:51:54 2011 +0100
Introduce a ParamMissing exception for missing query params
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
index 57385cd..ff160e2 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
@@ -23,6 +23,10 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
+import sun.security.provider.certpath.OCSPResponse;
+
+import org.rhq.enterprise.server.resource.ResourceNotFoundException;
+
/**
* Map a NotFoundException to a HTTP response with respective error message
* @author Heiko W. Rupp
@@ -40,6 +44,14 @@ public class CustomExceptionMapper implements ExceptionMapper<EJBException> {
return Response.status(Response.Status.NOT_FOUND)
.entity(cause.getMessage())
.build();
+ else if (cause instanceof ResourceNotFoundException)
+ return Response.status(Response.Status.NOT_FOUND)
+ .entity(cause.getMessage())
+ .build();
+ else if (cause instanceof ParameterMissingException)
+ return Response.status(Response.Status.NOT_ACCEPTABLE)
+ .entity(cause.getMessage())
+ .build();
else
return Response.status(Response.Status.SERVICE_UNAVAILABLE)
.entity(cause.getMessage())
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ParameterMissingException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ParameterMissingException.java
new file mode 100644
index 0000000..16fd62f
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ParameterMissingException.java
@@ -0,0 +1,12 @@
+package org.rhq.enterprise.server.rest;
+
+/**
+ * Exception thrown if (Query) Parameters are missing
+ * @author Heiko W. Rupp
+ */
+public class ParameterMissingException extends RuntimeException {
+
+ public ParameterMissingException(String what) {
+ super("(Query)param " + what + " is missing");
+ }
+}
commit 47a3371266a2607681cd7ee05f9028ef03bb86ed
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Nov 2 08:48:34 2011 +0100
Add hyperlinks from resource/schedules to their metrics
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 5251805..368efc0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -22,6 +22,7 @@
*/
package org.rhq.enterprise.server.rest;
+import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -29,8 +30,8 @@ import java.util.Set;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
-
-import org.jboss.resteasy.spi.Link;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
import org.rhq.core.domain.alert.Alert;
import org.rhq.core.domain.criteria.AlertCriteria;
@@ -42,8 +43,8 @@ import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceCategory;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.enterprise.server.alert.AlertManagerLocal;
-import org.rhq.enterprise.server.plugin.pc.content.RepoSource;
import org.rhq.enterprise.server.rest.domain.AvailabilityRest;
+import org.rhq.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.MetricSchedule;
import org.rhq.enterprise.server.rest.domain.ResourceWithChildren;
import org.rhq.enterprise.server.rest.domain.ResourceWithType;
@@ -163,7 +164,7 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
return rwt;
}
- public List<MetricSchedule> getSchedules(int resourceId) {
+ public List<MetricSchedule> getSchedules(int resourceId, UriInfo uriInfo) {
Resource res = resMgr.getResource(caller, resourceId);
@@ -174,14 +175,19 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
MetricSchedule ms = new MetricSchedule(schedule.getId(), definition.getName(), definition.getDisplayName(),
schedule.isEnabled(),schedule.getInterval(), definition.getUnits().toString(),
definition.getDataType().toString());
+ UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("/metric/data/{id}");
+ URI uri = uriBuilder.build(schedule.getId());
+ Link metricLink = new Link("metric",uri.toString());
+ ms.addLink(metricLink);
ret.add(ms);
}
return ret;
}
- public String getSchedulesHtml(int resourceId) {
- List<MetricSchedule> list = getSchedules(resourceId);
+ public String getSchedulesHtml(int resourceId, UriInfo uriInfo) {
+ List<MetricSchedule> list = getSchedules(resourceId, uriInfo);
return renderTemplate("listMetricSchedule", list);
}
@@ -212,7 +218,7 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
List<Link> links = new ArrayList<Link>(alerts.size());
for (Alert al: alerts) {
Link link = new Link();
- link.setRelationship("alert");
+ link.setRel("alert");
link.setHref("/alert/" + al.getId());
}
return links;
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 a36d4fb..c2e8698 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
@@ -25,13 +25,15 @@ import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
import org.jboss.resteasy.links.AddLinks;
import org.jboss.resteasy.links.LinkResource;
import org.jboss.resteasy.links.LinkResources;
-import org.jboss.resteasy.spi.Link;
import org.rhq.enterprise.server.rest.domain.AvailabilityRest;
+import org.rhq.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.MetricSchedule;
import org.rhq.enterprise.server.rest.domain.ResourceWithChildren;
import org.rhq.enterprise.server.rest.domain.ResourceWithType;
@@ -84,13 +86,15 @@ public interface ResourceHandlerLocal {
@Path("/{id}/schedules")
@Produces({"application/json","application/xml"})
@LinkResource(rel="schedules",value = MetricSchedule.class)
- List<MetricSchedule> getSchedules(@PathParam("id") int resourceId);
+ List<MetricSchedule> getSchedules(@PathParam("id") int resourceId,
+ @Context UriInfo uriInfo);
@GET
@Path("/{id}/schedules")
@Produces("text/html")
@LinkResource(rel="schedules",value = MetricSchedule.class)
- String getSchedulesHtml(@PathParam("id") int resourceId);
+ String getSchedulesHtml(@PathParam("id") int resourceId,
+ @Context UriInfo uriInfo);
@GET
@Path("/{id}/children")
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
index 894277a..1e5971c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
@@ -22,6 +22,9 @@
*/
package org.rhq.enterprise.server.rest.domain;
+import java.util.ArrayList;
+import java.util.List;
+
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
@@ -32,9 +35,6 @@ import javax.xml.bind.annotation.XmlRootElement;
import org.jboss.resteasy.annotations.providers.jaxb.json.Mapped;
import org.jboss.resteasy.annotations.providers.jaxb.json.XmlNsMap;
-import org.jboss.resteasy.links.AddLinks;
-import org.jboss.resteasy.links.LinkResource;
-import org.jboss.resteasy.links.RESTServiceDiscovery;
import org.jboss.resteasy.spi.touri.URITemplate;
/**
@@ -54,8 +54,8 @@ public class ResourceWithType {
Integer typeId;
String pluginName;
Integer parentId;
+ List<Link> links = new ArrayList<Link>();
- private RESTServiceDiscovery rest;
public ResourceWithType() {
}
@@ -124,12 +124,15 @@ public class ResourceWithType {
}
@XmlElementRef
- public RESTServiceDiscovery getRest() {
- return rest;
+ public List<Link> getLinks() {
+ return links;
}
- public void setRest(RESTServiceDiscovery rest) {
- this.rest = rest;
+ public void setLinks(List<Link> links) {
+ this.links = links;
}
+ public void addLink(Link link) {
+ links.add(link);
+ }
}
commit 691dc9c0cce937f4c1b979145bfa6458382c29c0
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri Oct 28 11:01:52 2011 +0200
Add support for hyperlinking between schedule and metrics and to the edit schedule method.
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 0f0c9a9..9908b7d 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
@@ -18,6 +18,7 @@
*/
package org.rhq.enterprise.server.rest;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -32,12 +33,15 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
import org.rhq.core.domain.measurement.DataType;
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.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.MetricAggregate;
import org.rhq.enterprise.server.measurement.MeasurementAggregate;
import org.rhq.enterprise.server.measurement.MeasurementDataManagerLocal;
@@ -132,12 +136,14 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
/**
* Return a metric schedule with the respective status codes for cache validation
*
+ *
* @param scheduleId ID of the schedule
* @param request the REST request - injected by the REST framework
* @param headers the REST request http headers - injected by the REST framework
+ * @param uriInfo
* @return Schedule with respective headers
*/
- public Response getSchedule(int scheduleId, Request request, HttpHeaders headers) {
+ public Response getSchedule(int scheduleId, Request request, HttpHeaders headers, UriInfo uriInfo) {
MeasurementSchedule schedule = scheduleManager.getScheduleById(caller, scheduleId);
if (schedule==null)
@@ -155,11 +161,29 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
// Check for conditional get
+ // Interestingly computing the hashCode of the original schedule is slower, as it also
+ // pulls in data from the definition and the resource
EntityTag eTag = new EntityTag(Integer.toOctalString(metricSchedule.hashCode()));
Response.ResponseBuilder builder = request.evaluatePreconditions(new Date(metricSchedule.getMtime()),eTag);
if (builder==null) {
// preconditions not met, we need to send the resource
+
+ // create link to metrics
+ UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("metric/data/" + scheduleId);
+ URI uri = uriBuilder.build();
+
+ Link link = new Link("metrics",uri.toString());
+ metricSchedule.addLink(link);
+
+ // Link for updates
+ uriBuilder = uriInfo.getAbsolutePathBuilder();
+ uri = uriBuilder.build();
+ Link updateLink = new Link("edit",uri.toString());
+ metricSchedule.addLink(updateLink);
+
+
if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
builder = Response.ok(renderTemplate("metricSchedule", metricSchedule), mediaType);
}
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 053005b..76c3f9d 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
@@ -34,6 +34,7 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
import org.rhq.enterprise.server.rest.domain.MetricAggregate;
import org.rhq.enterprise.server.rest.domain.MetricSchedule;
@@ -67,7 +68,8 @@ public interface MetricHandlerLocal {
@GET
@Path("/schedule/{id}")
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
- Response getSchedule(@PathParam("id") int scheduleId, @Context Request request, @Context HttpHeaders headers);
+ Response getSchedule(@PathParam("id") int scheduleId, @Context Request request, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo);
@PUT
@Path("/schedule/{id}")
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Link.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Link.java
new file mode 100644
index 0000000..1936425
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Link.java
@@ -0,0 +1,50 @@
+package org.rhq.enterprise.server.rest.domain;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * A link between two resources
+ * @author Heiko W. Rupp
+ */
+@XmlRootElement
+public class Link {
+
+ private String rel;
+ private String href;
+
+ public Link() {
+ }
+
+ public Link(String rel, String href) {
+ this.rel = rel;
+ this.href = href;
+ }
+
+
+ @XmlAttribute
+ public String getRel() {
+ return rel;
+ }
+
+ @XmlAttribute
+ public String getHref() {
+ return href;
+ }
+
+ public void setRel(String rel) {
+ this.rel = rel;
+ }
+
+ public void setHref(String href) {
+ this.href = href;
+ }
+
+ @Override
+ public String toString() {
+ return "Link{" +
+ "rel='" + rel + '\'' +
+ ", href='" + href + '\'' +
+ '}';
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java
index 377ca87..4333530 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java
@@ -18,6 +18,11 @@
*/
package org.rhq.enterprise.server.rest.domain;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.core.UriBuilder;
+import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
@@ -44,6 +49,7 @@ public class MetricSchedule {
String unit;
String type;
transient long mtime;
+ List<Link> links = new ArrayList<Link>();
@SuppressWarnings("unused")
public MetricSchedule() {
@@ -129,7 +135,14 @@ public class MetricSchedule {
this.mtime = mtime;
}
+ public void addLink(Link link) {
+ links.add(link);
+ }
+ @XmlElementRef
+ public List<Link> getLinks() {
+ return links;
+ }
@Override
public boolean equals(Object o) {
@@ -156,4 +169,5 @@ public class MetricSchedule {
result = 31 * result + (int) (mtime ^ (mtime >>> 32));
return result;
}
+
}
commit 9e080614d6b101bd3a86905583d4e4de002a89c7
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu Oct 27 22:53:51 2011 +0200
API cleanup for getting metrics and schedules. Also fix updating of schedules.
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 5beee77..0f0c9a9 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
@@ -26,6 +26,7 @@ import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
@@ -61,8 +62,10 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
private static final long EIGHT_HOURS = 8 * 3600L * 1000L;
@Override
- public MetricAggregate getMetricData(int scheduleId, long startTime, long endTime,
- int dataPoints,boolean hideEmpty) {
+ public Response getMetricData(int scheduleId, long startTime, long endTime,
+ int dataPoints,boolean hideEmpty,
+ @Context Request request,
+ @Context HttpHeaders headers) {
if (dataPoints<0)
throw new IllegalArgumentException("dataPoints must be >0 ");
@@ -105,19 +108,27 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
res.setMaxTimeStamp(maxTime);
res.setMinTimeStamp(minTime);
+ CacheControl cc = new CacheControl();
+ int maxAge = (int) (schedule.getInterval() / 1000L)/2; // millis ; half of schedule interval
+ cc.setMaxAge(maxAge); // these are seconds
+ cc.setPrivate(false);
+ cc.setNoCache(false);
- return res;
- }
- public String getMetricDataHtml(int scheduleId,
- long startTime,
- long endTime,
- int dataPoints,
- boolean hideEmpty) {
- MetricAggregate agg = getMetricData(scheduleId,startTime,endTime,dataPoints,hideEmpty);
- return renderTemplate("metricData", agg);
+ Response.ResponseBuilder builder;
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+ if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+ String htmlString = renderTemplate("metricData", res);
+ builder = Response.ok(htmlString,mediaType);
+ }
+ else
+ builder= Response.ok(res);
+ builder.cacheControl(cc);
+
+ return builder.build();
}
+
/**
* Return a metric schedule with the respective status codes for cache validation
*
@@ -149,7 +160,7 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
if (builder==null) {
// preconditions not met, we need to send the resource
- if (mediaType == MediaType.TEXT_HTML_TYPE) {
+ if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
builder = Response.ok(renderTemplate("metricSchedule", metricSchedule), mediaType);
}
else {
@@ -191,7 +202,6 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
public MetricSchedule updateSchedule(int scheduleId, MetricSchedule in) {
if (in==null)
throw new StuffNotFoundException("Input is null"); // TODO other type of exception
-
if (in.getScheduleId()==null)
throw new StuffNotFoundException("Invalid input data");
@@ -205,8 +215,10 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
scheduleManager.updateSchedule(caller, schedule);
schedule = scheduleManager.getScheduleById(caller,scheduleId);
+ MeasurementDefinition def = schedule.getDefinition();
- MetricSchedule ret = new MetricSchedule(scheduleId,in.getScheduleName(),in.getDisplayName(),schedule.isEnabled(),schedule.getInterval(),in.getUnit(),in.getType());
+ MetricSchedule ret = new MetricSchedule(scheduleId,def.getName(),def.getDisplayName(),
+ schedule.isEnabled(),schedule.getInterval(),def.getUnits().toString(),def.getDataType().toString());
return ret;
}
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 f7802d3..053005b 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
@@ -18,6 +18,7 @@
*/
package org.rhq.enterprise.server.rest;
+import java.io.InputStream;
import java.util.List;
import javax.ejb.Local;
@@ -30,6 +31,7 @@ import javax.ws.rs.PUT;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
@@ -48,21 +50,15 @@ public interface MetricHandlerLocal {
@GET
@Path("data/{scheduleId}")
- @Produces({"application/json","application/xml"})
- MetricAggregate getMetricData(@PathParam("scheduleId") int scheduleId,
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
+ Response getMetricData(@PathParam("scheduleId") int scheduleId,
@QueryParam("startTime") long startTime,
@QueryParam("endTime") long endTime,
@QueryParam("dataPoints") int dataPoints,
- @QueryParam("hideEmpty") boolean hideEmpty);
+ @QueryParam("hideEmpty") boolean hideEmpty,
+ @Context Request request,
+ @Context HttpHeaders headers);
- @GET
- @Path("data/{scheduleId}")
- @Produces("text/html")
- String getMetricDataHtml(@PathParam("scheduleId") int scheduleId,
- @QueryParam("startTime") long startTime,
- @QueryParam("endTime") long endTime,
- @QueryParam("dataPoints") int dataPoints,
- @QueryParam("hideEmpty") boolean hideEmpty);
@GET
@Path("data/resource/{resourceId}")
@@ -70,12 +66,13 @@ public interface MetricHandlerLocal {
@GET
@Path("/schedule/{id}")
- @Produces({"application/json","application/xml","text/html"})
+ @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
Response getSchedule(@PathParam("id") int scheduleId, @Context Request request, @Context HttpHeaders headers);
@PUT
@Path("/schedule/{id}")
- @Consumes("application/json")
- MetricSchedule updateSchedule(@PathParam("id") int scheduleId, MetricSchedule in);
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ MetricSchedule updateSchedule(@PathParam("id") int scheduleId, MetricSchedule in);
}
commit 8e40cd43b2ca814b43fcd17140d144ae6523cafb
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Oct 26 15:01:54 2011 +0200
Add cache control and merge all media types into one method
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 3ff403d..5beee77 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
@@ -19,11 +19,18 @@
package org.rhq.enterprise.server.rest;
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
+import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
import org.rhq.core.domain.measurement.DataType;
import org.rhq.core.domain.measurement.MeasurementDefinition;
@@ -111,23 +118,54 @@ public class MetricHandlerBean extends AbstractRestBean implements MetricHandle
return renderTemplate("metricData", agg);
}
- public MetricSchedule getSchedule(int scheduleId) {
+ /**
+ * Return a metric schedule with the respective status codes for cache validation
+ *
+ * @param scheduleId ID of the schedule
+ * @param request the REST request - injected by the REST framework
+ * @param headers the REST request http headers - injected by the REST framework
+ * @return Schedule with respective headers
+ */
+ public Response getSchedule(int scheduleId, Request request, HttpHeaders headers) {
- MeasurementSchedule schedule = scheduleManager.getScheduleById(caller,scheduleId);
+ MeasurementSchedule schedule = scheduleManager.getScheduleById(caller, scheduleId);
if (schedule==null)
throw new StuffNotFoundException("Schedule with id " + scheduleId);
+
MeasurementDefinition definition = schedule.getDefinition();
- MetricSchedule ms = new MetricSchedule(schedule.getId(), definition.getName(), definition.getDisplayName(),
- schedule.isEnabled(),schedule.getInterval(), definition.getUnits().toString(),
+ MetricSchedule metricSchedule = new MetricSchedule(schedule.getId(), definition.getName(),
+ definition.getDisplayName(),
+ schedule.isEnabled(), schedule.getInterval(), definition.getUnits().toString(),
definition.getDataType().toString());
+ if (schedule.getMtime()!=null)
+ metricSchedule.setMtime(schedule.getMtime());
- return ms;
- }
+ // What media type does the user request?
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
- @Override
- public String getScheduleHtml(int scheduleId) {
- MetricSchedule ms = getSchedule(scheduleId);
- return renderTemplate("metricSchedule", ms);
+ // Check for conditional get
+ EntityTag eTag = new EntityTag(Integer.toOctalString(metricSchedule.hashCode()));
+ Response.ResponseBuilder builder = request.evaluatePreconditions(new Date(metricSchedule.getMtime()),eTag);
+
+ if (builder==null) {
+ // preconditions not met, we need to send the resource
+ if (mediaType == MediaType.TEXT_HTML_TYPE) {
+ builder = Response.ok(renderTemplate("metricSchedule", metricSchedule), mediaType);
+ }
+ else {
+ builder = Response.ok(metricSchedule);
+ }
+ }
+
+ // Create a cache control
+ CacheControl cc = new CacheControl();
+ cc.setMaxAge(300); // Schedules are valid for 5 mins
+ cc.setPrivate(false); // Proxies may cache this
+
+ builder.cacheControl(cc);
+ builder.tag(eTag);
+
+ return builder.build();
}
@Override
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 572fe5b..f7802d3 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
@@ -28,6 +28,10 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.PUT;
import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
import org.rhq.enterprise.server.rest.domain.MetricAggregate;
import org.rhq.enterprise.server.rest.domain.MetricSchedule;
@@ -66,13 +70,8 @@ public interface MetricHandlerLocal {
@GET
@Path("/schedule/{id}")
- @Produces({"application/json","application/xml"})
- MetricSchedule getSchedule(@PathParam("id") int scheduleId);
-
- @GET
- @Path("/schedule/{id}")
- @Produces("text/html")
- String getScheduleHtml(@PathParam("id") int scheduleId);
+ @Produces({"application/json","application/xml","text/html"})
+ Response getSchedule(@PathParam("id") int scheduleId, @Context Request request, @Context HttpHeaders headers);
@PUT
@Path("/schedule/{id}")
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java
index efa6361..377ca87 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricSchedule.java
@@ -20,7 +20,7 @@ package org.rhq.enterprise.server.rest.domain;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlTransient;
import org.jboss.resteasy.annotations.providers.jaxb.json.Mapped;
import org.jboss.resteasy.annotations.providers.jaxb.json.XmlNsMap;
@@ -43,6 +43,7 @@ public class MetricSchedule {
String displayName;
String unit;
String type;
+ transient long mtime;
@SuppressWarnings("unused")
public MetricSchedule() {
@@ -118,4 +119,41 @@ public class MetricSchedule {
// public String getEnabled() {
// return String.valueOf(enabled);
// }
+
+ @XmlTransient
+ public long getMtime() {
+ return mtime;
+ }
+
+ public void setMtime(long mtime) {
+ this.mtime = mtime;
+ }
+
+
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ MetricSchedule that = (MetricSchedule) o;
+
+ if (collectionInterval != that.collectionInterval) return false;
+ if (mtime != that.mtime) return false;
+ if (scheduleId != that.scheduleId) return false;
+ if (enabled != null ? !enabled.equals(that.enabled) : that.enabled != null) return false;
+ if (scheduleName != null ? !scheduleName.equals(that.scheduleName) : that.scheduleName != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = scheduleId;
+ result = 31 * result + (scheduleName != null ? scheduleName.hashCode() : 0);
+ result = 31 * result + (enabled != null ? enabled.hashCode() : 0);
+ result = 31 * result + (int) (collectionInterval ^ (collectionInterval >>> 32));
+ result = 31 * result + (int) (mtime ^ (mtime >>> 32));
+ return result;
+ }
}
commit abd6af308975aab38766afa51c733923d3df23cf
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Oct 26 14:59:08 2011 +0200
Update to RESTeasy 2.2 and move artifacs into rhq.ear, so future updates do noot need a container build.
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/js/whisker.js b/modules/enterprise/gui/rest-war/src/main/webapp/js/whisker.js
index b07ec2e..6f23669 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/js/whisker.js
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/js/whisker.js
@@ -9,17 +9,16 @@ function whisker(scheduleId,divId) {
.attr("height", h);
// .append("svg:g");
// .attr("transform", "translate(" + p[3] + "," + (h - p[2]) + ")");
-console.log(scheduleId);
d3.json(
'/rest/1/metric/data/'+scheduleId+'.json?hideEmpty=true',
function (jsondata) {
- var points = jsondata.metricAggregate.dataPoints;
- var minVal = jsondata.metricAggregate.min;
- var maxVal = jsondata.metricAggregate.max;
- var avgVal = jsondata.metricAggregate.avg;
- var minTs = jsondata.metricAggregate.minTimeStamp;
- var maxTs = jsondata.metricAggregate.maxTimeStamp;
+ var points = jsondata.dataPoints;
+ var minVal = jsondata.min;
+ var maxVal = jsondata.max;
+ var avgVal = jsondata.avg;
+ var minTs = jsondata.minTimeStamp;
+ var maxTs = jsondata.maxTimeStamp;
var minTsD = new Date(minTs);
var maxTsD = new Date(maxTs);
@@ -30,7 +29,6 @@ console.log(scheduleId);
// Y axis goes from lowest to highest value
var y = d3.scale.linear().domain([minVal, maxVal]).rangeRound([0,h]);
-// console.log(jsondata.metricAggregate);
// Line for the average
var avgLine = svg.append("svg:line")
@@ -50,7 +48,9 @@ console.log(scheduleId);
return x(new Date(d.timeStamp))
};
- var line = bars.enter().append("svg:line")
+ var group = bars.enter().append("svg:g");
+
+ var line = group.append("svg:line")
.attr("x1", currX)
.attr("x2", currX)
.attr("y1", function(d) {
@@ -61,7 +61,7 @@ console.log(scheduleId);
})
.attr("stroke", "lightblue");
- var circleLow = bars.enter().append("svg:circle")
+ var circleLow = group.append("svg:circle")
.attr("cx", currX)
.attr("cy", function(d) {
return h - y(d.low)
@@ -70,7 +70,7 @@ console.log(scheduleId);
.attr("stroke", "green")
.attr("fill", "lightgreen");
- var circleHigh = bars.enter().append("svg:circle")
+ var circleHigh = group.append("svg:circle")
.attr("cx", currX)
.attr("cy", function(d) {
return h - y(d.high)
@@ -79,7 +79,7 @@ console.log(scheduleId);
.attr("stroke", "green")
.attr("fill", "lightblue");
- var circleVal = bars.enter().append("svg:circle")
+ var circleVal = group.append("svg:circle")
.attr("cx", currX)
.attr("cy", function(d) {
return h - y(d.value)
diff --git a/modules/enterprise/server/container/pom.xml b/modules/enterprise/server/container/pom.xml
index 1e55e08..e6fa762 100644
--- a/modules/enterprise/server/container/pom.xml
+++ b/modules/enterprise/server/container/pom.xml
@@ -194,7 +194,6 @@
<property name="jsf-impl.version" value="${jsf-impl.version}" />
<property name="hibernate3.version" value="${hibernate3.version}" />
<property name="quartz.version" value="${quartz.version}" />
- <property name="resteasy.version" value="${resteasy.version}" />
<!-- dev DB settings (used to init rhq-server.properties if dev profile is active or developer prop is set) -->
<property name="rhq.dev.ds.connection-url" value="${rhq.dev.ds.connection-url}" />
diff --git a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
index 1f8b8b2..e2f3663 100644
--- a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
+++ b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
@@ -408,27 +408,6 @@
</fileset>
</move>
- <echo>Adding REST support ...</echo>
- <copy file="${settings.localRepository}/org/jboss/resteasy/resteasy-jaxrs/${resteasy.version}/resteasy-jaxrs-${resteasy.version}.jar"
- todir="${jboss.home}/server/default/lib" verbose="true" failonerror="true"/>
- <copy file="${settings.localRepository}/org/jboss/resteasy/resteasy-jettison-provider/${resteasy.version}/resteasy-jettison-provider-${resteasy.version}.jar"
- todir="${jboss.home}/server/default/lib" verbose="true" failonerror="true"/>
- <copy file="${settings.localRepository}/org/jboss/resteasy/resteasy-jaxb-provider/${resteasy.version}/resteasy-jaxb-provider-${resteasy.version}.jar"
- todir="${jboss.home}/server/default/lib" verbose="true" failonerror="true"/>
- <copy file="${settings.localRepository}/org/jboss/resteasy/resteasy-links/${resteasy.version}/resteasy-links-${resteasy.version}.jar"
- todir="${jboss.home}/server/default/lib" verbose="true" failonerror="true"/>
- <copy file="${settings.localRepository}/org/jboss/resteasy/jaxrs-api/${resteasy.version}/jaxrs-api-${resteasy.version}.jar"
- todir="${jboss.home}/server/default/lib" verbose="true" failonerror="true"/>
-
- <!-- TODO define versions of the following in the root pom -->
- <copy file="${settings.localRepository}/org/scannotation/scannotation/1.0.3/scannotation-1.0.3.jar"
- todir="${jboss.home}/server/default/lib" verbose="true" failonerror="true"/>
- <copy file="${settings.localRepository}/net/jcip/jcip-annotations/1.0/jcip-annotations-1.0.jar"
- todir="${jboss.home}/server/default/lib" verbose="true" failonerror="true"/>
- <copy file="${settings.localRepository}/org/codehaus/jettison/jettison/1.2/jettison-1.2.jar"
- todir="${jboss.home}/server/default/lib" verbose="true" failonerror="true"/>
- <copy file="${settings.localRepository}/org/freemarker/freemarker/2.3.18/freemarker-2.3.18.jar"
- todir="${jboss.home}/server/default/lib" verbose="true" failonerror="true"/>
</target>
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index 32ce3d3..a913b44 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -95,7 +95,7 @@
<groupId>org.rhq</groupId>
<artifactId>rhq-core-domain</artifactId>
</exclusion>
- </exclusions>
+ </exclusions>
</dependency>
<dependency>
@@ -128,6 +128,43 @@
</dependency>
-->
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ <version>${resteasy.version}</version>
+ <scope>jar</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>javassist</groupId>
+ <artifactId>javassist</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jettison-provider</artifactId>
+ <version>${resteasy.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-links</artifactId>
+ <version>${resteasy.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.freemarker</groupId>
+ <artifactId>freemarker</artifactId>
+ <version>${freemarker.version}</version>
+ <type>jar</type>
+ </dependency>
+
</dependencies>
<build>
@@ -351,13 +388,13 @@
<artifactId>packagetype-cli</artifactId>
<version>${project.version}</version>
</artifactItem>
-
+
<artifactItem>
<groupId>org.rhq</groupId>
<artifactId>rhq-serverplugin-drift</artifactId>
<version>${project.version}</version>
</artifactItem>
-
+
</artifactItems>
<outputDirectory>${earDirectory}/rhq-serverplugins</outputDirectory>
</configuration>
diff --git a/pom.xml b/pom.xml
index 040e7e6..9eae894 100644
--- a/pom.xml
+++ b/pom.xml
@@ -107,7 +107,8 @@
<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.2.1.GA</resteasy.version>
+ <resteasy.version>2.2.2.GA</resteasy.version>
+ <freemarker.version>2.3.18</freemarker.version>
<rhq.db.admin.username>rhqadmin</rhq.db.admin.username>
<rhq.db.admin.password>rhqadmin</rhq.db.admin.password>
12 years, 4 months