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