diff -uNr zabbix-3.0.3.orig/frontends/php/include/defines.inc.php zabbix-3.0.3/frontends/php/include/defines.inc.php --- zabbix-3.0.3.orig/frontends/php/include/defines.inc.php 2016-05-18 14:59:37.000000000 +0200 +++ zabbix-3.0.3/frontends/php/include/defines.inc.php 2016-07-07 12:13:19.160761267 +0200 @@ -840,7 +840,7 @@ define('ZBX_PREG_INTERNAL_NAMES', '([0-9a-zA-Z_\. \-]+)'); // !!! Don't forget sync code with C !!! define('ZBX_PREG_NUMBER', '([\-+]?[0-9]+[.]?[0-9]*['.ZBX_BYTE_SUFFIXES.ZBX_TIME_SUFFIXES.']?)'); define('ZBX_PREG_DEF_FONT_STRING', '/^[0-9\.:% ]+$/'); -define('ZBX_PREG_DNS_FORMAT', '([0-9a-zA-Z_\.\-$]|\{\$?'.ZBX_PREG_MACRO_NAME.'\})*'); +define('ZBX_PREG_DNS_FORMAT', '(([0-9a-zA-Z_\.\-$]|\{\$?'.ZBX_PREG_MACRO_NAME.'\})*|^service\:jmx\:.+)'); define('ZBX_PREG_HOST_FORMAT', ZBX_PREG_INTERNAL_NAMES); define('ZBX_PREG_MACRO_NAME_FORMAT', '(\{[A-Z\.]+\})'); define('ZBX_PREG_EXPRESSION_LLD_MACROS', '(\{\#'.ZBX_PREG_MACRO_NAME_LLD.'\})'); diff -uNr zabbix-3.0.3.orig/src/zabbix_java/src/com/zabbix/gateway/JMXItemChecker.java zabbix-3.0.3/src/zabbix_java/src/com/zabbix/gateway/JMXItemChecker.java --- zabbix-3.0.3.orig/src/zabbix_java/src/com/zabbix/gateway/JMXItemChecker.java 2016-05-18 14:59:35.000000000 +0200 +++ zabbix-3.0.3/src/zabbix_java/src/com/zabbix/gateway/JMXItemChecker.java 2016-07-07 12:31:25.079449268 +0200 @@ -20,12 +20,14 @@ package com.zabbix.gateway; import java.util.HashMap; +import java.util.List; import javax.management.MBeanAttributeInfo; import javax.management.MBeanInfo; import javax.management.MBeanServerConnection; import javax.management.ObjectName; import javax.management.openmbean.CompositeData; +import javax.management.openmbean.TabularData; import javax.management.openmbean.TabularDataSupport; import javax.management.remote.JMXConnector; import javax.management.remote.JMXServiceURL; @@ -38,6 +40,7 @@ class JMXItemChecker extends ItemChecker { private static final Logger logger = LoggerFactory.getLogger(JMXItemChecker.class); + private static final String URL_SERVICE = "service:jmx:"; private JMXServiceURL url; private JMXConnector jmxc; @@ -55,7 +58,14 @@ String conn = request.getString(JSON_TAG_CONN); int port = request.getInt(JSON_TAG_PORT); - url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://[" + conn + "]:" + port + "/jmxrmi"); + if (conn.startsWith(URL_SERVICE)) + { + url = new JMXServiceURL(conn); + } + else + { + url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://[" + conn + "]:" + port + "/jmxrmi"); + } jmxc = null; mbsc = null; @@ -205,7 +215,79 @@ throw new ZabbixException("data object type is not primitive: %s", dataObject.getClass()); } - if (dataObject instanceof CompositeData) + if (dataObject instanceof TabularData) + { + TabularData td = (TabularData)dataObject; + Object foundData = null; + + String dataObjectName; + String newFieldNames = ""; + + // Get our comma-separated key(s) for the TabularData indexes + int sep = HelperFunctionChest.separatorIndex(fieldNames); + + if (-1 != sep) + { + dataObjectName = fieldNames.substring(0, sep); + newFieldNames = fieldNames.substring(sep + 1); + } + else + { + dataObjectName = fieldNames; + } + + // unescape possible dots or backslashes that were escaped by user + dataObjectName = HelperFunctionChest.unescapeUserInput(dataObjectName); + + // Now we have to locate the correct value in the tabular data: + // 1. Split the key using a comma so we can get everything + // 2. Search through all keys comparing the input to the key by string value + // Note: This obviously doesn't allow commas to be escaped, but I don't see that + // as a useful thing. + String[] tdKeys = dataObjectName.split(","); + + logger.trace("aforementioned data object contains TabularData; looking for '{}' with keys '{}'", + dataObjectName, tdKeys); + + for (Object k : td.keySet()) + { + List kl = (List)k; + // Check if our keys are the same length + if (kl.size() != tdKeys.length) + { + logger.trace("provided key length wrong, got {}, expected {}. Requested key: {}, found key: {}", + new Object[] { tdKeys.length, kl.size(), dataObjectName, k }); + throw new ZabbixException("TabularData key length is wrong, expected: " + kl.size()); + } + // Check if our keys are the same + boolean same = true; + for (int i = 0; i < tdKeys.length && same; i++) + { + if (!tdKeys[i].toString().equals(kl.get(i).toString())) + { + same = false; + } + } + if (same) + { + foundData = td.get(kl.toArray()); + break; + } + } + + if (foundData != null) + { + logger.trace("Found key: {} and continuing with: {}", dataObjectName, foundData); + return getPrimitiveAttributeValue(foundData, newFieldNames); + } + else + { + logger.error("Could not find TabularData key {}", dataObjectName); + logger.info("Available keys: {}", td.keySet()); + throw new ZabbixException("Could not find key " + dataObjectName + " in tabular data"); + } + } + else if (dataObject instanceof CompositeData) { logger.trace("'{}' contains composite data", dataObject);