Merge branch 'ff/genericjmx'
[collectd.git] / bindings / java / org / collectd / java / GenericJMXConfMBean.java
1 /*
2  * collectd/java - org/collectd/java/GenericJMXConfMBean.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.Iterator;
25 import java.util.List;
26 import java.util.Set;
27 import java.util.ArrayList;
28
29 import javax.management.MBeanServerConnection;
30 import javax.management.ObjectName;
31 import javax.management.MalformedObjectNameException;
32
33 import org.collectd.api.Collectd;
34 import org.collectd.api.PluginData;
35 import org.collectd.api.OConfigValue;
36 import org.collectd.api.OConfigItem;
37
38 class GenericJMXConfMBean
39 {
40   private String _name; /* name by which this mapping is referenced */
41   private ObjectName _obj_name;
42   private String _instance_prefix;
43   private List<String> _instance_from;
44   private List<GenericJMXConfValue> _values;
45
46   private String getConfigString (OConfigItem ci) /* {{{ */
47   {
48     List<OConfigValue> values;
49     OConfigValue v;
50
51     values = ci.getValues ();
52     if (values.size () != 1)
53     {
54       Collectd.logError ("GenericJMXConfMBean: The " + ci.getKey ()
55           + " configuration option needs exactly one string argument.");
56       return (null);
57     }
58
59     v = values.get (0);
60     if (v.getType () != OConfigValue.OCONFIG_TYPE_STRING)
61     {
62       Collectd.logError ("GenericJMXConfMBean: The " + ci.getKey ()
63           + " configuration option needs exactly one string argument.");
64       return (null);
65     }
66
67     return (v.getString ());
68   } /* }}} String getConfigString */
69
70   private String join (String separator, List<String> list) /* {{{ */
71   {
72     StringBuffer sb;
73
74     sb = new StringBuffer ();
75
76     for (int i = 0; i < list.size (); i++)
77     {
78       if (i > 0)
79         sb.append ("-");
80       sb.append (list.get (i));
81     }
82
83     return (sb.toString ());
84   } /* }}} String join */
85
86 /*
87  * <MBean "alias name">
88  *   ObjectName "object name"
89  *   InstancePrefix "foobar"
90  *   InstanceFrom "name"
91  *   <Value />
92  *   <Value />
93  *   :
94  * </MBean>
95  */
96   public GenericJMXConfMBean (OConfigItem ci) /* {{{ */
97     throws IllegalArgumentException
98   {
99     List<OConfigItem> children;
100     Iterator<OConfigItem> iter;
101
102     this._name = getConfigString (ci);
103     if (this._name == null)
104       throw (new IllegalArgumentException ("No alias name was defined. "
105             + "MBean blocks need exactly one string argument."));
106
107     this._obj_name = null;
108     this._instance_prefix = null;
109     this._instance_from = new ArrayList<String> ();
110     this._values = new ArrayList<GenericJMXConfValue> ();
111
112     children = ci.getChildren ();
113     iter = children.iterator ();
114     while (iter.hasNext ())
115     {
116       OConfigItem child = iter.next ();
117
118       Collectd.logDebug ("GenericJMXConfMBean: child.getKey () = "
119           + child.getKey ());
120       if (child.getKey ().equalsIgnoreCase ("ObjectName"))
121       {
122         String tmp = getConfigString (child);
123         if (tmp == null)
124           continue;
125
126         try
127         {
128           this._obj_name = new ObjectName (tmp);
129         }
130         catch (MalformedObjectNameException e)
131         {
132           throw (new IllegalArgumentException ("Not a valid object name: "
133                 + tmp, e));
134         }
135       }
136       else if (child.getKey ().equalsIgnoreCase ("InstancePrefix"))
137       {
138         String tmp = getConfigString (child);
139         if (tmp != null)
140           this._instance_prefix = tmp;
141       }
142       else if (child.getKey ().equalsIgnoreCase ("InstanceFrom"))
143       {
144         String tmp = getConfigString (child);
145         if (tmp != null)
146           this._instance_from.add (tmp);
147       }
148       else if (child.getKey ().equalsIgnoreCase ("Value"))
149       {
150         GenericJMXConfValue cv;
151
152         cv = new GenericJMXConfValue (child);
153         this._values.add (cv);
154       }
155       else
156         throw (new IllegalArgumentException ("Unknown option: "
157               + child.getKey ()));
158     }
159
160     if (this._obj_name == null)
161       throw (new IllegalArgumentException ("No object name was defined."));
162
163     if (this._values.size () == 0)
164       throw (new IllegalArgumentException ("No value block was defined."));
165
166   } /* }}} GenericJMXConfMBean (OConfigItem ci) */
167
168   public String getName () /* {{{ */
169   {
170     return (this._name);
171   } /* }}} */
172
173   public void query (MBeanServerConnection conn, PluginData pd) /* {{{ */
174   {
175     Set<ObjectName> names;
176     Iterator<ObjectName> iter;
177
178     try
179     {
180       names = conn.queryNames (this._obj_name, /* query = */ null);
181     }
182     catch (Exception e)
183     {
184       Collectd.logError ("GenericJMXConfMBean: queryNames failed: " + e);
185       return;
186     }
187
188     if (names.size () == 0)
189     {
190       Collectd.logWarning ("GenericJMXConfMBean: No MBean matched "
191           + "the ObjectName " + this._obj_name);
192     }
193
194     iter = names.iterator ();
195     while (iter.hasNext ())
196     {
197       ObjectName   objName;
198       PluginData   pd_tmp;
199       List<String> instanceList;
200       String       instance;
201
202       objName      = iter.next ();
203       pd_tmp       = new PluginData (pd);
204       instanceList = new ArrayList<String> ();
205
206       Collectd.logDebug ("GenericJMXConfMBean: objName = "
207           + objName.toString ());
208
209       for (int i = 0; i < this._instance_from.size (); i++)
210       {
211         String propertyName;
212         String propertyValue;
213
214         propertyName = this._instance_from.get (i);
215         propertyValue = objName.getKeyProperty (propertyName);
216         if (propertyValue == null)
217         {
218           Collectd.logError ("GenericJMXConfMBean: "
219               + "No such property in object name: " + propertyName);
220         }
221         else
222         {
223           instanceList.add (propertyValue);
224         }
225       }
226
227       if (this._instance_prefix != null)
228         instance = new String (this._instance_prefix
229             + join ("-", instanceList));
230       else
231         instance = join ("-", instanceList);
232       pd_tmp.setPluginInstance (instance);
233
234       Collectd.logDebug ("GenericJMXConfMBean: instance = " + instance);
235
236       for (int i = 0; i < this._values.size (); i++)
237         this._values.get (i).query (conn, objName, pd_tmp);
238     }
239   } /* }}} void query */
240 }
241
242 /* vim: set sw=2 sts=2 et fdm=marker : */