java bindings: Add first take at a `GenericJMX' plugin.
[collectd.git] / bindings / java / org / collectd / java / GenericJMXConfValue.java
1 /*
2  * collectd/java - org/collectd/java/GenericJMXConfValue.java
3  * Copyright (C) 2009  Florian octo Forster
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; only version 2 of the License is applicable.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  *
18  * Authors:
19  *   Florian octo Forster <octo at verplant.org>
20  */
21
22 package org.collectd.java;
23
24 import java.util.List;
25 import java.util.Iterator;
26 import java.util.ArrayList;
27
28 import javax.management.MBeanServerConnection;
29 import javax.management.ObjectName;
30
31 import org.collectd.api.Collectd;
32 import org.collectd.api.DataSet;
33 import org.collectd.api.DataSource;
34 import org.collectd.api.ValueList;
35 import org.collectd.api.PluginData;
36 import org.collectd.api.OConfigValue;
37 import org.collectd.api.OConfigItem;
38
39 class GenericJMXConfValue
40 {
41   private String ds_name;
42   private DataSet ds;
43   private List<String> _attributes;
44   private String instance_prefix;
45
46   private Number genericObjectToNumber (Object obj, int ds_type) /* {{{ */
47   {
48     if (obj instanceof String)
49     {
50       String str = (String) obj;
51       
52       try
53       {
54         if (ds_type == DataSource.TYPE_GAUGE)
55           return (new Double (str));
56         else
57           return (new Long (str));
58       }
59       catch (NumberFormatException e)
60       {
61         return (null);
62       }
63     }
64     else if (obj instanceof Integer)
65     {
66       return (new Integer ((Integer) obj));
67     }
68     else if (obj instanceof Long)
69     {
70       return (new Long ((Long) obj));
71     }
72     else if (obj instanceof Double)
73     {
74       return (new Double ((Double) obj));
75     }
76
77     return (null);
78   } /* }}} Number genericObjectToNumber */
79
80   private Number queryAttribute (MBeanServerConnection conn, /* {{{ */
81       ObjectName objName, String attrName,
82       DataSource dsrc)
83   {
84     Object attrObj;
85
86     try
87     {
88       attrObj = conn.getAttribute (objName, attrName);
89     }
90     catch (Exception e)
91     {
92       Collectd.logError ("GenericJMXConfValue.query: getAttribute failed: "
93           + e);
94       return (null);
95     }
96
97     return (genericObjectToNumber (attrObj, dsrc.getType ()));
98   } /* }}} int queryAttribute */
99
100   private String getConfigString (OConfigItem ci) /* {{{ */
101   {
102     List<OConfigValue> values;
103     OConfigValue v;
104
105     values = ci.getValues ();
106     if (values.size () != 1)
107     {
108       Collectd.logError ("GenericJMXConfValue: The " + ci.getKey ()
109           + " configuration option needs exactly one string argument.");
110       return (null);
111     }
112
113     v = values.get (0);
114     if (v.getType () != OConfigValue.OCONFIG_TYPE_STRING)
115     {
116       Collectd.logError ("GenericJMXConfValue: The " + ci.getKey ()
117           + " configuration option needs exactly one string argument.");
118       return (null);
119     }
120
121     return (v.getString ());
122   } /* }}} String getConfigString */
123
124 /*
125  *    <Value>
126  *      Type "memory"
127  *      Attribute "HeapMemoryUsage"
128  *      # Type instance:
129  *      InstancePrefix "heap-"
130  *    </Value>
131  */
132   public GenericJMXConfValue (OConfigItem ci) /* {{{ */
133     throws IllegalArgumentException
134   {
135     List<OConfigItem> children;
136     Iterator<OConfigItem> iter;
137
138     this.ds_name = null;
139     this.ds = null;
140     this._attributes = new ArrayList<String> ();
141     this.instance_prefix = null;
142
143
144     children = ci.getChildren ();
145     iter = children.iterator ();
146     while (iter.hasNext ())
147     {
148       OConfigItem child = iter.next ();
149
150       if (child.getKey ().equalsIgnoreCase ("Type"))
151       {
152         String tmp = getConfigString (child);
153         if (tmp != null)
154           this.ds_name = tmp;
155       }
156       else if (child.getKey ().equalsIgnoreCase ("Attribute"))
157       {
158         String tmp = getConfigString (child);
159         if (tmp != null)
160           this._attributes.add (tmp);
161       }
162       else if (child.getKey ().equalsIgnoreCase ("InstancePrefix"))
163       {
164         String tmp = getConfigString (child);
165         if (tmp != null)
166           this.instance_prefix = tmp;
167       }
168       else
169         throw (new IllegalArgumentException ("Unknown option: "
170               + child.getKey ()));
171     }
172
173     if (this.ds_name == null)
174       throw (new IllegalArgumentException ("No data set was defined."));
175     else if (this._attributes.size () == 0)
176       throw (new IllegalArgumentException ("No attribute was defined."));
177   } /* }}} GenericJMXConfValue (OConfigItem ci) */
178
179   public void query (MBeanServerConnection conn, ObjectName objName, /* {{{ */
180       PluginData pd)
181   {
182     ValueList vl;
183     List<DataSource> dsrc;
184
185     if (this.ds == null)
186     {
187       this.ds = Collectd.getDS (this.ds_name);
188       if (ds == null)
189       {
190         Collectd.logError ("GenericJMXConfValue: Unknown type: "
191             + this.ds_name);
192         return;
193       }
194     }
195
196     dsrc = this.ds.getDataSources ();
197     if (dsrc.size () != this._attributes.size ())
198     {
199       Collectd.logError ("GenericJMXConfValue.query: The data set "
200           + ds_name + " has " + this.ds.getDataSources ().size ()
201           + " data sources, but there were " + this._attributes.size ()
202           + " attributes configured. This doesn't match!");
203       this.ds = null;
204       return;
205     }
206
207     vl = new ValueList (pd);
208     vl.setType (this.ds_name);
209     vl.setTypeInstance (this.instance_prefix);
210
211     assert (dsrc.size () == this._attributes.size ());
212     for (int i = 0; i < this._attributes.size (); i++)
213     {
214       Number v;
215
216       v = queryAttribute (conn, objName, this._attributes.get (i),
217           dsrc.get (i));
218       if (v == null)
219       {
220         Collectd.logError ("GenericJMXConfValue.query: "
221             + "Querying attribute " + this._attributes.get (i) + " failed.");
222         return;
223       }
224       Collectd.logDebug ("GenericJMXConfValue.query: dsrc[" + i + "]: v = " + v);
225       vl.addValue (v);
226     }
227
228     Collectd.dispatchValues (vl);
229   } /* }}} void query */
230 }
231
232 /* vim: set sw=2 sts=2 et fdm=marker : */