1 package org.munin; 2 3 import java.io.IOException; 4 import java.text.NumberFormat; 5 import java.util.Arrays; 6 import java.util.HashMap; 7 import java.util.Iterator; 8 import java.util.Map; 9 import java.util.Set; 10 11 import javax.management.Attribute; 12 import javax.management.AttributeList; 13 import javax.management.InstanceNotFoundException; 14 import javax.management.IntrospectionException; 15 import javax.management.MBeanAttributeInfo; 16 import javax.management.MBeanInfo; 17 import javax.management.MBeanServerConnection; 18 import javax.management.ObjectName; 19 import javax.management.ReflectionException; 20 import javax.management.openmbean.CompositeDataSupport; 21 import javax.management.remote.JMXConnector; 22 import javax.management.remote.JMXConnectorFactory; 23 import javax.management.remote.JMXServiceURL; 24 25 public class JMXQuery { 26 private static final String USERNAME_KEY = "username"; 27 private static final String PASSWORD_KEY = "password"; 28 public static final String USAGE = "Usage of program is:\njava -cp jmxquery.jar org.munin.JMXQuery --url=<URL> [--user=<username> --pass=<password>] [--conf=<config file> [config]]\n, where <URL> is a JMX URL, for example: service:jmx:rmi:///jndi/rmi://HOST:PORT/jmxrmi\nWhen invoked with the config file (see examples folder) - operates as Munin plugin with the provided configuration\nWithout options just fetches all JMX attributes using provided URL"; 29 private String url; 30 private String username; 31 private String password; 32 private JMXConnector connector; 33 private MBeanServerConnection connection; 34 private Configuration config; 35 JMXQuery(String url)36 public JMXQuery(String url) { 37 this(url, null, null); 38 } 39 JMXQuery(String url, String username, String password)40 public JMXQuery(String url, String username, String password) { 41 this.url = url; 42 this.username = username; 43 this.password = password; 44 } 45 connect()46 private void connect() throws IOException { 47 Map<String, Object> environment = null; 48 if ((username != null) && (password != null)) { 49 environment = new HashMap(); 50 51 environment.put("jmx.remote.credentials", new String[] { username, 52 password }); 53 environment.put("username", username); 54 environment.put("password", password); 55 } 56 57 JMXServiceURL jmxUrl = new JMXServiceURL(url); 58 connector = JMXConnectorFactory.connect(jmxUrl, environment); 59 connection = connector.getMBeanServerConnection(); 60 } 61 list()62 private void list() throws IOException, InstanceNotFoundException, 63 IntrospectionException, ReflectionException { 64 if (config == null) { 65 listAll(); 66 } else { 67 listConfig(); 68 } 69 } 70 listConfig()71 private void listConfig() { 72 for (Configuration.FieldProperties field : config.getFields()) { 73 try { 74 Object value = connection.getAttribute( 75 field.getJmxObjectName(), field.getJmxAttributeName()); 76 output(field.getFieldname(), value, field.getJmxAttributeKey()); 77 } catch (Exception e) { 78 System.err.println("Fail to output " + field); 79 e.printStackTrace(); 80 } 81 } 82 } 83 output(String name, Object attr, String key)84 private void output(String name, Object attr, String key) { 85 if ((attr instanceof CompositeDataSupport)) { 86 CompositeDataSupport cds = (CompositeDataSupport) attr; 87 if (key == null) { 88 throw new IllegalArgumentException( 89 "Key is null for composed data " + name); 90 } 91 System.out.println(name + ".value " + format(cds.get(key))); 92 } else { 93 System.out.println(name + ".value " + format(attr)); 94 } 95 } 96 output(String name, Object attr)97 private void output(String name, Object attr) { 98 CompositeDataSupport cds; 99 Iterator it; 100 if ((attr instanceof CompositeDataSupport)) { 101 cds = (CompositeDataSupport) attr; 102 for (it = cds.getCompositeType().keySet().iterator(); it.hasNext();) { 103 String key = it.next().toString(); 104 System.out.println(name + "." + key + ".value " 105 + format(cds.get(key))); 106 } 107 } else { 108 System.out.println(name + ".value " + format(attr)); 109 } 110 } 111 listAll()112 private void listAll() throws IOException, InstanceNotFoundException, 113 IntrospectionException, ReflectionException { 114 Set<ObjectName> mbeans = connection.queryNames(null, null); 115 for (ObjectName name : mbeans) { 116 MBeanInfo info = connection.getMBeanInfo(name); 117 MBeanAttributeInfo[] attrs = info.getAttributes(); 118 String[] attrNames = new String[attrs.length]; 119 for (int i = 0; i < attrs.length; i++) { 120 attrNames[i] = attrs[i].getName(); 121 } 122 try { 123 AttributeList attributes = connection.getAttributes(name, 124 attrNames); 125 for (Attribute attribute : attributes.asList()) { 126 output(name.getCanonicalName() + "%" + attribute.getName(), 127 attribute.getValue()); 128 } 129 } catch (Exception e) { 130 System.err.println("error getting " + name + ":" 131 + e.getMessage()); 132 } 133 } 134 } 135 format(Object value)136 private String format(Object value) { 137 if (value == null) 138 return null; 139 if ((value instanceof String)) 140 return (String) value; 141 if ((value instanceof Number)) { 142 NumberFormat f = NumberFormat.getInstance(); 143 f.setMaximumFractionDigits(2); 144 f.setGroupingUsed(false); 145 return f.format(value); 146 } 147 if ((value instanceof Object[])) { 148 return Integer.toString(Arrays.asList((Object[]) value).size()); 149 } 150 return value.toString(); 151 } 152 disconnect()153 private void disconnect() throws IOException { 154 connector.close(); 155 } 156 main(String[] args)157 public static void main(String[] args) { 158 int arglen = args.length; 159 if (arglen < 1) { 160 System.err 161 .println("Usage of program is:\njava -cp jmxquery.jar org.munin.JMXQuery --url=<URL> [--user=<username> --pass=<password>] [--conf=<config file> [config]]\n, where <URL> is a JMX URL, for example: service:jmx:rmi:///jndi/rmi://HOST:PORT/jmxrmi\nWhen invoked with the config file (see examples folder) - operates as Munin plugin with the provided configuration\nWithout options just fetches all JMX attributes using provided URL"); 162 System.exit(1); 163 } 164 165 String url = null; 166 String user = null; 167 String pass = null; 168 String config_file = null; 169 boolean toconfig = false; 170 for (int i = 0; i < arglen; i++) { 171 if (args[i].startsWith("--url=")) { 172 url = args[i].substring(6); 173 } else if (args[i].startsWith("--user=")) { 174 user = args[i].substring(7); 175 } else if (args[i].startsWith("--pass=")) { 176 pass = args[i].substring(7); 177 } else if (args[i].startsWith("--conf=")) { 178 config_file = args[i].substring(7); 179 } else if (args[i].equals("config")) { 180 toconfig = true; 181 } 182 } 183 184 if ((url == null) || ((user != null) && (pass == null)) 185 || ((user == null) && (pass != null)) 186 || ((config_file == null) && (toconfig))) { 187 System.err 188 .println("Usage of program is:\njava -cp jmxquery.jar org.munin.JMXQuery --url=<URL> [--user=<username> --pass=<password>] [--conf=<config file> [config]]\n, where <URL> is a JMX URL, for example: service:jmx:rmi:///jndi/rmi://HOST:PORT/jmxrmi\nWhen invoked with the config file (see examples folder) - operates as Munin plugin with the provided configuration\nWithout options just fetches all JMX attributes using provided URL"); 189 System.exit(1); 190 } 191 192 if (toconfig) { 193 try { 194 Configuration.parse(config_file).report(System.out); 195 } catch (Exception e) { 196 System.err.println(e.getMessage() + " reading " + config_file); 197 System.exit(1); 198 } 199 } else { 200 JMXQuery query = new JMXQuery(url, user, pass); 201 try { 202 query.connect(); 203 if (config_file != null) { 204 query.setConfig(Configuration.parse(config_file)); 205 } 206 query.list(); 207 } catch (Exception ex) { 208 System.err.println(ex.getMessage() + " querying " + url); 209 ex.printStackTrace(); 210 System.exit(1); 211 } finally { 212 try { 213 query.disconnect(); 214 } catch (IOException e) { 215 System.err.println(e.getMessage() + " closing " + url); 216 } 217 } 218 } 219 } 220 setConfig(Configuration configuration)221 private void setConfig(Configuration configuration) { 222 config = configuration; 223 } 224 getConfig()225 public Configuration getConfig() { 226 return config; 227 } 228 } 229