1 /** 2 * collectd - bindings/java/org/collectd/java/GenericJMXConfConnection.java 3 * Copyright (C) 2009-2012 Florian octo Forster 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * Authors: 24 * Florian octo Forster <octo at collectd.org> 25 */ 26 27 package org.collectd.java; 28 29 import java.util.List; 30 import java.util.Map; 31 import java.util.Iterator; 32 import java.util.ArrayList; 33 import java.util.HashMap; 34 import java.net.InetAddress; 35 import java.net.UnknownHostException; 36 37 import javax.management.MBeanServerConnection; 38 39 import javax.management.remote.JMXServiceURL; 40 import javax.management.remote.JMXConnector; 41 import javax.management.remote.JMXConnectorFactory; 42 43 import org.collectd.api.Collectd; 44 import org.collectd.api.PluginData; 45 import org.collectd.api.OConfigValue; 46 import org.collectd.api.OConfigItem; 47 48 class GenericJMXConfConnection 49 { 50 private String _username = null; 51 private String _password = null; 52 private String _host = null; 53 private String _instance_prefix = null; 54 private String _service_url = null; 55 private JMXConnector _jmx_connector = null; 56 private MBeanServerConnection _mbean_connection = null; 57 private List<GenericJMXConfMBean> _mbeans = null; 58 59 /* 60 * private methods 61 */ getConfigString(OConfigItem ci)62 private String getConfigString (OConfigItem ci) /* {{{ */ 63 { 64 List<OConfigValue> values; 65 OConfigValue v; 66 67 values = ci.getValues (); 68 if (values.size () != 1) 69 { 70 Collectd.logError ("GenericJMXConfConnection: The " + ci.getKey () 71 + " configuration option needs exactly one string argument."); 72 return (null); 73 } 74 75 v = values.get (0); 76 if (v.getType () != OConfigValue.OCONFIG_TYPE_STRING) 77 { 78 Collectd.logError ("GenericJMXConfConnection: The " + ci.getKey () 79 + " configuration option needs exactly one string argument."); 80 return (null); 81 } 82 83 return (v.getString ()); 84 } /* }}} String getConfigString */ 85 getHost()86 private String getHost () /* {{{ */ 87 { 88 if (this._host != null) 89 { 90 return (this._host); 91 } 92 93 return Collectd.getHostname(); 94 } /* }}} String getHost */ 95 connect()96 private void connect () /* {{{ */ 97 { 98 JMXServiceURL service_url; 99 Map<String,Object> environment; 100 101 // already connected 102 if (this._jmx_connector != null) { 103 return; 104 } 105 106 environment = null; 107 if (this._password != null) 108 { 109 String[] credentials; 110 111 if (this._username == null) 112 this._username = new String ("monitorRole"); 113 114 credentials = new String[] { this._username, this._password }; 115 116 environment = new HashMap<String,Object> (); 117 environment.put (JMXConnector.CREDENTIALS, credentials); 118 environment.put (JMXConnectorFactory.PROTOCOL_PROVIDER_CLASS_LOADER, this.getClass().getClassLoader()); 119 } 120 121 try 122 { 123 service_url = new JMXServiceURL (this._service_url); 124 this._jmx_connector = JMXConnectorFactory.connect (service_url, environment); 125 this._mbean_connection = _jmx_connector.getMBeanServerConnection (); 126 } 127 catch (Exception e) 128 { 129 Collectd.logError ("GenericJMXConfConnection: " 130 + "Creating MBean server connection failed: " + e); 131 disconnect (); 132 return; 133 } 134 } /* }}} void connect */ 135 disconnect()136 private void disconnect () /* {{{ */ 137 { 138 try 139 { 140 if (this._jmx_connector != null) { 141 this._jmx_connector.close(); 142 } 143 } 144 catch (Exception e) 145 { 146 // It's fine if close throws an exception 147 } 148 149 this._jmx_connector = null; 150 this._mbean_connection = null; 151 } /* }}} void disconnect */ 152 153 /* 154 * public methods 155 * 156 * <Connection> 157 * Host "tomcat0.mycompany" 158 * ServiceURL "service:jmx:rmi:///jndi/rmi://localhost:17264/jmxrmi" 159 * Collect "java.lang:type=GarbageCollector,name=Copy" 160 * Collect "java.lang:type=Memory" 161 * </Connection> 162 * 163 */ GenericJMXConfConnection(OConfigItem ci)164 public GenericJMXConfConnection (OConfigItem ci) /* {{{ */ 165 throws IllegalArgumentException 166 { 167 List<OConfigItem> children; 168 Iterator<OConfigItem> iter; 169 170 this._mbeans = new ArrayList<GenericJMXConfMBean> (); 171 172 children = ci.getChildren (); 173 iter = children.iterator (); 174 while (iter.hasNext ()) 175 { 176 OConfigItem child = iter.next (); 177 178 if (child.getKey ().equalsIgnoreCase ("Host")) 179 { 180 String tmp = getConfigString (child); 181 if (tmp != null) 182 this._host = tmp; 183 } 184 else if (child.getKey ().equalsIgnoreCase ("User")) 185 { 186 String tmp = getConfigString (child); 187 if (tmp != null) 188 this._username = tmp; 189 } 190 else if (child.getKey ().equalsIgnoreCase ("Password")) 191 { 192 String tmp = getConfigString (child); 193 if (tmp != null) 194 this._password = tmp; 195 } 196 else if (child.getKey ().equalsIgnoreCase ("ServiceURL")) 197 { 198 String tmp = getConfigString (child); 199 if (tmp != null) 200 this._service_url = tmp; 201 } 202 else if (child.getKey ().equalsIgnoreCase ("InstancePrefix")) 203 { 204 String tmp = getConfigString (child); 205 if (tmp != null) 206 this._instance_prefix = tmp; 207 } 208 else if (child.getKey ().equalsIgnoreCase ("Collect")) 209 { 210 String tmp = getConfigString (child); 211 if (tmp != null) 212 { 213 GenericJMXConfMBean mbean; 214 215 mbean = GenericJMX.getMBean (tmp); 216 if (mbean == null) 217 throw (new IllegalArgumentException ("No such MBean defined: " 218 + tmp + ". Please make sure all `MBean' blocks appear " 219 + "before (above) all `Connection' blocks.")); 220 Collectd.logDebug ("GenericJMXConfConnection: " + this._host + ": Add " + tmp); 221 this._mbeans.add (mbean); 222 } 223 } 224 else 225 throw (new IllegalArgumentException ("Unknown option: " 226 + child.getKey ())); 227 } 228 229 if (this._service_url == null) 230 throw (new IllegalArgumentException ("No service URL was defined.")); 231 if (this._mbeans.size () == 0) 232 throw (new IllegalArgumentException ("No valid collect statement " 233 + "present.")); 234 } /* }}} GenericJMXConfConnection (OConfigItem ci) */ 235 query()236 public void query () /* {{{ */ 237 { 238 PluginData pd; 239 240 // try to connect 241 connect (); 242 243 if (this._mbean_connection == null) 244 return; 245 246 Collectd.logDebug ("GenericJMXConfConnection.query: " 247 + "Reading " + this._mbeans.size () + " mbeans from " 248 + ((this._host != null) ? this._host : "(null)")); 249 250 pd = new PluginData (); 251 pd.setHost (this.getHost ()); 252 pd.setPlugin ("GenericJMX"); 253 254 for (int i = 0; i < this._mbeans.size (); i++) 255 { 256 int status; 257 258 status = this._mbeans.get (i).query (this._mbean_connection, pd, 259 this._instance_prefix); 260 if (status != 0) 261 { 262 disconnect (); 263 return; 264 } 265 } /* for */ 266 } /* }}} void query */ 267 toString()268 public String toString () 269 { 270 return (new String ("host = " + this._host + "; " 271 + "url = " + this._service_url)); 272 } 273 } 274 275 /* vim: set sw=2 sts=2 et fdm=marker : */ 276